summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/core
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2020-10-06 12:48:11 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2020-10-13 09:33:43 +0000
commit7b5b123ac58f58ffde0f4f6e488bcd09aa4decd3 (patch)
treefa14ba0ca8d2683ba2efdabd246dc9b18a1229c6 /chromium/third_party/blink/renderer/core
parent79b4f909db1049fca459c07cca55af56a9b54fe3 (diff)
downloadqtwebengine-chromium-7b5b123ac58f58ffde0f4f6e488bcd09aa4decd3.tar.gz
BASELINE: Update Chromium to 84.0.4147.141
Change-Id: Ib85eb4cfa1cbe2b2b81e5022c8cad5c493969535 Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/third_party/blink/renderer/core')
-rw-r--r--chromium/third_party/blink/renderer/core/BUILD.gn32
-rw-r--r--chromium/third_party/blink/renderer/core/DEPS15
-rw-r--r--chromium/third_party/blink/renderer/core/accessibility/BUILD.gn14
-rw-r--r--chromium/third_party/blink/renderer/core/accessibility/OWNERS4
-rw-r--r--chromium/third_party/blink/renderer/core/accessibility/ax_object_cache.h23
-rw-r--r--chromium/third_party/blink/renderer/core/accessibility/blink_ax_event_intent.cc229
-rw-r--r--chromium/third_party/blink/renderer/core/accessibility/blink_ax_event_intent.h111
-rw-r--r--chromium/third_party/blink/renderer/core/accessibility/blink_ax_event_intent_test.cc71
-rw-r--r--chromium/third_party/blink/renderer/core/accessibility/scoped_blink_ax_event_intent.cc63
-rw-r--r--chromium/third_party/blink/renderer/core/accessibility/scoped_blink_ax_event_intent.h54
-rw-r--r--chromium/third_party/blink/renderer/core/accessibility/scoped_blink_ax_event_intent_test.cc199
-rw-r--r--chromium/third_party/blink/renderer/core/animation/BUILD.gn7
-rw-r--r--chromium/third_party/blink/renderer/core/animation/OWNERS1
-rw-r--r--chromium/third_party/blink/renderer/core/animation/animation.cc470
-rw-r--r--chromium/third_party/blink/renderer/core/animation/animation.h33
-rw-r--r--chromium/third_party/blink/renderer/core/animation/animation.idl6
-rw-r--r--chromium/third_party/blink/renderer/core/animation/animation_sim_test.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/animation/animation_test.cc308
-rw-r--r--chromium/third_party/blink/renderer/core/animation/animation_test_helper.cc25
-rw-r--r--chromium/third_party/blink/renderer/core/animation/animation_test_helper.h9
-rw-r--r--chromium/third_party/blink/renderer/core/animation/animation_timeline.cc22
-rw-r--r--chromium/third_party/blink/renderer/core/animation/animation_timeline.h11
-rw-r--r--chromium/third_party/blink/renderer/core/animation/animation_timeline.idl3
-rw-r--r--chromium/third_party/blink/renderer/core/animation/animation_utils.cc56
-rw-r--r--chromium/third_party/blink/renderer/core/animation/animation_utils.h36
-rw-r--r--chromium/third_party/blink/renderer/core/animation/animation_utils_test.cc117
-rw-r--r--chromium/third_party/blink/renderer/core/animation/compositor_animations_test.cc24
-rw-r--r--chromium/third_party/blink/renderer/core/animation/css/css_animation.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/animation/css/css_animation.h9
-rw-r--r--chromium/third_party/blink/renderer/core/animation/css/css_animation_update.h8
-rw-r--r--chromium/third_party/blink/renderer/core/animation/css/css_animations.cc332
-rw-r--r--chromium/third_party/blink/renderer/core/animation/css/css_animations.h6
-rw-r--r--chromium/third_party/blink/renderer/core/animation/css/css_keyframe_effect_model.cc122
-rw-r--r--chromium/third_party/blink/renderer/core/animation/css/css_keyframe_effect_model.h42
-rw-r--r--chromium/third_party/blink/renderer/core/animation/css/css_transition.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/animation/css/css_transition.h3
-rw-r--r--chromium/third_party/blink/renderer/core/animation/css_interpolation_environment.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/animation/css_interpolation_type.cc114
-rw-r--r--chromium/third_party/blink/renderer/core/animation/css_interpolation_types_map.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/animation/css_var_cycle_interpolation_type.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/animation/document_animations.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/animation/document_animations.h7
-rw-r--r--chromium/third_party/blink/renderer/core/animation/document_animations_test.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/animation/document_timeline.cc13
-rw-r--r--chromium/third_party/blink/renderer/core/animation/document_timeline.h8
-rw-r--r--chromium/third_party/blink/renderer/core/animation/document_timeline_test.cc19
-rw-r--r--chromium/third_party/blink/renderer/core/animation/effect_stack.cc24
-rw-r--r--chromium/third_party/blink/renderer/core/animation/effect_stack.h4
-rw-r--r--chromium/third_party/blink/renderer/core/animation/effect_stack_test.cc59
-rw-r--r--chromium/third_party/blink/renderer/core/animation/element_animations.cc28
-rw-r--r--chromium/third_party/blink/renderer/core/animation/element_animations.h36
-rw-r--r--chromium/third_party/blink/renderer/core/animation/keyframe.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/animation/keyframe.h6
-rw-r--r--chromium/third_party/blink/renderer/core/animation/keyframe_effect.cc15
-rw-r--r--chromium/third_party/blink/renderer/core/animation/keyframe_effect.h1
-rw-r--r--chromium/third_party/blink/renderer/core/animation/keyframe_effect_model.cc48
-rw-r--r--chromium/third_party/blink/renderer/core/animation/keyframe_effect_model.h15
-rw-r--r--chromium/third_party/blink/renderer/core/animation/keyframe_effect_test.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/animation/pending_animations.cc46
-rw-r--r--chromium/third_party/blink/renderer/core/animation/pending_animations.h6
-rw-r--r--chromium/third_party/blink/renderer/core/animation/scroll_timeline.cc184
-rw-r--r--chromium/third_party/blink/renderer/core/animation/scroll_timeline.h66
-rw-r--r--chromium/third_party/blink/renderer/core/animation/scroll_timeline.idl5
-rw-r--r--chromium/third_party/blink/renderer/core/animation/scroll_timeline_element_based_offset.idl16
-rw-r--r--chromium/third_party/blink/renderer/core/animation/scroll_timeline_offset.cc208
-rw-r--r--chromium/third_party/blink/renderer/core/animation/scroll_timeline_offset.h63
-rw-r--r--chromium/third_party/blink/renderer/core/animation/scroll_timeline_options.idl5
-rw-r--r--chromium/third_party/blink/renderer/core/animation/scroll_timeline_test.cc271
-rw-r--r--chromium/third_party/blink/renderer/core/animation/scroll_timeline_util.cc17
-rw-r--r--chromium/third_party/blink/renderer/core/animation/scroll_timeline_util_test.cc20
-rw-r--r--chromium/third_party/blink/renderer/core/animation/string_keyframe.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/animation/string_keyframe.h8
-rw-r--r--chromium/third_party/blink/renderer/core/animation/timing_calculations.h47
-rw-r--r--chromium/third_party/blink/renderer/core/animation/timing_input_test.cc66
-rw-r--r--chromium/third_party/blink/renderer/core/animation/transition_keyframe.cc37
-rw-r--r--chromium/third_party/blink/renderer/core/animation/transition_keyframe.h4
-rw-r--r--chromium/third_party/blink/renderer/core/animation_frame/worker_animation_frame_provider.cc17
-rw-r--r--chromium/third_party/blink/renderer/core/animation_frame/worker_animation_frame_provider.h11
-rw-r--r--chromium/third_party/blink/renderer/core/aom/accessible_node.cc348
-rw-r--r--chromium/third_party/blink/renderer/core/aom/accessible_node.h88
-rw-r--r--chromium/third_party/blink/renderer/core/aom/accessible_node.idl1
-rw-r--r--chromium/third_party/blink/renderer/core/aom/accessible_node_list.idl1
-rw-r--r--chromium/third_party/blink/renderer/core/aom/computed_accessible_node.cc123
-rw-r--r--chromium/third_party/blink/renderer/core/aom/computed_accessible_node.h30
-rw-r--r--chromium/third_party/blink/renderer/core/aom/computed_accessible_node.idl1
-rw-r--r--chromium/third_party/blink/renderer/core/clipboard/raw_system_clipboard.cc24
-rw-r--r--chromium/third_party/blink/renderer/core/clipboard/raw_system_clipboard.h17
-rw-r--r--chromium/third_party/blink/renderer/core/clipboard/system_clipboard.cc20
-rw-r--r--chromium/third_party/blink/renderer/core/clipboard/system_clipboard.h9
-rw-r--r--chromium/third_party/blink/renderer/core/content_capture/content_capture_task.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/content_capture/content_capture_test.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/core_idl_files.gni14
-rw-r--r--chromium/third_party/blink/renderer/core/core_initializer.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/core_initializer.h4
-rw-r--r--chromium/third_party/blink/renderer/core/css/BUILD.gn20
-rw-r--r--chromium/third_party/blink/renderer/core/css/active_style_sheets_test.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/css/computed_style_css_value_mapping.cc41
-rw-r--r--chromium/third_party/blink/renderer/core/css/computed_style_css_value_mapping.h2
-rw-r--r--chromium/third_party/blink/renderer/core/css/computed_style_css_value_mapping_test.cc41
-rw-r--r--chromium/third_party/blink/renderer/core/css/css.dict4
-rw-r--r--chromium/third_party/blink/renderer/core/css/css.idl1
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_computed_style_declaration.cc232
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_crossfade_value.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_custom_property_declaration.h5
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_default_style_sheets.cc12
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_default_style_sheets.h4
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_font_face.cc11
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_font_face.h5
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_font_face_rule.idl4
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_font_face_source.h4
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_font_face_src_value.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_font_face_src_value.h17
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_font_selector.cc12
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_font_selector.h4
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_image_set_value.cc11
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_image_set_value.h5
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_image_value.cc18
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_image_value.h12
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_light_dark_color_pair_test.cc42
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_light_dark_value_pair.cc (renamed from chromium/third_party/blink/renderer/core/css/css_light_dark_color_pair.cc)6
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_light_dark_value_pair.h (renamed from chromium/third_party/blink/renderer/core/css/css_light_dark_color_pair.h)16
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_light_dark_value_pair_test.cc65
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_math_expression_node.cc49
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_math_expression_node.h11
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_properties.json5201
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_properties_ranking.json52
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_property_rule.cc75
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_property_rule.h8
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_property_rule.idl6
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_revert_value.cc24
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_revert_value.h44
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_revert_value_test.cc36
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_rule.idl4
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_segmented_font_face.cc247
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_segmented_font_face.h51
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_style_declaration_test.cc60
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_style_sheet.cc50
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_style_sheet.h9
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_syntax_definition.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_syntax_definition.h4
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_syntax_string_parser.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_syntax_string_parser_test.cc11
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_test_helpers.cc26
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_test_helpers.h11
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_value.cc29
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_value.h10
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_value_id_mappings.h13
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_value_keywords.json524
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_value_pool.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_value_pool.h4
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_viewport_rule.cc84
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_viewport_rule.h74
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_viewport_rule.idl37
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/computed_style_property_map.cc30
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/css_keyword_value.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/style_property_map_test.cc100
-rw-r--r--chromium/third_party/blink/renderer/core/css/font_display_auto_lcp_align_test.cc393
-rw-r--r--chromium/third_party/blink/renderer/core/css/font_face.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/css/font_face_cache_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/css/font_face_set.cc11
-rw-r--r--chromium/third_party/blink/renderer/core/css/font_face_set.h6
-rw-r--r--chromium/third_party/blink/renderer/core/css/font_face_set_document.cc79
-rw-r--r--chromium/third_party/blink/renderer/core/css/font_face_set_document.h35
-rw-r--r--chromium/third_party/blink/renderer/core/css/font_face_set_worker.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/css/font_update_invalidation_test.cc141
-rw-r--r--chromium/third_party/blink/renderer/core/css/invalidation/pending_invalidations.cc16
-rw-r--r--chromium/third_party/blink/renderer/core/css/local_font_face_source.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/css/mathml.css20
-rw-r--r--chromium/third_party/blink/renderer/core/css/media_feature_names.json51
-rw-r--r--chromium/third_party/blink/renderer/core/css/media_query_evaluator.cc21
-rw-r--r--chromium/third_party/blink/renderer/core/css/media_query_evaluator_test.cc56
-rw-r--r--chromium/third_party/blink/renderer/core/css/media_query_exp.cc12
-rw-r--r--chromium/third_party/blink/renderer/core/css/media_query_set_test.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/css/media_values.cc21
-rw-r--r--chromium/third_party/blink/renderer/core/css/media_values.h3
-rw-r--r--chromium/third_party/blink/renderer/core/css/media_values_cached.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/css/media_values_cached.h3
-rw-r--r--chromium/third_party/blink/renderer/core/css/media_values_dynamic.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/css/media_values_dynamic.h1
-rw-r--r--chromium/third_party/blink/renderer/core/css/offscreen_font_selector.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/css/offscreen_font_selector.h2
-rw-r--r--chromium/third_party/blink/renderer/core/css/parser/at_rule_descriptor_parser.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/css/parser/css_parser_context.cc11
-rw-r--r--chromium/third_party/blink/renderer/core/css/parser/css_parser_context.h8
-rw-r--r--chromium/third_party/blink/renderer/core/css/parser/css_parser_fast_paths.cc36
-rw-r--r--chromium/third_party/blink/renderer/core/css/parser/css_parser_fast_paths_test.cc41
-rw-r--r--chromium/third_party/blink/renderer/core/css/parser/css_parser_impl.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/css/parser/css_property_parser.cc11
-rw-r--r--chromium/third_party/blink/renderer/core/css/parser/css_property_parser_helpers.cc110
-rw-r--r--chromium/third_party/blink/renderer/core/css/parser/css_property_parser_helpers.h3
-rw-r--r--chromium/third_party/blink/renderer/core/css/parser/css_property_parser_helpers_test.cc25
-rw-r--r--chromium/third_party/blink/renderer/core/css/parser/css_property_parser_test.cc142
-rw-r--r--chromium/third_party/blink/renderer/core/css/parser/css_variable_parser.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/README.md17
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/computed_style_utils.cc216
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/computed_style_utils.h51
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/computed_style_utils_test.cc44
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/css_bitset.h165
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/css_bitset_test.cc311
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/css_parsing_utils.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/css_parsing_utils.h2
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/css_parsing_utils_test.cc13
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/css_property.h20
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/css_property_test.cc140
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/longhands/custom_property.cc28
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/longhands/custom_property.h3
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/longhands/custom_property_test.cc40
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc161
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/longhands/variable.h5
-rw-r--r--chromium/third_party/blink/renderer/core/css/property_registration.cc60
-rw-r--r--chromium/third_party/blink/renderer/core/css/property_registration.h8
-rw-r--r--chromium/third_party/blink/renderer/core/css/property_registration.idl2
-rw-r--r--chromium/third_party/blink/renderer/core/css/property_registry.cc89
-rw-r--r--chromium/third_party/blink/renderer/core/css/property_registry.h76
-rw-r--r--chromium/third_party/blink/renderer/core/css/property_registry_test.cc316
-rw-r--r--chromium/third_party/blink/renderer/core/css/remote_font_face_source.cc73
-rw-r--r--chromium/third_party/blink/renderer/core/css/remote_font_face_source.h6
-rw-r--r--chromium/third_party/blink/renderer/core/css/resolver/cascade_interpolations.h34
-rw-r--r--chromium/third_party/blink/renderer/core/css/resolver/cascade_interpolations_test.cc37
-rw-r--r--chromium/third_party/blink/renderer/core/css/resolver/cascade_map.cc142
-rw-r--r--chromium/third_party/blink/renderer/core/css/resolver/cascade_map.h51
-rw-r--r--chromium/third_party/blink/renderer/core/css/resolver/cascade_map_test.cc61
-rw-r--r--chromium/third_party/blink/renderer/core/css/resolver/cascade_resolver.h12
-rw-r--r--chromium/third_party/blink/renderer/core/css/resolver/css_property_priority.h2
-rw-r--r--chromium/third_party/blink/renderer/core/css/resolver/css_to_style_map.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/css/resolver/css_variable_resolver.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/css/resolver/css_variable_resolver_test.cc11
-rw-r--r--chromium/third_party/blink/renderer/core/css/resolver/element_style_resources.cc39
-rw-r--r--chromium/third_party/blink/renderer/core/css/resolver/element_style_resources.h2
-rw-r--r--chromium/third_party/blink/renderer/core/css/resolver/matched_properties_cache.cc79
-rw-r--r--chromium/third_party/blink/renderer/core/css/resolver/matched_properties_cache.h42
-rw-r--r--chromium/third_party/blink/renderer/core/css/resolver/matched_properties_cache_test.cc247
-rw-r--r--chromium/third_party/blink/renderer/core/css/resolver/style_adjuster.cc20
-rw-r--r--chromium/third_party/blink/renderer/core/css/resolver/style_builder_converter.cc75
-rw-r--r--chromium/third_party/blink/renderer/core/css/resolver/style_builder_converter.h57
-rw-r--r--chromium/third_party/blink/renderer/core/css/resolver/style_builder_test.cc74
-rw-r--r--chromium/third_party/blink/renderer/core/css/resolver/style_cascade.cc319
-rw-r--r--chromium/third_party/blink/renderer/core/css/resolver/style_cascade.h42
-rw-r--r--chromium/third_party/blink/renderer/core/css/resolver/style_cascade_test.cc973
-rw-r--r--chromium/third_party/blink/renderer/core/css/resolver/style_resolver.cc164
-rw-r--r--chromium/third_party/blink/renderer/core/css/resolver/style_resolver.h8
-rw-r--r--chromium/third_party/blink/renderer/core/css/resolver/style_resolver_state.cc14
-rw-r--r--chromium/third_party/blink/renderer/core/css/resolver/style_resolver_state.h22
-rw-r--r--chromium/third_party/blink/renderer/core/css/resolver/style_resolver_test.cc163
-rw-r--r--chromium/third_party/blink/renderer/core/css/resolver/viewport_style_resolver.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/css/selector_checker.cc11
-rw-r--r--chromium/third_party/blink/renderer/core/css/style_engine.cc112
-rw-r--r--chromium/third_party/blink/renderer/core/css/style_engine.h9
-rw-r--r--chromium/third_party/blink/renderer/core/css/style_engine_test.cc30
-rw-r--r--chromium/third_party/blink/renderer/core/css/style_property_serializer.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/css/style_recalc.h25
-rw-r--r--chromium/third_party/blink/renderer/core/css/style_recalc_root.cc48
-rw-r--r--chromium/third_party/blink/renderer/core/css/style_rule.cc18
-rw-r--r--chromium/third_party/blink/renderer/core/css/style_rule.h3
-rw-r--r--chromium/third_party/blink/renderer/core/css/style_rule_import.cc22
-rw-r--r--chromium/third_party/blink/renderer/core/css/style_sheet_contents_test.cc45
-rw-r--r--chromium/third_party/blink/renderer/core/css/svg.css2
-rw-r--r--chromium/third_party/blink/renderer/core/css/vision_deficiency.cc22
-rw-r--r--chromium/third_party/blink/renderer/core/display_lock/BUILD.gn2
-rw-r--r--chromium/third_party/blink/renderer/core/display_lock/display_lock_context.cc176
-rw-r--r--chromium/third_party/blink/renderer/core/display_lock/display_lock_context.h52
-rw-r--r--chromium/third_party/blink/renderer/core/display_lock/display_lock_context_test.cc770
-rw-r--r--chromium/third_party/blink/renderer/core/display_lock/display_lock_document_state.cc209
-rw-r--r--chromium/third_party/blink/renderer/core/display_lock/display_lock_document_state.h161
-rw-r--r--chromium/third_party/blink/renderer/core/display_lock/display_lock_utilities.cc258
-rw-r--r--chromium/third_party/blink/renderer/core/display_lock/display_lock_utilities.h92
-rw-r--r--chromium/third_party/blink/renderer/core/display_lock/display_lock_utilities_test.cc41
-rw-r--r--chromium/third_party/blink/renderer/core/display_lock/render_subtree_activation_event.idl3
-rw-r--r--chromium/third_party/blink/renderer/core/dom/aria_attributes.idl3
-rw-r--r--chromium/third_party/blink/renderer/core/dom/container_node.cc12
-rw-r--r--chromium/third_party/blink/renderer/core/dom/container_node.h2
-rw-r--r--chromium/third_party/blink/renderer/core/dom/decoded_data_document_parser.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/dom/document.cc636
-rw-r--r--chromium/third_party/blink/renderer/core/dom/document.h247
-rw-r--r--chromium/third_party/blink/renderer/core/dom/document.idl3
-rw-r--r--chromium/third_party/blink/renderer/core/dom/document_fragment.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/dom/document_init.cc190
-rw-r--r--chromium/third_party/blink/renderer/core/dom/document_init.h35
-rw-r--r--chromium/third_party/blink/renderer/core/dom/document_lifecycle.h6
-rw-r--r--chromium/third_party/blink/renderer/core/dom/document_test.cc259
-rw-r--r--chromium/third_party/blink/renderer/core/dom/dom_implementation.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/dom/element.cc579
-rw-r--r--chromium/third_party/blink/renderer/core/dom/element.h59
-rw-r--r--chromium/third_party/blink/renderer/core/dom/element.idl5
-rw-r--r--chromium/third_party/blink/renderer/core/dom/element_data.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/dom/element_data.h12
-rw-r--r--chromium/third_party/blink/renderer/core/dom/events/custom_event.cc14
-rw-r--r--chromium/third_party/blink/renderer/core/dom/events/event_target.cc15
-rw-r--r--chromium/third_party/blink/renderer/core/dom/events/listener_leak_test.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/dom/get_inner_html_options.idl7
-rw-r--r--chromium/third_party/blink/renderer/core/dom/global_event_handlers.h1
-rw-r--r--chromium/third_party/blink/renderer/core/dom/global_event_handlers.idl6
-rw-r--r--chromium/third_party/blink/renderer/core/dom/idle_deadline.h7
-rw-r--r--chromium/third_party/blink/renderer/core/dom/layout_tree_builder_traversal.cc30
-rw-r--r--chromium/third_party/blink/renderer/core/dom/live_node_list_registry.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/dom/live_node_list_registry.h8
-rw-r--r--chromium/third_party/blink/renderer/core/dom/node.cc88
-rw-r--r--chromium/third_party/blink/renderer/core/dom/node.h10
-rw-r--r--chromium/third_party/blink/renderer/core/dom/node_test.cc15
-rw-r--r--chromium/third_party/blink/renderer/core/dom/presentation_attribute_style.cc98
-rw-r--r--chromium/third_party/blink/renderer/core/dom/presentation_attribute_style.h2
-rw-r--r--chromium/third_party/blink/renderer/core/dom/processing_instruction.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/dom/scripted_idle_task_controller.cc49
-rw-r--r--chromium/third_party/blink/renderer/core/dom/scripted_idle_task_controller.h25
-rw-r--r--chromium/third_party/blink/renderer/core/dom/shadow_root.cc17
-rw-r--r--chromium/third_party/blink/renderer/core/dom/shadow_root.h15
-rw-r--r--chromium/third_party/blink/renderer/core/dom/shadow_root_v0.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/dom/slot_assignment.cc70
-rw-r--r--chromium/third_party/blink/renderer/core/dom/slot_assignment.h7
-rw-r--r--chromium/third_party/blink/renderer/core/dom/text_link_colors.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/dom/v0_insertion_point.cc25
-rw-r--r--chromium/third_party/blink/renderer/core/dom/v0_insertion_point.h1
-rw-r--r--chromium/third_party/blink/renderer/core/editing/commands/apply_style_command.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/editing/commands/composite_edit_command.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/editing/commands/insert_text_command.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/editing/commands/style_commands.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/editing/dom_selection.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/editing/editing_behavior.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/editing/editing_style.cc33
-rw-r--r--chromium/third_party/blink/renderer/core/editing/editor.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/editing/editor_key_bindings.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/editing/finder/find_buffer.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/editing/finder/find_task_controller.cc102
-rw-r--r--chromium/third_party/blink/renderer/core/editing/finder/find_task_controller.h30
-rw-r--r--chromium/third_party/blink/renderer/core/editing/finder/text_finder.cc57
-rw-r--r--chromium/third_party/blink/renderer/core/editing/finder/text_finder_test.cc106
-rw-r--r--chromium/third_party/blink/renderer/core/editing/frame_selection.cc41
-rw-r--r--chromium/third_party/blink/renderer/core/editing/frame_selection.h7
-rw-r--r--chromium/third_party/blink/renderer/core/editing/frame_selection_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/editing/ime/edit_context.cc18
-rw-r--r--chromium/third_party/blink/renderer/core/editing/ime/input_method_controller.cc32
-rw-r--r--chromium/third_party/blink/renderer/core/editing/ime/input_method_controller.h11
-rw-r--r--chromium/third_party/blink/renderer/core/editing/iterators/text_iterator_behavior.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/editing/iterators/text_iterator_behavior.h5
-rw-r--r--chromium/third_party/blink/renderer/core/editing/iterators/text_iterator_behavior_test.cc28
-rw-r--r--chromium/third_party/blink/renderer/core/editing/iterators/text_iterator_test.cc39
-rw-r--r--chromium/third_party/blink/renderer/core/editing/iterators/text_iterator_text_node_handler.cc16
-rw-r--r--chromium/third_party/blink/renderer/core/editing/keyboard_test.cc15
-rw-r--r--chromium/third_party/blink/renderer/core/editing/link_selection_test.cc35
-rw-r--r--chromium/third_party/blink/renderer/core/editing/markers/document_marker_controller.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/editing/markers/document_marker_controller.h2
-rw-r--r--chromium/third_party/blink/renderer/core/editing/selection_controller.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/editing/selection_controller_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/editing/selection_modifier.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/editing/selection_modifier.h3
-rw-r--r--chromium/third_party/blink/renderer/core/editing/selection_modifier_line.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/editing/serializers/markup_accumulator.cc16
-rw-r--r--chromium/third_party/blink/renderer/core/editing/serializers/serialization.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/editing/spellcheck/cold_mode_spell_check_requester.cc14
-rw-r--r--chromium/third_party/blink/renderer/core/editing/spellcheck/cold_mode_spell_check_requester.h9
-rw-r--r--chromium/third_party/blink/renderer/core/editing/spellcheck/idle_spell_check_controller.cc76
-rw-r--r--chromium/third_party/blink/renderer/core/editing/spellcheck/idle_spell_check_controller.h29
-rw-r--r--chromium/third_party/blink/renderer/core/editing/spellcheck/spell_check_requester.cc31
-rw-r--r--chromium/third_party/blink/renderer/core/editing/spellcheck/spell_check_requester.h16
-rw-r--r--chromium/third_party/blink/renderer/core/editing/spellcheck/spell_checker.cc25
-rw-r--r--chromium/third_party/blink/renderer/core/editing/spellcheck/spell_checker.h13
-rw-r--r--chromium/third_party/blink/renderer/core/editing/suggestion/text_suggestion_controller.cc29
-rw-r--r--chromium/third_party/blink/renderer/core/editing/suggestion/text_suggestion_controller.h24
-rw-r--r--chromium/third_party/blink/renderer/core/editing/suggestion/text_suggestion_controller_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/editing/visible_position_test.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/editing/visible_units_line.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/editing/web_substring_util.mm2
-rw-r--r--chromium/third_party/blink/renderer/core/events/animation_playback_event.cc10
-rw-r--r--chromium/third_party/blink/renderer/core/events/animation_playback_event.h3
-rw-r--r--chromium/third_party/blink/renderer/core/events/application_cache_error_event.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/events/application_cache_error_event.idl1
-rw-r--r--chromium/third_party/blink/renderer/core/events/error_event.cc23
-rw-r--r--chromium/third_party/blink/renderer/core/events/error_event_init.idl10
-rw-r--r--chromium/third_party/blink/renderer/core/events/event_type_names.json55
-rw-r--r--chromium/third_party/blink/renderer/core/events/gesture_event.cc28
-rw-r--r--chromium/third_party/blink/renderer/core/events/keyboard_event.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/events/message_event.cc14
-rw-r--r--chromium/third_party/blink/renderer/core/events/message_event_init.idl8
-rw-r--r--chromium/third_party/blink/renderer/core/events/message_event_test.cc12
-rw-r--r--chromium/third_party/blink/renderer/core/events/mutation_event.idl4
-rw-r--r--chromium/third_party/blink/renderer/core/events/overscroll_event.idl1
-rw-r--r--chromium/third_party/blink/renderer/core/events/pointer_event.idl2
-rw-r--r--chromium/third_party/blink/renderer/core/events/pointer_event_factory.cc40
-rw-r--r--chromium/third_party/blink/renderer/core/events/pointer_event_factory_test.cc46
-rw-r--r--chromium/third_party/blink/renderer/core/events/pointer_event_init.idl2
-rw-r--r--chromium/third_party/blink/renderer/core/events/pop_state_event.cc74
-rw-r--r--chromium/third_party/blink/renderer/core/events/pop_state_event.h39
-rw-r--r--chromium/third_party/blink/renderer/core/events/pop_state_event.idl2
-rw-r--r--chromium/third_party/blink/renderer/core/events/pop_state_event_init.idl2
-rw-r--r--chromium/third_party/blink/renderer/core/events/security_policy_violation_event_init.idl21
-rw-r--r--chromium/third_party/blink/renderer/core/events/text_event.idl4
-rw-r--r--chromium/third_party/blink/renderer/core/events/touch_event.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/events/touch_event.h2
-rw-r--r--chromium/third_party/blink/renderer/core/events/touch_event_test.cc12
-rw-r--r--chromium/third_party/blink/renderer/core/events/web_input_event_conversion.cc37
-rw-r--r--chromium/third_party/blink/renderer/core/events/web_input_event_conversion.h14
-rw-r--r--chromium/third_party/blink/renderer/core/events/web_input_event_conversion_test.cc76
-rw-r--r--chromium/third_party/blink/renderer/core/execution_context/agent_metrics_collector.cc14
-rw-r--r--chromium/third_party/blink/renderer/core/execution_context/agent_metrics_collector.h8
-rw-r--r--chromium/third_party/blink/renderer/core/execution_context/execution_context.cc37
-rw-r--r--chromium/third_party/blink/renderer/core/execution_context/execution_context.h24
-rw-r--r--chromium/third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.cc45
-rw-r--r--chromium/third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.h58
-rw-r--r--chromium/third_party/blink/renderer/core/execution_context/execution_context_lifecycle_state_observer.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/execution_context/execution_context_lifecycle_state_observer.h3
-rw-r--r--chromium/third_party/blink/renderer/core/execution_context/execution_context_lifecycle_state_observer_test.cc51
-rw-r--r--chromium/third_party/blink/renderer/core/execution_context/remote_security_context.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/execution_context/remote_security_context.h4
-rw-r--r--chromium/third_party/blink/renderer/core/execution_context/security_context.cc51
-rw-r--r--chromium/third_party/blink/renderer/core/execution_context/security_context.h21
-rw-r--r--chromium/third_party/blink/renderer/core/execution_context/security_context_init.cc128
-rw-r--r--chromium/third_party/blink/renderer/core/execution_context/security_context_init.h7
-rw-r--r--chromium/third_party/blink/renderer/core/exported/BUILD.gn2
-rw-r--r--chromium/third_party/blink/renderer/core/exported/local_frame_client_impl.cc83
-rw-r--r--chromium/third_party/blink/renderer/core/exported/local_frame_client_impl.h12
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_console_message.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_dev_tools_agent_impl.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_document.cc15
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_document_loader_impl.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_document_test.cc20
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_dom_message_event.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_element.cc18
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_element_test.cc56
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_external_widget_impl.cc48
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_external_widget_impl.h17
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_form_control_element.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_form_element.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_form_element_observer_impl.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_frame.cc10
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_frame_content_dumper.cc11
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_frame_serializer_sanitization_test.cc26
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_frame_test.cc400
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_hit_test_result.cc10
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_page_popup_impl.cc96
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_page_popup_impl.h27
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_plugin_container_impl.cc54
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_plugin_container_impl.h2
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_plugin_container_test.cc136
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_remote_frame_impl.cc62
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_remote_frame_impl.h46
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_scoped_window_focus_allowed_indicator.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_scoped_window_focus_allowed_indicator_test.cc16
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_searchable_form_data_test.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_settings_impl.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_settings_impl.h5
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_shared_worker_impl.cc17
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_shared_worker_impl.h2
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_view_impl.cc351
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_view_impl.h57
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_view_test.cc753
-rw-r--r--chromium/third_party/blink/renderer/core/feature_policy/BUILD.gn2
-rw-r--r--chromium/third_party/blink/renderer/core/feature_policy/document_policy_features.json59
-rw-r--r--chromium/third_party/blink/renderer/core/feature_policy/document_policy_fuzzer.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/feature_policy/document_policy_parser.cc223
-rw-r--r--chromium/third_party/blink/renderer/core/feature_policy/document_policy_parser.h10
-rw-r--r--chromium/third_party/blink/renderer/core/feature_policy/document_policy_parser_test.cc502
-rw-r--r--chromium/third_party/blink/renderer/core/feature_policy/dom_feature_policy.cc29
-rw-r--r--chromium/third_party/blink/renderer/core/feature_policy/feature_policy_features.json521
-rw-r--r--chromium/third_party/blink/renderer/core/feature_policy/feature_policy_parser.cc689
-rw-r--r--chromium/third_party/blink/renderer/core/feature_policy/feature_policy_parser.h12
-rw-r--r--chromium/third_party/blink/renderer/core/feature_policy/feature_policy_test.cc296
-rw-r--r--chromium/third_party/blink/renderer/core/feature_policy/feature_policy_value.dict10
-rw-r--r--chromium/third_party/blink/renderer/core/feature_policy/feature_policy_value_corpus/11
-rw-r--r--chromium/third_party/blink/renderer/core/feature_policy/feature_policy_value_corpus/21
-rw-r--r--chromium/third_party/blink/renderer/core/feature_policy/feature_policy_value_corpus/31
-rw-r--r--chromium/third_party/blink/renderer/core/feature_policy/feature_policy_value_corpus/41
-rw-r--r--chromium/third_party/blink/renderer/core/feature_policy/feature_policy_value_corpus/51
-rw-r--r--chromium/third_party/blink/renderer/core/feature_policy/feature_policy_value_corpus/61
-rw-r--r--chromium/third_party/blink/renderer/core/feature_policy/feature_policy_value_fuzzer.cc25
-rw-r--r--chromium/third_party/blink/renderer/core/feature_policy/layout_animations_policy.cc13
-rw-r--r--chromium/third_party/blink/renderer/core/feature_policy/policy_helper.h (renamed from chromium/third_party/blink/renderer/core/feature_policy/feature_policy_helper.h)58
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/BUILD.gn2
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/DEPS3
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/body.h15
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/fetch_header_list.cc17
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/fetch_header_list.h1
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/fetch_manager.cc77
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/fetch_request_data.cc19
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/fetch_request_data.h14
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/fetch_response_data.cc139
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/fetch_response_data.h10
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/fetch_response_data_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/request.cc125
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/request.h10
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/request_init.idl6
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/request_test.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/response.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/response.h5
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/trust_token_issuance_authorization.cc18
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/trust_token_issuance_authorization.h24
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/trust_token_to_mojom.cc24
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/trust_token_to_mojom.h11
-rw-r--r--chromium/third_party/blink/renderer/core/fileapi/file_reader.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/fileapi/public_url_manager.cc32
-rw-r--r--chromium/third_party/blink/renderer/core/fileapi/public_url_manager.h5
-rw-r--r--chromium/third_party/blink/renderer/core/fileapi/public_url_manager_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/frame/BUILD.gn6
-rw-r--r--chromium/third_party/blink/renderer/core/frame/DEPS3
-rw-r--r--chromium/third_party/blink/renderer/core/frame/ad_tracker.cc49
-rw-r--r--chromium/third_party/blink/renderer/core/frame/ad_tracker.h21
-rw-r--r--chromium/third_party/blink/renderer/core/frame/ad_tracker_test.cc554
-rw-r--r--chromium/third_party/blink/renderer/core/frame/bar_prop.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/frame/bar_prop.h2
-rw-r--r--chromium/third_party/blink/renderer/core/frame/browser_controls_test.cc188
-rw-r--r--chromium/third_party/blink/renderer/core/frame/csp/content_security_policy.cc75
-rw-r--r--chromium/third_party/blink/renderer/core/frame/csp/content_security_policy.h27
-rw-r--r--chromium/third_party/blink/renderer/core/frame/csp/content_security_policy_fuzzer.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/frame/csp/content_security_policy_test.cc535
-rw-r--r--chromium/third_party/blink/renderer/core/frame/csp/csp_directive_list.cc100
-rw-r--r--chromium/third_party/blink/renderer/core/frame/csp/csp_directive_list.h5
-rw-r--r--chromium/third_party/blink/renderer/core/frame/csp/csp_directive_list_test.cc140
-rw-r--r--chromium/third_party/blink/renderer/core/frame/csp/csp_violation_report_body.h10
-rw-r--r--chromium/third_party/blink/renderer/core/frame/csp/execution_context_csp_delegate.cc20
-rw-r--r--chromium/third_party/blink/renderer/core/frame/csp/execution_context_csp_delegate.h3
-rw-r--r--chromium/third_party/blink/renderer/core/frame/csp/navigation_initiator_impl.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/frame/csp/navigation_initiator_impl.h1
-rw-r--r--chromium/third_party/blink/renderer/core/frame/dactyloscoper.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/frame/deprecation.cc112
-rw-r--r--chromium/third_party/blink/renderer/core/frame/deprecation.h5
-rw-r--r--chromium/third_party/blink/renderer/core/frame/device_single_window_event_controller.cc35
-rw-r--r--chromium/third_party/blink/renderer/core/frame/device_single_window_event_controller.h5
-rw-r--r--chromium/third_party/blink/renderer/core/frame/document_policy_violation_report_body.h11
-rw-r--r--chromium/third_party/blink/renderer/core/frame/dom_timer_test.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/frame/dom_window.cc32
-rw-r--r--chromium/third_party/blink/renderer/core/frame/event_handler_registry.cc15
-rw-r--r--chromium/third_party/blink/renderer/core/frame/event_handler_registry.h3
-rw-r--r--chromium/third_party/blink/renderer/core/frame/feature_policy_violation_report_body.h17
-rw-r--r--chromium/third_party/blink/renderer/core/frame/find_in_page.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/frame/fragment_directive.idl6
-rw-r--r--chromium/third_party/blink/renderer/core/frame/frame.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/frame/frame.h19
-rw-r--r--chromium/third_party/blink/renderer/core/frame/frame_console.cc10
-rw-r--r--chromium/third_party/blink/renderer/core/frame/frame_overlay.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/frame/frame_overlay_test.cc36
-rw-r--r--chromium/third_party/blink/renderer/core/frame/frame_serializer.cc15
-rw-r--r--chromium/third_party/blink/renderer/core/frame/frame_serializer_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/frame/frame_test_helpers.cc194
-rw-r--r--chromium/third_party/blink/renderer/core/frame/frame_test_helpers.h93
-rw-r--r--chromium/third_party/blink/renderer/core/frame/history.cc73
-rw-r--r--chromium/third_party/blink/renderer/core/frame/history.h5
-rw-r--r--chromium/third_party/blink/renderer/core/frame/history.idl2
-rw-r--r--chromium/third_party/blink/renderer/core/frame/intervention.cc14
-rw-r--r--chromium/third_party/blink/renderer/core/frame/is_input_pending_options.cc20
-rw-r--r--chromium/third_party/blink/renderer/core/frame/is_input_pending_options.h34
-rw-r--r--chromium/third_party/blink/renderer/core/frame/is_input_pending_options.idl12
-rw-r--r--chromium/third_party/blink/renderer/core/frame/is_input_pending_options_init.idl8
-rw-r--r--chromium/third_party/blink/renderer/core/frame/local_dom_window.cc185
-rw-r--r--chromium/third_party/blink/renderer/core/frame/local_dom_window.h35
-rw-r--r--chromium/third_party/blink/renderer/core/frame/local_frame.cc243
-rw-r--r--chromium/third_party/blink/renderer/core/frame/local_frame.h58
-rw-r--r--chromium/third_party/blink/renderer/core/frame/local_frame_client.h16
-rw-r--r--chromium/third_party/blink/renderer/core/frame/local_frame_test.cc84
-rw-r--r--chromium/third_party/blink/renderer/core/frame/local_frame_ukm_aggregator.h2
-rw-r--r--chromium/third_party/blink/renderer/core/frame/local_frame_view.cc151
-rw-r--r--chromium/third_party/blink/renderer/core/frame/local_frame_view.h33
-rw-r--r--chromium/third_party/blink/renderer/core/frame/local_frame_view_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/frame/location.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/frame/location_report_body.cc34
-rw-r--r--chromium/third_party/blink/renderer/core/frame/location_report_body.h57
-rw-r--r--chromium/third_party/blink/renderer/core/frame/mhtml_loading_test.cc21
-rw-r--r--chromium/third_party/blink/renderer/core/frame/navigator.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/frame/navigator.h2
-rw-r--r--chromium/third_party/blink/renderer/core/frame/navigator_automation_information.idl1
-rw-r--r--chromium/third_party/blink/renderer/core/frame/navigator_concurrent_hardware.idl4
-rw-r--r--chromium/third_party/blink/renderer/core/frame/navigator_cookies.idl1
-rw-r--r--chromium/third_party/blink/renderer/core/frame/navigator_device_memory.idl4
-rw-r--r--chromium/third_party/blink/renderer/core/frame/navigator_id.idl4
-rw-r--r--chromium/third_party/blink/renderer/core/frame/navigator_language.idl4
-rw-r--r--chromium/third_party/blink/renderer/core/frame/navigator_on_line.idl4
-rw-r--r--chromium/third_party/blink/renderer/core/frame/navigator_scheduling.idl3
-rw-r--r--chromium/third_party/blink/renderer/core/frame/navigator_ua.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/frame/navigator_ua_data.cc26
-rw-r--r--chromium/third_party/blink/renderer/core/frame/navigator_ua_data.h8
-rw-r--r--chromium/third_party/blink/renderer/core/frame/navigator_ua_data.idl2
-rw-r--r--chromium/third_party/blink/renderer/core/frame/overlay_interstitial_ad_detector.cc105
-rw-r--r--chromium/third_party/blink/renderer/core/frame/overlay_interstitial_ad_detector.h60
-rw-r--r--chromium/third_party/blink/renderer/core/frame/pausable_script_executor.cc13
-rw-r--r--chromium/third_party/blink/renderer/core/frame/performance_monitor.cc17
-rw-r--r--chromium/third_party/blink/renderer/core/frame/performance_monitor_test.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/frame/platform_event_controller.cc14
-rw-r--r--chromium/third_party/blink/renderer/core/frame/platform_event_controller.h8
-rw-r--r--chromium/third_party/blink/renderer/core/frame/remote_frame.cc53
-rw-r--r--chromium/third_party/blink/renderer/core/frame/remote_frame.h9
-rw-r--r--chromium/third_party/blink/renderer/core/frame/remote_frame_client.h7
-rw-r--r--chromium/third_party/blink/renderer/core/frame/remote_frame_client_impl.cc11
-rw-r--r--chromium/third_party/blink/renderer/core/frame/remote_frame_client_impl.h4
-rw-r--r--chromium/third_party/blink/renderer/core/frame/remote_frame_owner.cc15
-rw-r--r--chromium/third_party/blink/renderer/core/frame/remote_frame_owner.h14
-rw-r--r--chromium/third_party/blink/renderer/core/frame/remote_frame_view.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/frame/reporting_context.cc88
-rw-r--r--chromium/third_party/blink/renderer/core/frame/reporting_context.h16
-rw-r--r--chromium/third_party/blink/renderer/core/frame/reporting_context_test.cc11
-rw-r--r--chromium/third_party/blink/renderer/core/frame/reporting_observer.idl3
-rw-r--r--chromium/third_party/blink/renderer/core/frame/sandbox_flags.cc135
-rw-r--r--chromium/third_party/blink/renderer/core/frame/sandbox_flags.h20
-rw-r--r--chromium/third_party/blink/renderer/core/frame/scheduling.cc51
-rw-r--r--chromium/third_party/blink/renderer/core/frame/scheduling.h4
-rw-r--r--chromium/third_party/blink/renderer/core/frame/scheduling.idl10
-rw-r--r--chromium/third_party/blink/renderer/core/frame/screen.cc59
-rw-r--r--chromium/third_party/blink/renderer/core/frame/screen.h12
-rw-r--r--chromium/third_party/blink/renderer/core/frame/screen.idl13
-rw-r--r--chromium/third_party/blink/renderer/core/frame/screen_orientation_controller.cc33
-rw-r--r--chromium/third_party/blink/renderer/core/frame/screen_orientation_controller.h57
-rw-r--r--chromium/third_party/blink/renderer/core/frame/settings.json515
-rw-r--r--chromium/third_party/blink/renderer/core/frame/ua_data_values.idl10
-rw-r--r--chromium/third_party/blink/renderer/core/frame/visual_viewport.cc14
-rw-r--r--chromium/third_party/blink/renderer/core/frame/visual_viewport.idl1
-rw-r--r--chromium/third_party/blink/renderer/core/frame/visual_viewport_test.cc22
-rw-r--r--chromium/third_party/blink/renderer/core/frame/web_frame_widget_base.cc139
-rw-r--r--chromium/third_party/blink/renderer/core/frame/web_frame_widget_base.h66
-rw-r--r--chromium/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc119
-rw-r--r--chromium/third_party/blink/renderer/core/frame/web_frame_widget_impl.h45
-rw-r--r--chromium/third_party/blink/renderer/core/frame/web_local_frame_impl.cc233
-rw-r--r--chromium/third_party/blink/renderer/core/frame/web_local_frame_impl.h78
-rw-r--r--chromium/third_party/blink/renderer/core/frame/web_view_frame_widget.cc42
-rw-r--r--chromium/third_party/blink/renderer/core/frame/web_view_frame_widget.h45
-rw-r--r--chromium/third_party/blink/renderer/core/frame/window.idl10
-rw-r--r--chromium/third_party/blink/renderer/core/frame/window_event_handlers.idl3
-rw-r--r--chromium/third_party/blink/renderer/core/frame/window_or_worker_global_scope.cc21
-rw-r--r--chromium/third_party/blink/renderer/core/fullscreen/fullscreen.cc50
-rw-r--r--chromium/third_party/blink/renderer/core/fullscreen/fullscreen.h10
-rw-r--r--chromium/third_party/blink/renderer/core/geometry/dom_rect.h9
-rw-r--r--chromium/third_party/blink/renderer/core/geometry/dom_rect_list.idl4
-rw-r--r--chromium/third_party/blink/renderer/core/html/BUILD.gn2
-rw-r--r--chromium/third_party/blink/renderer/core/html/anchor_element_metrics.cc44
-rw-r--r--chromium/third_party/blink/renderer/core/html/anchor_element_metrics.h5
-rw-r--r--chromium/third_party/blink/renderer/core/html/anchor_element_metrics_sender.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/html/canvas/canvas_async_blob_creator.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/html/canvas/canvas_font_cache_test.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/html/canvas/canvas_rendering_context_host.cc105
-rw-r--r--chromium/third_party/blink/renderer/core/html/canvas/canvas_rendering_context_host.h20
-rw-r--r--chromium/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc69
-rw-r--r--chromium/third_party/blink/renderer/core/html/canvas/html_canvas_element.h10
-rw-r--r--chromium/third_party/blink/renderer/core/html/canvas/image_data.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/html/canvas/image_data.h1
-rw-r--r--chromium/third_party/blink/renderer/core/html/canvas/image_element_base.cc12
-rw-r--r--chromium/third_party/blink/renderer/core/html/canvas/image_element_base.h1
-rw-r--r--chromium/third_party/blink/renderer/core/html/custom/custom_element.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/html/custom/custom_element.h2
-rw-r--r--chromium/third_party/blink/renderer/core/html/custom/custom_element_definition.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/html/custom/custom_element_definition.h3
-rw-r--r--chromium/third_party/blink/renderer/core/html/custom/custom_element_reaction_factory.cc24
-rw-r--r--chromium/third_party/blink/renderer/core/html/custom/custom_element_reaction_factory.h3
-rw-r--r--chromium/third_party/blink/renderer/core/html/custom/custom_element_registry.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/html/custom/element_internals.cc24
-rw-r--r--chromium/third_party/blink/renderer/core/html/custom/element_internals.h7
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/base_button_input_type.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/color_chooser_popup_ui_controller.cc51
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/color_chooser_popup_ui_controller.h9
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/color_chooser_ui_controller.h1
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/date_time_chooser_impl.cc45
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/date_time_field_element.cc13
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/external_popup_menu.cc158
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/external_popup_menu.h31
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/external_popup_menu_test.cc260
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/file_input_type.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/form_data_event.idl2
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/html_button_element.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/html_form_control_element_with_state.h3
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/html_form_element.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/html_input_element.cc48
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/html_input_element.h11
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/html_opt_group_element.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/html_option_element.h10
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/html_select_element.cc75
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/html_select_element.h3
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/html_select_element_test.cc38
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/html_text_area_element.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/internal_popup_menu.cc35
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/internal_popup_menu.h2
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/internal_popup_menu_test.cc24
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/multiple_fields_temporal_input_type_view.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/password_input_type.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/password_input_type.h1
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/picker_indicator_element.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/range_input_type.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/resources/color_picker.js229
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/resources/color_picker_common.js1
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/resources/listPicker.css5
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/resources/listPicker.js4
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/select_type.cc70
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/select_type.h2
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/spin_button_element.cc32
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/spin_button_element.h2
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/text_control_element.cc11
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/text_control_inner_elements.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/text_control_inner_elements.h1
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/text_field_input_type.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/type_ahead_test.cc10
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_anchor_element.cc117
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_anchor_element.h11
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_attribute_names.json55
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_body_element.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_body_element.h3
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_body_element.idl2
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_collection.idl1
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_content_element.idl4
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_element.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_element.h6
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_embed_element.h6
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_frame_element.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_frame_element.h6
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_frame_element_base.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_frame_element_test.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_frame_owner_element.cc37
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_frame_owner_element.h6
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_frame_set_element.h3
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_frame_set_element.idl2
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_iframe_element.cc107
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_iframe_element.h16
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_iframe_element.idl2
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_iframe_element_test.cc87
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_image_element.cc11
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_object_element.h6
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_plugin_element.cc11
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_rt_element.cc15
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_rt_element.h2
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_ruby_element.cc15
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_ruby_element.h2
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_script_element.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_script_element.h1
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_shadow_element.idl4
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_slot_element.cc104
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_slot_element.h14
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_slot_element.idl6
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_table_element.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_table_part_element.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_template_element.cc16
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_template_element.h26
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_template_element.idl10
-rw-r--r--chromium/third_party/blink/renderer/core/html/image_document_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/html/imports/html_import_loader.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/html/imports/html_imports_controller.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/html/lazy_load_image_observer.cc10
-rw-r--r--chromium/third_party/blink/renderer/core/html/lazy_load_image_observer.h1
-rw-r--r--chromium/third_party/blink/renderer/core/html/lazy_load_image_observer_test.cc329
-rw-r--r--chromium/third_party/blink/renderer/core/html/link_style.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/html/loading_attribute.cc17
-rw-r--r--chromium/third_party/blink/renderer/core/html/loading_attribute.h17
-rw-r--r--chromium/third_party/blink/renderer/core/html/media/autoplay_policy.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/html/media/html_media_element.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/html/media/html_video_element.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/html/media/html_video_element.h1
-rw-r--r--chromium/third_party/blink/renderer/core/html/media/media_remoting_interstitial.h1
-rw-r--r--chromium/third_party/blink/renderer/core/html/media/picture_in_picture_interstitial.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/html/media/video_wake_lock.cc49
-rw-r--r--chromium/third_party/blink/renderer/core/html/media/video_wake_lock.h13
-rw-r--r--chromium/third_party/blink/renderer/core/html/media/video_wake_lock_test.cc138
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/html_construction_site.cc36
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/html_construction_site.h4
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/html_preload_scanner.cc107
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/html_preload_scanner.h3
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/html_preload_scanner_test.cc135
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/html_tree_builder.cc85
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/preload_request.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/preload_request.h7
-rw-r--r--chromium/third_party/blink/renderer/core/html/portal/html_portal_element.h4
-rw-r--r--chromium/third_party/blink/renderer/core/html/portal/html_portal_element.idl2
-rw-r--r--chromium/third_party/blink/renderer/core/html/portal/html_portal_element_test.cc25
-rw-r--r--chromium/third_party/blink/renderer/core/html/portal/portal_activate_event.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/html/portal/portal_activate_event_init.idl2
-rw-r--r--chromium/third_party/blink/renderer/core/html/portal/portal_contents.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/html/portal/portal_host.idl2
-rw-r--r--chromium/third_party/blink/renderer/core/html/rel_list.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/html/resources/android.css6
-rw-r--r--chromium/third_party/blink/renderer/core/html/resources/controls_refresh.css43
-rw-r--r--chromium/third_party/blink/renderer/core/html/resources/forced_colors.css8
-rw-r--r--chromium/third_party/blink/renderer/core/html/resources/html.css26
-rw-r--r--chromium/third_party/blink/renderer/core/html/resources/input_multiple_fields.css6
-rw-r--r--chromium/third_party/blink/renderer/core/html/resources/linux.css6
-rw-r--r--chromium/third_party/blink/renderer/core/html/resources/mac.css6
-rw-r--r--chromium/third_party/blink/renderer/core/html/resources/quirks.css6
-rw-r--r--chromium/third_party/blink/renderer/core/html/resources/win.css8
-rw-r--r--chromium/third_party/blink/renderer/core/html/resources/win_quirks.css6
-rw-r--r--chromium/third_party/blink/renderer/core/html/shadow/details_marker_control.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/html/track/text_track_container.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/html/track/vtt/vtt_cue.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/html/trust_token_attribute_parsing.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/html/trust_token_attribute_parsing.h2
-rw-r--r--chromium/third_party/blink/renderer/core/imagebitmap/image_bitmap.cc26
-rw-r--r--chromium/third_party/blink/renderer/core/imagebitmap/image_bitmap.h11
-rw-r--r--chromium/third_party/blink/renderer/core/imagebitmap/image_bitmap_factories.cc66
-rw-r--r--chromium/third_party/blink/renderer/core/imagebitmap/image_bitmap_factories.h39
-rw-r--r--chromium/third_party/blink/renderer/core/imagebitmap/image_bitmap_source.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/imagebitmap/image_bitmap_source.h1
-rw-r--r--chromium/third_party/blink/renderer/core/imagebitmap/image_bitmap_test.cc20
-rw-r--r--chromium/third_party/blink/renderer/core/input/BUILD.gn4
-rw-r--r--chromium/third_party/blink/renderer/core/input/event_handler.cc113
-rw-r--r--chromium/third_party/blink/renderer/core/input/event_handler.h16
-rw-r--r--chromium/third_party/blink/renderer/core/input/event_handler_test.cc321
-rw-r--r--chromium/third_party/blink/renderer/core/input/fallback_cursor_event_manager.cc466
-rw-r--r--chromium/third_party/blink/renderer/core/input/fallback_cursor_event_manager.h77
-rw-r--r--chromium/third_party/blink/renderer/core/input/fallback_cursor_event_manager_test.cc597
-rw-r--r--chromium/third_party/blink/renderer/core/input/gesture_manager.cc46
-rw-r--r--chromium/third_party/blink/renderer/core/input/ime_on_focus_test.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/input/input_device_capabilities.idl4
-rw-r--r--chromium/third_party/blink/renderer/core/input/keyboard_event_manager.cc112
-rw-r--r--chromium/third_party/blink/renderer/core/input/keyboard_event_manager.h1
-rw-r--r--chromium/third_party/blink/renderer/core/input/mouse_event_manager.cc17
-rw-r--r--chromium/third_party/blink/renderer/core/input/overscroll_behavior_test.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/input/pointer_event_manager.cc48
-rw-r--r--chromium/third_party/blink/renderer/core/input/pointer_event_manager_test.cc125
-rw-r--r--chromium/third_party/blink/renderer/core/input/scroll_manager.cc46
-rw-r--r--chromium/third_party/blink/renderer/core/input/scroll_snap_test.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/input/touch_action_test.cc20
-rw-r--r--chromium/third_party/blink/renderer/core/input/touch_event_manager.cc94
-rw-r--r--chromium/third_party/blink/renderer/core/input/touch_event_manager.h2
-rw-r--r--chromium/third_party/blink/renderer/core/input/touch_event_manager_test.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/input/touch_list.idl4
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/BUILD.gn2
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/dom_traversal_utils.cc46
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/dom_traversal_utils.h22
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspect_tool_highlight.html327
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspect_tools.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspect_tools.h1
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_animation_agent.cc20
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_audits_agent.cc225
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_css_agent.cc76
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_css_agent.h5
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_dom_agent.cc10
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_dom_snapshot_agent.cc122
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_dom_snapshot_agent.h12
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_emulation_agent.cc73
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_emulation_agent.h9
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_highlight.cc217
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_highlight.h24
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_issue.cc18
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_issue.h5
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_issue_storage.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_issue_storage.h3
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_media_agent.cc120
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_media_agent.h6
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_media_context_impl.cc129
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_media_context_impl.h44
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_network_agent.cc68
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_network_agent.h1
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_overlay_agent.cc281
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_overlay_agent.h38
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_page_agent.cc30
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_page_agent.h3
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_resource_content_loader.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_style_sheet.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/legacy_dom_snapshot_agent.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/network_resources_data.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/network_resources_data.h5
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/thread_debugger.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/worker_inspector_controller.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/intersection_observer/intersection_geometry.cc15
-rw-r--r--chromium/third_party/blink/renderer/core/intersection_observer/intersection_observer.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/intersection_observer/intersection_observer.h5
-rw-r--r--chromium/third_party/blink/renderer/core/intersection_observer/intersection_observer_entry.idl4
-rw-r--r--chromium/third_party/blink/renderer/core/intersection_observer/intersection_observer_test.cc16
-rw-r--r--chromium/third_party/blink/renderer/core/invisible_dom/BUILD.gn14
-rw-r--r--chromium/third_party/blink/renderer/core/invisible_dom/OWNERS4
-rw-r--r--chromium/third_party/blink/renderer/core/invisible_dom/activate_invisible_event.cc29
-rw-r--r--chromium/third_party/blink/renderer/core/invisible_dom/activate_invisible_event.h36
-rw-r--r--chromium/third_party/blink/renderer/core/invisible_dom/activate_invisible_event.idl11
-rw-r--r--chromium/third_party/blink/renderer/core/invisible_dom/invisible_dom.cc63
-rw-r--r--chromium/third_party/blink/renderer/core/invisible_dom/invisible_dom.h34
-rw-r--r--chromium/third_party/blink/renderer/core/layout/BUILD.gn49
-rw-r--r--chromium/third_party/blink/renderer/core/layout/box_layout_extra_input.h4
-rw-r--r--chromium/third_party/blink/renderer/core/layout/flexible_box_algorithm.cc120
-rw-r--r--chromium/third_party/blink/renderer/core/layout/flexible_box_algorithm.h14
-rw-r--r--chromium/third_party/blink/renderer/core/layout/grid_track_sizing_algorithm.cc10
-rw-r--r--chromium/third_party/blink/renderer/core/layout/hit_testing_test.cc63
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_block.cc41
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_block_flow.cc19
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_block_flow_line.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_box.cc234
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_box.h31
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_box_model_object.cc85
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_box_model_object.h7
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_box_model_object_test.cc130
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_button.cc10
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_custom_scrollbar_part.cc27
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_custom_scrollbar_part.h2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_details_marker.h2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_fieldset.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_flexible_box.cc138
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_flexible_box.h2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_flexible_box_test.cc58
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_flow_thread.cc14
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_flow_thread.h7
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_frame_set.h1
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_grid.cc10
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_grid_test.cc38
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_inline.cc93
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_inline.h5
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_inline_test.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_multi_column_flow_thread.cc15
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_multi_column_flow_thread.h5
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_object.cc159
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_object.h95
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_object_child_list.cc11
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_object_factory.cc43
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_object_factory.h6
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_object_test.cc25
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_ruby.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_ruby.h6
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_ruby_base.cc17
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_ruby_base.h12
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_ruby_run.cc21
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_ruby_run.h13
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_ruby_text.h2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_shift_tracker.cc65
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_shift_tracker.h22
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_shift_tracker_test.cc18
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_table_section.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_text.cc66
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_text.h9
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_text_control.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_theme.cc10
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_theme.h1
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_theme_default.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_theme_default.h4
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_theme_mac.mm6
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_view.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_view.h10
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_view_test.cc55
-rw-r--r--chromium/third_party/blink/renderer/core/layout/line/inline_box.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/multi_column_fragmentainer_group_test.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/custom/css_layout_definition.cc12
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/custom/css_layout_definition.h4
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/custom/custom_layout_child.cc23
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/custom/custom_layout_constraints.cc10
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/custom/custom_layout_constraints.h2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/custom/custom_layout_fragment.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/custom/custom_layout_fragment.h2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/custom/custom_layout_work_task.cc17
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/custom/custom_layout_work_task.h6
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/custom/layout_worklet.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/custom/layout_worklet.h2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/custom/layout_worklet_global_scope.cc21
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/custom/layout_worklet_global_scope.h3
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/custom/layout_worklet_global_scope_proxy.cc22
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/custom/layout_worklet_test.cc79
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/custom/ng_custom_layout_algorithm.cc34
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/custom/ng_custom_layout_algorithm.h7
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/flex/layout_ng_flexible_box.cc (renamed from chromium/third_party/blink/renderer/core/layout/ng/layout_ng_flexible_box.cc)2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/flex/layout_ng_flexible_box.h (renamed from chromium/third_party/blink/renderer/core/layout/ng/layout_ng_flexible_box.h)6
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/flex/ng_flex_child_iterator.cc (renamed from chromium/third_party/blink/renderer/core/layout/ng/ng_flex_child_iterator.cc)2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/flex/ng_flex_child_iterator.h (renamed from chromium/third_party/blink/renderer/core/layout/ng/ng_flex_child_iterator.h)6
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/flex/ng_flex_layout_algorithm.cc (renamed from chromium/third_party/blink/renderer/core/layout/ng/ng_flex_layout_algorithm.cc)348
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/flex/ng_flex_layout_algorithm.h (renamed from chromium/third_party/blink/renderer/core/layout/ng/ng_flex_layout_algorithm.h)13
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/README.md32
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_abstract_inline_text_box.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_caret_position.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_dirty_lines.cc50
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_dirty_lines.h91
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.cc145
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.h78
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item_test.cc563
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items.cc346
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items.h65
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items_builder.cc252
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items_builder.h57
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.cc30
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.h3
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.cc460
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.h120
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor_test.cc41
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item.cc37
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item.h45
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item_result.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item_result.h2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item_segment.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item_segment.h4
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_items_builder.cc169
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_items_builder.h45
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_layout_algorithm.cc127
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_layout_algorithm.h26
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_layout_algorithm_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.cc280
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.h19
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node_test.cc418
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_line_box_fragment_builder.cc22
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_line_box_fragment_builder.h24
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.cc88
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.h5
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker_test.cc12
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_offset_mapping.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_offset_mapping.h2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_offset_mapping_test.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_physical_text_fragment.cc36
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_physical_text_fragment.h30
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_physical_text_fragment_test.cc14
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_text_fragment_builder.cc43
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_text_fragment_builder.h10
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_text_type.h32
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/layout_box_utils.cc19
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/layout_ng_block_flow_mixin.cc12
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/layout_ng_block_flow_mixin.h10
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/layout_ng_fieldset.cc57
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/layout_ng_grid.cc23
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/layout_ng_grid.h31
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/layout_ng_mixin.cc14
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/layout_ng_mixin.h9
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_as_block.cc18
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_as_block.h28
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_base.cc18
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_base.h27
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_run.cc19
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_run.h27
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_text.cc18
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_text.h27
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/layout_ng_table_cell.h26
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/legacy_layout_tree_walking.h12
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/mathml/layout_ng_mathml_block.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/mathml/layout_ng_mathml_block.h3
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_fraction_layout_algorithm.cc44
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_fraction_layout_algorithm.h3
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_layout_utils.cc16
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_layout_utils.h1
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_row_layout_algorithm.cc43
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_row_layout_algorithm.h3
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_scripts_layout_algorithm.cc392
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_scripts_layout_algorithm.h67
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_space_layout_algorithm.cc16
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_space_layout_algorithm.h3
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_under_over_layout_algorithm.cc286
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_under_over_layout_algorithm.h35
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.cc445
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.h31
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm_test.cc78
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm_utils.h2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_block_node.cc356
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_block_node.h33
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_block_node_test.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.cc23
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.h13
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm.cc36
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm.h3
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm_test.cc21
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_constraint_space.h23
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_constraint_space_builder.h10
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.cc33
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.h13
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm.cc180
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm.h14
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm_test.cc19
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_floats_utils.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_fragment_builder.h4
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_fragment_child_iterator.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.cc39
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.h29
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_grid_layout_algorithm.cc27
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_grid_layout_algorithm.h28
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_layout_algorithm.h20
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_layout_input_node.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_layout_input_node.h32
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_layout_result.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_layout_result.h6
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_layout_result_caching_test.cc158
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_layout_utils.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_layout_utils.h7
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_length_utils.cc292
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_length_utils.h49
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_length_utils_test.cc104
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.cc18
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_page_layout_algorithm.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_page_layout_algorithm.h3
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.cc44
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h10
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_physical_container_fragment.cc26
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_physical_container_fragment.h12
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_physical_fragment.cc19
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_physical_fragment.h29
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_simplified_layout_algorithm.cc307
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_simplified_layout_algorithm.h12
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_space_utils.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table.cc73
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table.h139
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_caption.cc (renamed from chromium/third_party/blink/renderer/core/layout/ng/layout_ng_table_caption.cc)6
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_caption.h (renamed from chromium/third_party/blink/renderer/core/layout/ng/layout_ng_table_caption.h)14
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_cell.cc124
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_cell.h118
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_cell_legacy.cc (renamed from chromium/third_party/blink/renderer/core/layout/ng/layout_ng_table_cell.cc)6
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_cell_legacy.h39
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_column.cc82
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_column.h93
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_interface.h6
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_row.cc59
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_row.h93
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_section.cc101
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_section.h103
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_section_interface.h4
-rw-r--r--chromium/third_party/blink/renderer/core/layout/scroll_anchor.cc65
-rw-r--r--chromium/third_party/blink/renderer/core/layout/scroll_anchor.h13
-rw-r--r--chromium/third_party/blink/renderer/core/layout/scroll_anchor_test.cc240
-rw-r--r--chromium/third_party/blink/renderer/core/layout/scrollbars_test.cc109
-rw-r--r--chromium/third_party/blink/renderer/core/layout/subtree_layout_scope.cc14
-rw-r--r--chromium/third_party/blink/renderer/core/layout/svg/layout_svg_container.cc10
-rw-r--r--chromium/third_party/blink/renderer/core/layout/svg/layout_svg_container.h2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/svg/layout_svg_rect.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/layout/svg/layout_svg_resource_container.cc23
-rw-r--r--chromium/third_party/blink/renderer/core/layout/svg/layout_svg_resource_container.h11
-rw-r--r--chromium/third_party/blink/renderer/core/layout/svg/layout_svg_resource_filter.cc19
-rw-r--r--chromium/third_party/blink/renderer/core/layout/svg/layout_svg_resource_filter.h3
-rw-r--r--chromium/third_party/blink/renderer/core/layout/svg/layout_svg_resource_marker.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/layout/svg/layout_svg_resource_marker.h2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/svg/layout_svg_root.cc23
-rw-r--r--chromium/third_party/blink/renderer/core/layout/svg/layout_svg_root.h4
-rw-r--r--chromium/third_party/blink/renderer/core/layout/svg/layout_svg_shape.cc91
-rw-r--r--chromium/third_party/blink/renderer/core/layout/svg/layout_svg_shape.h4
-rw-r--r--chromium/third_party/blink/renderer/core/layout/svg/layout_svg_transformable_container.cc20
-rw-r--r--chromium/third_party/blink/renderer/core/layout/svg/layout_svg_transformable_container.h4
-rw-r--r--chromium/third_party/blink/renderer/core/layout/svg/layout_svg_viewport_container.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/layout/svg/layout_svg_viewport_container.h2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/svg/svg_resources.cc40
-rw-r--r--chromium/third_party/blink/renderer/core/layout/svg/svg_resources.h3
-rw-r--r--chromium/third_party/blink/renderer/core/layout/text_decoration_offset_base.cc42
-rw-r--r--chromium/third_party/blink/renderer/core/layout/text_decoration_offset_base.h3
-rw-r--r--chromium/third_party/blink/renderer/core/loader/BUILD.gn4
-rw-r--r--chromium/third_party/blink/renderer/core/loader/DEPS1
-rw-r--r--chromium/third_party/blink/renderer/core/loader/alternate_signed_exchange_resource_info.cc21
-rw-r--r--chromium/third_party/blink/renderer/core/loader/appcache/application_cache.cc11
-rw-r--r--chromium/third_party/blink/renderer/core/loader/appcache/application_cache.h2
-rw-r--r--chromium/third_party/blink/renderer/core/loader/appcache/application_cache_host.cc14
-rw-r--r--chromium/third_party/blink/renderer/core/loader/appcache/application_cache_host.h24
-rw-r--r--chromium/third_party/blink/renderer/core/loader/appcache/application_cache_host_for_frame.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/loader/appcache/application_cache_host_for_worker.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/loader/appcache/application_cache_host_for_worker.h3
-rw-r--r--chromium/third_party/blink/renderer/core/loader/base_fetch_context.cc32
-rw-r--r--chromium/third_party/blink/renderer/core/loader/base_fetch_context.h17
-rw-r--r--chromium/third_party/blink/renderer/core/loader/base_fetch_context_test.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/loader/cookie_jar.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/loader/document_loader.cc233
-rw-r--r--chromium/third_party/blink/renderer/core/loader/document_loader.h28
-rw-r--r--chromium/third_party/blink/renderer/core/loader/document_loader_test.cc312
-rw-r--r--chromium/third_party/blink/renderer/core/loader/empty_clients.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/loader/empty_clients.h18
-rw-r--r--chromium/third_party/blink/renderer/core/loader/font_preload_manager_test.cc99
-rw-r--r--chromium/third_party/blink/renderer/core/loader/frame_fetch_context.cc367
-rw-r--r--chromium/third_party/blink/renderer/core/loader/frame_fetch_context.h33
-rw-r--r--chromium/third_party/blink/renderer/core/loader/frame_fetch_context_test.cc176
-rw-r--r--chromium/third_party/blink/renderer/core/loader/frame_load_request.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/loader/frame_load_request.h10
-rw-r--r--chromium/third_party/blink/renderer/core/loader/frame_loader.cc323
-rw-r--r--chromium/third_party/blink/renderer/core/loader/frame_loader.h47
-rw-r--r--chromium/third_party/blink/renderer/core/loader/frame_loader_types.h12
-rw-r--r--chromium/third_party/blink/renderer/core/loader/frame_or_imported_document.cc65
-rw-r--r--chromium/third_party/blink/renderer/core/loader/frame_or_imported_document.h73
-rw-r--r--chromium/third_party/blink/renderer/core/loader/frame_resource_fetcher_properties.cc79
-rw-r--r--chromium/third_party/blink/renderer/core/loader/frame_resource_fetcher_properties.h14
-rw-r--r--chromium/third_party/blink/renderer/core/loader/frame_resource_fetcher_properties_test.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/loader/http_equiv.cc75
-rw-r--r--chromium/third_party/blink/renderer/core/loader/http_equiv.h2
-rw-r--r--chromium/third_party/blink/renderer/core/loader/idleness_detector.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/loader/image_loader.cc103
-rw-r--r--chromium/third_party/blink/renderer/core/loader/image_loader.h21
-rw-r--r--chromium/third_party/blink/renderer/core/loader/interactive_detector.cc10
-rw-r--r--chromium/third_party/blink/renderer/core/loader/lazy_image_helper.cc47
-rw-r--r--chromium/third_party/blink/renderer/core/loader/lazy_image_helper.h1
-rw-r--r--chromium/third_party/blink/renderer/core/loader/link_loader.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/loader/loader_factory_for_frame.cc31
-rw-r--r--chromium/third_party/blink/renderer/core/loader/loader_factory_for_frame.h8
-rw-r--r--chromium/third_party/blink/renderer/core/loader/mixed_content_checker.cc88
-rw-r--r--chromium/third_party/blink/renderer/core/loader/mixed_content_checker.h14
-rw-r--r--chromium/third_party/blink/renderer/core/loader/mixed_content_checker_test.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/loader/modulescript/module_script_loader.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/loader/modulescript/module_script_loader_test.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/loader/navigation_policy.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/loader/navigation_policy_test.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/loader/preload_helper.cc37
-rw-r--r--chromium/third_party/blink/renderer/core/loader/previews_resource_loading_hints_test.cc15
-rw-r--r--chromium/third_party/blink/renderer/core/loader/private/frame_client_hints_preferences_context.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/loader/private/frame_client_hints_preferences_context.h2
-rw-r--r--chromium/third_party/blink/renderer/core/loader/private/prerender_handle.cc27
-rw-r--r--chromium/third_party/blink/renderer/core/loader/private/prerender_handle.h16
-rw-r--r--chromium/third_party/blink/renderer/core/loader/resource/document_resource.cc103
-rw-r--r--chromium/third_party/blink/renderer/core/loader/resource/document_resource.h88
-rw-r--r--chromium/third_party/blink/renderer/core/loader/resource/font_resource.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/loader/resource/font_resource.h3
-rw-r--r--chromium/third_party/blink/renderer/core/loader/resource/font_resource_test.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/loader/resource/image_resource.cc184
-rw-r--r--chromium/third_party/blink/renderer/core/loader/resource/image_resource.h37
-rw-r--r--chromium/third_party/blink/renderer/core/loader/resource/image_resource_content.cc58
-rw-r--r--chromium/third_party/blink/renderer/core/loader/resource/image_resource_content.h2
-rw-r--r--chromium/third_party/blink/renderer/core/loader/resource/image_resource_info.h4
-rw-r--r--chromium/third_party/blink/renderer/core/loader/resource/image_resource_test.cc596
-rw-r--r--chromium/third_party/blink/renderer/core/loader/resource/script_resource.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/loader/resource/text_resource.cc27
-rw-r--r--chromium/third_party/blink/renderer/core/loader/resource/text_resource.h30
-rw-r--r--chromium/third_party/blink/renderer/core/loader/resource_load_observer_for_frame.cc149
-rw-r--r--chromium/third_party/blink/renderer/core/loader/resource_load_observer_for_frame.h18
-rw-r--r--chromium/third_party/blink/renderer/core/loader/resource_load_observer_for_frame_test.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/loader/subresource_filter.cc16
-rw-r--r--chromium/third_party/blink/renderer/core/loader/threadable_loader.cc30
-rw-r--r--chromium/third_party/blink/renderer/core/loader/threadable_loader.h12
-rw-r--r--chromium/third_party/blink/renderer/core/loader/threadable_loader_test.cc12
-rw-r--r--chromium/third_party/blink/renderer/core/loader/threaded_icon_loader.cc22
-rw-r--r--chromium/third_party/blink/renderer/core/loader/threaded_icon_loader.h4
-rw-r--r--chromium/third_party/blink/renderer/core/loader/threaded_icon_loader_test.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/loader/web_associated_url_loader_impl.cc36
-rw-r--r--chromium/third_party/blink/renderer/core/loader/web_associated_url_loader_impl.h12
-rw-r--r--chromium/third_party/blink/renderer/core/loader/worker_fetch_context.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/loader/worker_fetch_context.h10
-rw-r--r--chromium/third_party/blink/renderer/core/loader/worker_resource_fetcher_properties.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/loader/worker_resource_fetcher_properties.h2
-rw-r--r--chromium/third_party/blink/renderer/core/loader/worker_resource_timing_notifier_impl.cc16
-rw-r--r--chromium/third_party/blink/renderer/core/mathml/BUILD.gn4
-rw-r--r--chromium/third_party/blink/renderer/core/mathml/mathml_attribute_names.json51
-rw-r--r--chromium/third_party/blink/renderer/core/mathml/mathml_element.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/mathml/mathml_fraction_element.cc12
-rw-r--r--chromium/third_party/blink/renderer/core/mathml/mathml_fraction_element.h5
-rw-r--r--chromium/third_party/blink/renderer/core/mathml/mathml_scripts_element.cc28
-rw-r--r--chromium/third_party/blink/renderer/core/mathml/mathml_scripts_element.h48
-rw-r--r--chromium/third_party/blink/renderer/core/mathml/mathml_space_element.cc11
-rw-r--r--chromium/third_party/blink/renderer/core/mathml/mathml_space_element.h3
-rw-r--r--chromium/third_party/blink/renderer/core/mathml/mathml_tag_names.json524
-rw-r--r--chromium/third_party/blink/renderer/core/mathml/mathml_under_over_element.cc13
-rw-r--r--chromium/third_party/blink/renderer/core/mathml/mathml_under_over_element.h38
-rw-r--r--chromium/third_party/blink/renderer/core/messaging/blink_transferable_message_mojom_traits.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/messaging/blink_transferable_message_mojom_traits.h10
-rw-r--r--chromium/third_party/blink/renderer/core/messaging/message_channel.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/messaging/message_port.cc28
-rw-r--r--chromium/third_party/blink/renderer/core/messaging/message_port.h8
-rw-r--r--chromium/third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.cc152
-rw-r--r--chromium/third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.h1
-rw-r--r--chromium/third_party/blink/renderer/core/origin_trials/origin_trial_context.cc51
-rw-r--r--chromium/third_party/blink/renderer/core/origin_trials/origin_trial_context_test.cc22
-rw-r--r--chromium/third_party/blink/renderer/core/origin_trials/origin_trials.h4
-rw-r--r--chromium/third_party/blink/renderer/core/origin_trials/origin_trials_test.cc40
-rw-r--r--chromium/third_party/blink/renderer/core/page/BUILD.gn4
-rw-r--r--chromium/third_party/blink/renderer/core/page/autoscroll_controller.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/page/autoscroll_controller_test.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/page/chrome_client.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/page/chrome_client.h20
-rw-r--r--chromium/third_party/blink/renderer/core/page/chrome_client_impl.cc77
-rw-r--r--chromium/third_party/blink/renderer/core/page/chrome_client_impl.h18
-rw-r--r--chromium/third_party/blink/renderer/core/page/chrome_client_impl_test.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/page/color_page_popup_controller.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/page/color_page_popup_controller.h3
-rw-r--r--chromium/third_party/blink/renderer/core/page/context_menu_controller_test.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/page/create_window.cc19
-rw-r--r--chromium/third_party/blink/renderer/core/page/drag_controller.cc11
-rw-r--r--chromium/third_party/blink/renderer/core/page/drag_controller_test.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/page/focus_controller.cc27
-rw-r--r--chromium/third_party/blink/renderer/core/page/named_pages_mapper.cc43
-rw-r--r--chromium/third_party/blink/renderer/core/page/named_pages_mapper.h56
-rw-r--r--chromium/third_party/blink/renderer/core/page/named_pages_mapper_test.cc125
-rw-r--r--chromium/third_party/blink/renderer/core/page/page.cc17
-rw-r--r--chromium/third_party/blink/renderer/core/page/page.h9
-rw-r--r--chromium/third_party/blink/renderer/core/page/page_animator.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/page/page_popup.h1
-rw-r--r--chromium/third_party/blink/renderer/core/page/page_popup_client.cc10
-rw-r--r--chromium/third_party/blink/renderer/core/page/page_popup_client.h7
-rw-r--r--chromium/third_party/blink/renderer/core/page/page_popup_controller.cc19
-rw-r--r--chromium/third_party/blink/renderer/core/page/page_popup_controller.h12
-rw-r--r--chromium/third_party/blink/renderer/core/page/page_popup_supplement.cc81
-rw-r--r--chromium/third_party/blink/renderer/core/page/page_popup_supplement.h70
-rw-r--r--chromium/third_party/blink/renderer/core/page/page_widget_delegate.cc82
-rw-r--r--chromium/third_party/blink/renderer/core/page/page_widget_delegate.h17
-rw-r--r--chromium/third_party/blink/renderer/core/page/plugin_script_forbidden_scope.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/page/pointer_lock_controller.cc16
-rw-r--r--chromium/third_party/blink/renderer/core/page/pointer_lock_controller.h2
-rw-r--r--chromium/third_party/blink/renderer/core/page/print_context.cc24
-rw-r--r--chromium/third_party/blink/renderer/core/page/print_context.h2
-rw-r--r--chromium/third_party/blink/renderer/core/page/scrolling/DEPS6
-rw-r--r--chromium/third_party/blink/renderer/core/page/scrolling/element_fragment_anchor.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/page/scrolling/main_thread_scrolling_reasons_test.cc179
-rw-r--r--chromium/third_party/blink/renderer/core/page/scrolling/root_scroller_test.cc144
-rw-r--r--chromium/third_party/blink/renderer/core/page/scrolling/scroll_metrics_test.cc42
-rw-r--r--chromium/third_party/blink/renderer/core/page/scrolling/scroll_state.idl3
-rw-r--r--chromium/third_party/blink/renderer/core/page/scrolling/scrolling_coordinator.cc87
-rw-r--r--chromium/third_party/blink/renderer/core/page/scrolling/scrolling_coordinator.h9
-rw-r--r--chromium/third_party/blink/renderer/core/page/scrolling/scrolling_test.cc423
-rw-r--r--chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_anchor.cc78
-rw-r--r--chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_anchor.h12
-rw-r--r--chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_anchor_metrics.cc85
-rw-r--r--chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_anchor_metrics.h38
-rw-r--r--chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_anchor_metrics_test.cc348
-rw-r--r--chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_anchor_test.cc151
-rw-r--r--chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_finder.cc18
-rw-r--r--chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_finder.h5
-rw-r--r--chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_selector.h2
-rw-r--r--chromium/third_party/blink/renderer/core/page/spatial_navigation_controller.cc13
-rw-r--r--chromium/third_party/blink/renderer/core/page/spatial_navigation_controller.h10
-rw-r--r--chromium/third_party/blink/renderer/core/page/spatial_navigation_test.cc20
-rw-r--r--chromium/third_party/blink/renderer/core/page/validation_message_overlay_delegate.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/page/viewport_test.cc14
-rw-r--r--chromium/third_party/blink/renderer/core/paint/BUILD.gn4
-rw-r--r--chromium/third_party/blink/renderer/core/paint/DEPS3
-rw-r--r--chromium/third_party/blink/renderer/core/paint/applied_decoration_painter.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/paint/background_image_geometry.cc63
-rw-r--r--chromium/third_party/blink/renderer/core/paint/background_image_geometry.h18
-rw-r--r--chromium/third_party/blink/renderer/core/paint/box_painter.cc30
-rw-r--r--chromium/third_party/blink/renderer/core/paint/box_painter_test.cc110
-rw-r--r--chromium/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.cc118
-rw-r--r--chromium/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.h4
-rw-r--r--chromium/third_party/blink/renderer/core/paint/compositing/compositing_inputs_updater.cc19
-rw-r--r--chromium/third_party/blink/renderer/core/paint/compositing/compositing_layer_assigner.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder.cc12
-rw-r--r--chromium/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder_test.cc36
-rw-r--r--chromium/third_party/blink/renderer/core/paint/compositing/compositing_requirements_updater.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/paint/compositing/compositing_test.cc147
-rw-r--r--chromium/third_party/blink/renderer/core/paint/compositing/graphics_layer_updater.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/paint/decoration_info.h7
-rw-r--r--chromium/third_party/blink/renderer/core/paint/filter_effect_builder.cc23
-rw-r--r--chromium/third_party/blink/renderer/core/paint/filter_effect_builder.h6
-rw-r--r--chromium/third_party/blink/renderer/core/paint/first_meaningful_paint_detector.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/paint/first_meaningful_paint_detector.h1
-rw-r--r--chromium/third_party/blink/renderer/core/paint/html_canvas_painter.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/paint/image_element_timing.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/paint/image_paint_timing_detector.cc14
-rw-r--r--chromium/third_party/blink/renderer/core/paint/image_paint_timing_detector.h12
-rw-r--r--chromium/third_party/blink/renderer/core/paint/image_paint_timing_detector_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/paint/image_painter.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/paint/line_box_list_painter.cc15
-rw-r--r--chromium/third_party/blink/renderer/core/paint/link_highlight_impl_test.cc12
-rw-r--r--chromium/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc321
-rw-r--r--chromium/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.h12
-rw-r--r--chromium/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter_test.cc50
-rw-r--r--chromium/third_party/blink/renderer/core/paint/ng/ng_inline_box_fragment_painter.cc18
-rw-r--r--chromium/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.cc136
-rw-r--r--chromium/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.h17
-rw-r--r--chromium/third_party/blink/renderer/core/paint/ng/ng_paint_fragment_test.cc206
-rw-r--r--chromium/third_party/blink/renderer/core/paint/object_painter_base.cc31
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_and_raster_invalidation_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_controller_paint_test.cc25
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_layer.cc135
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_layer.h33
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_layer_painter.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_layer_painter_test.cc198
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc73
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_layer_scrollable_area_test.cc134
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_layer_test.cc269
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc135
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_property_tree_builder_test.cc83
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_timing.cc14
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_timing.h2
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_timing_detector.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_timing_detector.h17
-rw-r--r--chromium/third_party/blink/renderer/core/paint/pre_paint_tree_walk.cc148
-rw-r--r--chromium/third_party/blink/renderer/core/paint/scoped_svg_paint_state.cc32
-rw-r--r--chromium/third_party/blink/renderer/core/paint/scoped_svg_paint_state.h22
-rw-r--r--chromium/third_party/blink/renderer/core/paint/scrollable_area_painter.cc21
-rw-r--r--chromium/third_party/blink/renderer/core/paint/scrollable_area_painter.h8
-rw-r--r--chromium/third_party/blink/renderer/core/paint/svg_filter_painter.cc76
-rw-r--r--chromium/third_party/blink/renderer/core/paint/svg_filter_painter.h54
-rw-r--r--chromium/third_party/blink/renderer/core/paint/text_paint_timing_detector_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/paint/text_painter_base.cc45
-rw-r--r--chromium/third_party/blink/renderer/core/paint/url_metadata_utils.cc28
-rw-r--r--chromium/third_party/blink/renderer/core/paint/url_metadata_utils.h22
-rw-r--r--chromium/third_party/blink/renderer/core/paint/video_painter_test.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/paint/view_painter.cc101
-rw-r--r--chromium/third_party/blink/renderer/core/paint/view_painter.h1
-rw-r--r--chromium/third_party/blink/renderer/core/probe/core_probes.h12
-rw-r--r--chromium/third_party/blink/renderer/core/probe/core_probes.json54
-rw-r--r--chromium/third_party/blink/renderer/core/probe/core_probes.pidl12
-rw-r--r--chromium/third_party/blink/renderer/core/resize_observer/resize_observation.cc14
-rw-r--r--chromium/third_party/blink/renderer/core/resize_observer/resize_observer.cc31
-rw-r--r--chromium/third_party/blink/renderer/core/resize_observer/resize_observer.h13
-rw-r--r--chromium/third_party/blink/renderer/core/resize_observer/resize_observer.idl2
-rw-r--r--chromium/third_party/blink/renderer/core/resize_observer/resize_observer_controller.cc20
-rw-r--r--chromium/third_party/blink/renderer/core/resize_observer/resize_observer_controller.h28
-rw-r--r--chromium/third_party/blink/renderer/core/resize_observer/resize_observer_entry.cc14
-rw-r--r--chromium/third_party/blink/renderer/core/resize_observer/resize_observer_size.idl3
-rw-r--r--chromium/third_party/blink/renderer/core/resize_observer/resize_observer_test.cc43
-rw-r--r--chromium/third_party/blink/renderer/core/scheduler_integration_tests/frame_throttling_test.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/script/classic_pending_script.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/script/document_modulator_impl.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/script/dynamic_module_resolver.cc101
-rw-r--r--chromium/third_party/blink/renderer/core/script/dynamic_module_resolver_test.cc41
-rw-r--r--chromium/third_party/blink/renderer/core/script/mock_script_element_base.h1
-rw-r--r--chromium/third_party/blink/renderer/core/script/modulator.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/script/modulator.h13
-rw-r--r--chromium/third_party/blink/renderer/core/script/modulator_impl_base.cc34
-rw-r--r--chromium/third_party/blink/renderer/core/script/modulator_impl_base.h3
-rw-r--r--chromium/third_party/blink/renderer/core/script/module_map_test.cc19
-rw-r--r--chromium/third_party/blink/renderer/core/script/module_record_resolver_impl_test.cc15
-rw-r--r--chromium/third_party/blink/renderer/core/script/module_script.cc12
-rw-r--r--chromium/third_party/blink/renderer/core/script/module_script_test.cc26
-rw-r--r--chromium/third_party/blink/renderer/core/script/pending_import_map.cc25
-rw-r--r--chromium/third_party/blink/renderer/core/script/pending_import_map.h10
-rw-r--r--chromium/third_party/blink/renderer/core/script/pending_script.cc31
-rw-r--r--chromium/third_party/blink/renderer/core/script/pending_script.h6
-rw-r--r--chromium/third_party/blink/renderer/core/script/script_element_base.h19
-rw-r--r--chromium/third_party/blink/renderer/core/script/script_loader.cc58
-rw-r--r--chromium/third_party/blink/renderer/core/script/script_runner.cc32
-rw-r--r--chromium/third_party/blink/renderer/core/script/script_runner_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/script/value_wrapper_synthetic_module_script.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/scroll/scroll_test.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/scroll/scrollbar.cc30
-rw-r--r--chromium/third_party/blink/renderer/core/scroll/scrollbar.h2
-rw-r--r--chromium/third_party/blink/renderer/core/scroll/scrollbar_layer_delegate.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/scroll/scrollbar_layer_delegate.h1
-rw-r--r--chromium/third_party/blink/renderer/core/scroll/scrollbar_theme.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/scroll/scrollbar_theme_aura_test.cc24
-rw-r--r--chromium/third_party/blink/renderer/core/scroll/scrollbar_theme_mac.mm2
-rw-r--r--chromium/third_party/blink/renderer/core/scroll/scrollbar_theme_overlay_test.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/streams/readable_stream_default_controller.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/streams/readable_stream_default_controller.h2
-rw-r--r--chromium/third_party/blink/renderer/core/streams/readable_stream_default_controller.idl5
-rw-r--r--chromium/third_party/blink/renderer/core/streams/readable_stream_test.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/streams/transform_stream_default_controller.cc15
-rw-r--r--chromium/third_party/blink/renderer/core/streams/transform_stream_default_controller.h2
-rw-r--r--chromium/third_party/blink/renderer/core/streams/transform_stream_default_controller.idl5
-rw-r--r--chromium/third_party/blink/renderer/core/streams/writable_stream.h8
-rw-r--r--chromium/third_party/blink/renderer/core/streams/writable_stream_default_controller.idl5
-rw-r--r--chromium/third_party/blink/renderer/core/streams/writable_stream_test.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/style/BUILD.gn2
-rw-r--r--chromium/third_party/blink/renderer/core/style/computed_style.cc93
-rw-r--r--chromium/third_party/blink/renderer/core/style/computed_style.h79
-rw-r--r--chromium/third_party/blink/renderer/core/style/computed_style_diff_functions.json512
-rw-r--r--chromium/third_party/blink/renderer/core/style/computed_style_extra_fields.json538
-rw-r--r--chromium/third_party/blink/renderer/core/style/computed_style_test.cc334
-rw-r--r--chromium/third_party/blink/renderer/core/style/style_fetched_image.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/style/style_fetched_image.h3
-rw-r--r--chromium/third_party/blink/renderer/core/style/style_inherited_variables.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/style/style_inherited_variables.h2
-rw-r--r--chromium/third_party/blink/renderer/core/style/style_initial_data.h4
-rw-r--r--chromium/third_party/blink/renderer/core/style/style_non_inherited_variables.h4
-rw-r--r--chromium/third_party/blink/renderer/core/style/style_variables.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/style/style_variables.h2
-rw-r--r--chromium/third_party/blink/renderer/core/style/style_variables_test.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/style/text_decoration_thickness.cc30
-rw-r--r--chromium/third_party/blink/renderer/core/style/text_decoration_thickness.h35
-rw-r--r--chromium/third_party/blink/renderer/core/svg/BUILD.gn2
-rw-r--r--chromium/third_party/blink/renderer/core/svg/animation/smil_time_container_test.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/svg/graphics/svg_image.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/svg/graphics/svg_image_test.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/svg/properties/svg_animated_property.cc13
-rw-r--r--chromium/third_party/blink/renderer/core/svg/properties/svg_animated_property.h6
-rw-r--r--chromium/third_party/blink/renderer/core/svg/properties/svg_list_property_helper.h33
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_animate_element.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_animate_element.idl4
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_animate_motion_element.idl4
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_animate_transform_element.idl4
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_animation_element.idl4
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_clip_path_element.idl4
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_component_transfer_function_element.idl3
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_element.cc104
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_element.h7
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_element_rare_data.h4
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_external_document_cache.cc134
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_external_document_cache.h89
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_external_document_cache_test.cc53
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_fe_blend_element.idl3
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_fe_color_matrix_element.idl3
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_fe_component_transfer_element.idl4
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_fe_composite_element.idl3
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_fe_convolve_matrix_element.idl3
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_fe_diffuse_lighting_element.idl4
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_fe_displacement_map_element.idl3
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_fe_distant_light_element.idl4
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_fe_drop_shadow_element.idl4
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_fe_flood_element.idl4
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_fe_func_a_element.idl4
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_fe_func_b_element.idl4
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_fe_func_g_element.idl4
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_fe_func_r_element.idl4
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_fe_gaussian_blur_element.idl4
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_fe_image_element.cc11
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_fe_image_element.h2
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_fe_image_element.idl4
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_fe_merge_element.idl4
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_fe_merge_node_element.idl4
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_fe_morphology_element.idl3
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_fe_offset_element.idl4
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_fe_point_light_element.idl4
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_fe_specular_lighting_element.idl4
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_fe_spot_light_element.idl4
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_fe_tile_element.idl4
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_fe_turbulence_element.idl3
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_filter_element.idl4
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_geometry_element.cc10
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_image_element.idl3
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_length.cc18
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_length.h1
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_mask_element.idl4
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_matrix.idl1
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_mpath_element.idl4
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_point.idl1
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_poly_element.cc10
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_rect.idl1
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_resource.cc46
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_resource.h21
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_script_element.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_script_element.h1
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_set_element.idl4
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_static_string_list.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_static_string_list.h1
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_svg_element.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_transform_list.cc12
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_tree_scope_resources.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_tree_scope_resources.h2
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_use_element.cc67
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_use_element.h14
-rw-r--r--chromium/third_party/blink/renderer/core/testing/core_unit_test_helper.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/testing/data/display_mode_listener.html20
-rw-r--r--chromium/third_party/blink/renderer/core/testing/data/fixed_layout.html8
-rw-r--r--chromium/third_party/blink/renderer/core/testing/data/iframe-display_mode.html6
-rw-r--r--chromium/third_party/blink/renderer/core/testing/data/iframe-display_mode_listener.html6
-rw-r--r--chromium/third_party/blink/renderer/core/testing/data/max-frames-detach.html7
-rw-r--r--chromium/third_party/blink/renderer/core/testing/data/mhtml/shadow.mht3
-rw-r--r--chromium/third_party/blink/renderer/core/testing/data/popup/select.html4
-rw-r--r--chromium/third_party/blink/renderer/core/testing/data/popup/select_event_remove_frame_on_change.html12
-rw-r--r--chromium/third_party/blink/renderer/core/testing/data/touch-action-tests.js6
-rw-r--r--chromium/third_party/blink/renderer/core/testing/data/two_scrollable_area.html27
-rw-r--r--chromium/third_party/blink/renderer/core/testing/data/viewport-and-media.html16
-rw-r--r--chromium/third_party/blink/renderer/core/testing/data/viewport-inside-media.html8
-rw-r--r--chromium/third_party/blink/renderer/core/testing/data/viewport-lengths.html7
-rw-r--r--chromium/third_party/blink/renderer/core/testing/data/viewport/viewport-legacy-ordering-10.html10
-rw-r--r--chromium/third_party/blink/renderer/core/testing/dictionary_test.cc64
-rw-r--r--chromium/third_party/blink/renderer/core/testing/dictionary_test.h17
-rw-r--r--chromium/third_party/blink/renderer/core/testing/dictionary_test.idl6
-rw-r--r--chromium/third_party/blink/renderer/core/testing/dummy_modulator.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/testing/dummy_modulator.h3
-rw-r--r--chromium/third_party/blink/renderer/core/testing/dummy_page_holder.cc10
-rw-r--r--chromium/third_party/blink/renderer/core/testing/fake_local_frame_host.cc20
-rw-r--r--chromium/third_party/blink/renderer/core/testing/fake_local_frame_host.h17
-rw-r--r--chromium/third_party/blink/renderer/core/testing/internals.cc32
-rw-r--r--chromium/third_party/blink/renderer/core/testing/internals.h6
-rw-r--r--chromium/third_party/blink/renderer/core/testing/internals.idl1
-rw-r--r--chromium/third_party/blink/renderer/core/testing/mock_clipboard_host.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/testing/mock_clipboard_host.h1
-rw-r--r--chromium/third_party/blink/renderer/core/testing/null_execution_context.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/testing/null_execution_context.h2
-rw-r--r--chromium/third_party/blink/renderer/core/testing/sim/sim_compositor.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/testing/sim/sim_compositor.h5
-rw-r--r--chromium/third_party/blink/renderer/core/timezone/timezone_controller.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/timing/BUILD.gn4
-rw-r--r--chromium/third_party/blink/renderer/core/timing/event_counts.cc103
-rw-r--r--chromium/third_party/blink/renderer/core/timing/event_counts.h49
-rw-r--r--chromium/third_party/blink/renderer/core/timing/event_counts.idl4
-rw-r--r--chromium/third_party/blink/renderer/core/timing/event_timing.cc30
-rw-r--r--chromium/third_party/blink/renderer/core/timing/largest_contentful_paint.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/timing/largest_contentful_paint.h14
-rw-r--r--chromium/third_party/blink/renderer/core/timing/layout_shift.cc23
-rw-r--r--chromium/third_party/blink/renderer/core/timing/layout_shift.h26
-rw-r--r--chromium/third_party/blink/renderer/core/timing/layout_shift.idl1
-rw-r--r--chromium/third_party/blink/renderer/core/timing/layout_shift_attribution.cc58
-rw-r--r--chromium/third_party/blink/renderer/core/timing/layout_shift_attribution.h43
-rw-r--r--chromium/third_party/blink/renderer/core/timing/layout_shift_attribution.idl13
-rw-r--r--chromium/third_party/blink/renderer/core/timing/measure_memory/measure_memory_delegate.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/timing/memory_info.h6
-rw-r--r--chromium/third_party/blink/renderer/core/timing/performance.cc94
-rw-r--r--chromium/third_party/blink/renderer/core/timing/performance.h36
-rw-r--r--chromium/third_party/blink/renderer/core/timing/performance.idl7
-rw-r--r--chromium/third_party/blink/renderer/core/timing/performance_element_timing.cc11
-rw-r--r--chromium/third_party/blink/renderer/core/timing/performance_event_timing.cc21
-rw-r--r--chromium/third_party/blink/renderer/core/timing/performance_event_timing.h9
-rw-r--r--chromium/third_party/blink/renderer/core/timing/performance_event_timing.idl1
-rw-r--r--chromium/third_party/blink/renderer/core/timing/performance_navigation.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/timing/performance_navigation.h2
-rw-r--r--chromium/third_party/blink/renderer/core/timing/performance_navigation_timing.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/timing/performance_navigation_timing_test.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/timing/performance_observer.cc31
-rw-r--r--chromium/third_party/blink/renderer/core/timing/performance_observer.h7
-rw-r--r--chromium/third_party/blink/renderer/core/timing/performance_observer_init.idl1
-rw-r--r--chromium/third_party/blink/renderer/core/timing/performance_observer_test.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/timing/performance_timing.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/timing/performance_timing.h2
-rw-r--r--chromium/third_party/blink/renderer/core/timing/performance_user_timing.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/timing/performance_user_timing.h5
-rw-r--r--chromium/third_party/blink/renderer/core/timing/profiler.cc12
-rw-r--r--chromium/third_party/blink/renderer/core/timing/profiler.h11
-rw-r--r--chromium/third_party/blink/renderer/core/timing/profiler_group.cc30
-rw-r--r--chromium/third_party/blink/renderer/core/timing/profiler_group.h4
-rw-r--r--chromium/third_party/blink/renderer/core/timing/window_performance.cc80
-rw-r--r--chromium/third_party/blink/renderer/core/timing/window_performance.h13
-rw-r--r--chromium/third_party/blink/renderer/core/timing/window_performance_test.cc60
-rw-r--r--chromium/third_party/blink/renderer/core/trustedtypes/trusted_html.idl3
-rw-r--r--chromium/third_party/blink/renderer/core/trustedtypes/trusted_script.idl3
-rw-r--r--chromium/third_party/blink/renderer/core/trustedtypes/trusted_script_url.idl3
-rw-r--r--chromium/third_party/blink/renderer/core/trustedtypes/trusted_type_policy.idl3
-rw-r--r--chromium/third_party/blink/renderer/core/trustedtypes/trusted_type_policy_factory.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/trustedtypes/trusted_type_policy_factory.idl3
-rw-r--r--chromium/third_party/blink/renderer/core/trustedtypes/trusted_types_util.cc52
-rw-r--r--chromium/third_party/blink/renderer/core/trustedtypes/trusted_types_util.h12
-rw-r--r--chromium/third_party/blink/renderer/core/trustedtypes/trusted_types_util_test.cc55
-rw-r--r--chromium/third_party/blink/renderer/core/typed_arrays/array_buffer/array_buffer_contents.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/workers/abstract_worker.cc13
-rw-r--r--chromium/third_party/blink/renderer/core/workers/abstract_worker.h11
-rw-r--r--chromium/third_party/blink/renderer/core/workers/dedicated_worker.cc29
-rw-r--r--chromium/third_party/blink/renderer/core/workers/dedicated_worker_global_scope.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/workers/dedicated_worker_test.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/workers/main_thread_worklet_reporting_proxy.cc18
-rw-r--r--chromium/third_party/blink/renderer/core/workers/main_thread_worklet_reporting_proxy.h6
-rw-r--r--chromium/third_party/blink/renderer/core/workers/main_thread_worklet_test.cc41
-rw-r--r--chromium/third_party/blink/renderer/core/workers/shared_worker.cc37
-rw-r--r--chromium/third_party/blink/renderer/core/workers/shared_worker.idl3
-rw-r--r--chromium/third_party/blink/renderer/core/workers/shared_worker_client.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/workers/shared_worker_client_holder.cc23
-rw-r--r--chromium/third_party/blink/renderer/core/workers/shared_worker_client_holder.h12
-rw-r--r--chromium/third_party/blink/renderer/core/workers/shared_worker_global_scope.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/workers/shared_worker_reporting_proxy.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/workers/threaded_worklet_messaging_proxy.cc29
-rw-r--r--chromium/third_party/blink/renderer/core/workers/threaded_worklet_test.cc54
-rw-r--r--chromium/third_party/blink/renderer/core/workers/worker_classic_script_loader.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/workers/worker_global_scope.cc14
-rw-r--r--chromium/third_party/blink/renderer/core/workers/worker_global_scope.h1
-rw-r--r--chromium/third_party/blink/renderer/core/workers/worker_global_scope.idl3
-rw-r--r--chromium/third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.cc69
-rw-r--r--chromium/third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.h13
-rw-r--r--chromium/third_party/blink/renderer/core/workers/worker_thread.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/workers/worker_thread.h5
-rw-r--r--chromium/third_party/blink/renderer/core/workers/worker_thread_test.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/workers/worklet.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/workers/worklet.h4
-rw-r--r--chromium/third_party/blink/renderer/core/workers/worklet.idl1
-rw-r--r--chromium/third_party/blink/renderer/core/workers/worklet_global_scope.cc37
-rw-r--r--chromium/third_party/blink/renderer/core/workers/worklet_global_scope.h22
-rw-r--r--chromium/third_party/blink/renderer/core/workers/worklet_module_tree_client.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/xml/document_xslt.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/xml/dom_parser.cc17
-rw-r--r--chromium/third_party/blink/renderer/core/xml/dom_parser.h10
-rw-r--r--chromium/third_party/blink/renderer/core/xml/dom_parser.idl2
-rw-r--r--chromium/third_party/blink/renderer/core/xml/xpath_evaluator.idl14
-rw-r--r--chromium/third_party/blink/renderer/core/xml/xpath_expression.idl6
-rw-r--r--chromium/third_party/blink/renderer/core/xml/xpath_result.idl6
-rw-r--r--chromium/third_party/blink/renderer/core/xml/xslt_processor.cc77
-rw-r--r--chromium/third_party/blink/renderer/core/xml/xslt_processor.idl1
-rw-r--r--chromium/third_party/blink/renderer/core/xmlhttprequest/main_thread_disallow_synchronous_xhr_scope.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.cc26
-rw-r--r--chromium/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.h7
-rw-r--r--chromium/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.idl3
1613 files changed, 41445 insertions, 22677 deletions
diff --git a/chromium/third_party/blink/renderer/core/BUILD.gn b/chromium/third_party/blink/renderer/core/BUILD.gn
index e9ef6e2aca7..432954cf39f 100644
--- a/chromium/third_party/blink/renderer/core/BUILD.gn
+++ b/chromium/third_party/blink/renderer/core/BUILD.gn
@@ -118,6 +118,7 @@ source_set("prerequisites") {
"//ui/display/mojom:mojom_blink",
"//ui/events:dom_keycode_converter",
"//ui/gfx/geometry",
+ "//ui/latency",
"//ui/native_theme",
"//url",
"//v8",
@@ -187,7 +188,6 @@ component("core") {
"//third_party/blink/renderer/core/input",
"//third_party/blink/renderer/core/inspector",
"//third_party/blink/renderer/core/intersection_observer",
- "//third_party/blink/renderer/core/invisible_dom",
"//third_party/blink/renderer/core/layout",
"//third_party/blink/renderer/core/layout/svg:svg_layout",
"//third_party/blink/renderer/core/loader",
@@ -248,7 +248,7 @@ jumbo_source_set("testing") {
":generated_testing_idls",
"//third_party/blink/renderer/bindings/core/v8:testing",
"//ui/base/cursor",
- "//ui/base/mojom:cursor_type_blink",
+ "//ui/base/cursor/mojom:cursor_type_blink",
]
sources = [
@@ -359,7 +359,6 @@ generate_event_interfaces("core_event_interfaces") {
"html/forms/form_data_event.idl",
"html/forms/submit_event.idl",
"html/track/track_event.idl",
- "invisible_dom/activate_invisible_event.idl",
"mojo/test/mojo_interface_request_event.idl",
]
@@ -824,16 +823,16 @@ blink_python_runner("make_core_generated_css_primitive_value_unit_trie") {
}
blink_python_runner("make_core_generated_feature_policy_helper") {
- script = "../build/scripts/make_feature_policy_helper.py"
+ script = "../build/scripts/make_policy_helper.py"
inputs = scripts_for_json5_files + [
- "../build/scripts/make_feature_policy_helper.py",
+ "../build/scripts/make_policy_helper.py",
"./feature_policy/feature_policy_features.json5",
"./feature_policy/document_policy_features.json5",
"../platform/runtime_enabled_features.json5",
- "../build/scripts/templates/feature_policy_helper.cc.tmpl",
+ "../build/scripts/templates/policy_helper.cc.tmpl",
]
- outputs = [ "$blink_core_output_dir/feature_policy/feature_policy_helper.cc" ]
+ outputs = [ "$blink_core_output_dir/feature_policy/policy_helper.cc" ]
args = [
rebase_path("../platform/runtime_enabled_features.json5", root_build_dir),
@@ -1047,10 +1046,12 @@ jumbo_source_set("unit_tests") {
sources = [
"clipboard/clipboard_utilities_test.cc",
"content_capture/content_capture_test.cc",
+ "css/css_revert_value_test.cc",
"css/css_test_helpers.cc",
"css/css_test_helpers.h",
"css/css_uri_value_test.cc",
"css/css_value_test_helper.h",
+ "css/font_display_auto_lcp_align_test.cc",
"css/mock_css_paint_image_generator.h",
"display_lock/display_lock_context_test.cc",
"display_lock/display_lock_utilities_test.cc",
@@ -1170,7 +1171,6 @@ jumbo_source_set("unit_tests") {
"geometry/dom_matrix_test.cc",
"imagebitmap/image_bitmap_test.cc",
"input/event_handler_test.cc",
- "input/fallback_cursor_event_manager_test.cc",
"input/ime_on_focus_test.cc",
"input/overscroll_behavior_test.cc",
"input/pointer_event_manager_test.cc",
@@ -1199,6 +1199,7 @@ jumbo_source_set("unit_tests") {
"layout/layout_embedded_content_test.cc",
"layout/layout_flexible_box_test.cc",
"layout/layout_geometry_map_test.cc",
+ "layout/layout_grid_test.cc",
"layout/layout_image_test.cc",
"layout/layout_inline_test.cc",
"layout/layout_media_test.cc",
@@ -1307,6 +1308,7 @@ jumbo_source_set("unit_tests") {
"messaging/blink_transferable_message_mojom_traits_test.cc",
"messaging/message_port_descriptor_mojom_traits_test.cc",
"origin_trials/origin_trial_context_test.cc",
+ "origin_trials/origin_trials_test.cc",
"page/autoscroll_controller_test.cc",
"page/chrome_client_impl_test.cc",
"page/chrome_client_test.cc",
@@ -1314,6 +1316,7 @@ jumbo_source_set("unit_tests") {
"page/drag_controller_test.cc",
"page/drag_image_test.cc",
"page/focus_controller_test.cc",
+ "page/named_pages_mapper_test.cc",
"page/page_popup_client_test.cc",
"page/plugin_data_test.cc",
"page/print_context_test.cc",
@@ -1416,6 +1419,7 @@ jumbo_source_set("unit_tests") {
"svg/animation/smil_time_container_test.cc",
"svg/animation/svg_smil_element_test.cc",
"svg/graphics/svg_image_test.cc",
+ "svg/svg_external_document_cache_test.cc",
"svg/svg_foreign_object_element_test.cc",
"svg/svg_path_parser_test.cc",
"svg/svg_path_query_test.cc",
@@ -1485,7 +1489,7 @@ jumbo_source_set("unit_tests") {
"//third_party/blink/renderer/core/fileapi:unit_tests",
"//third_party/blink/renderer/core/html:unit_tests",
"//ui/base/cursor",
- "//ui/base/mojom:cursor_type_blink",
+ "//ui/base/cursor/mojom:cursor_type_blink",
]
data_deps = [ ":unit_tests_data" ]
@@ -1651,16 +1655,6 @@ fuzzer_test("feature_policy_attr_fuzzer") {
"//third_party/blink/renderer/core/feature_policy/feature_policy_corpus"
}
-fuzzer_test("feature_policy_value_fuzzer") {
- sources = [ "feature_policy/feature_policy_value_fuzzer.cc" ]
- deps = [
- "//third_party/blink/renderer/platform:blink_fuzzer_test_support",
- "//third_party/icu",
- ]
- dict = "//third_party/blink/renderer/core/feature_policy/feature_policy_value.dict"
- seed_corpus = "//third_party/blink/renderer/core/feature_policy/feature_policy_value_corpus"
-}
-
fuzzer_test("document_policy_fuzzer") {
sources = [ "feature_policy/document_policy_fuzzer.cc" ]
deps = [
diff --git a/chromium/third_party/blink/renderer/core/DEPS b/chromium/third_party/blink/renderer/core/DEPS
index 391a21202df..ade19e141c6 100644
--- a/chromium/third_party/blink/renderer/core/DEPS
+++ b/chromium/third_party/blink/renderer/core/DEPS
@@ -12,8 +12,10 @@ include_rules = [
"+base/memory/scoped_refptr.h",
"+base/metrics/field_trial_params.h",
"+base/numerics/ranges.h",
+ "+base/profiler/sample_metadata.h",
"+base/strings/stringprintf.h",
"+base/synchronization/waitable_event.h",
+ "+base/values.h",
"+base/task/sequence_manager/task_time_observer.h",
"+base/test/bind_test_util.h",
"+base/test/simple_test_tick_clock.h",
@@ -48,7 +50,7 @@ include_rules = [
"+cc/layers/scrollbar_layer_base.h",
"+cc/layers/surface_layer.h",
"+cc/metrics/begin_main_frame_metrics.h",
- "+cc/metrics/frame_sequence_tracker.h",
+ "+cc/metrics/frame_sequence_tracker_collection.h",
"+cc/paint/display_item_list.h",
"+cc/paint/paint_canvas.h",
"+cc/paint/paint_flags.h",
@@ -57,6 +59,7 @@ include_rules = [
"+cc/trees/browser_controls_params.h",
"+cc/trees/layer_tree_host.h",
"+cc/trees/paint_holding_commit_trigger.h",
+ "+cc/trees/ukm_manager.h",
"+components/performance_manager/public/mojom/coordination_unit.mojom-blink.h",
"+gpu/config/gpu_feature_info.h",
"-inspector/v8",
@@ -70,8 +73,9 @@ include_rules = [
"+services/metrics/public",
"+services/network/public/cpp/cors/cors_error_status.h",
"+services/network/public/cpp/features.h",
- "+services/network/public/cpp/request_mode.h",
"+services/network/public/cpp/request_destination.h",
+ "+services/network/public/cpp/request_mode.h",
+ "+services/network/public/cpp/web_sandbox_flags.h",
"+services/network/public/cpp/shared_url_loader_factory.h",
"+services/resource_coordinator/public/mojom/coordination_unit.mojom-blink.h",
"+services/service_manager/public",
@@ -87,6 +91,10 @@ include_rules = [
"+third_party/blink/renderer/core",
"-third_party/blink/renderer/modules",
"+third_party/skia/include",
+ "+ui/accessibility/ax_enums.mojom-blink.h",
+ "+ui/accessibility/ax_enums.mojom-blink-forward.h",
+ "+ui/accessibility/ax_event.h",
+ "+ui/accessibility/ax_event_intent.h",
"+ui/base/cursor/cursor.h",
"+ui/base/ime/mojom/ime_types.mojom-blink.h",
"+ui/base/ime/mojom/ime_types.mojom-blink-forward.h",
@@ -95,6 +103,7 @@ include_rules = [
"+ui/display/mojom/display.mojom-blink.h",
"+ui/gfx/mac/cocoa_scrollbar_painter.h",
"+ui/gfx/geometry",
+ "+ui/gfx/range/range.h",
"+ui/gfx/skia_util.h",
"-web",
# We do not want any new dependencies into core/exported until we resolve
@@ -148,7 +157,7 @@ specific_include_rules = {
"html_canvas_painter_test.cc": [
"+components/viz/test/test_context_provider.h",
],
- "document.cc" : [
+ "local_dom_window.cc" : [
"+net/base/registry_controlled_domains/registry_controlled_domain.h",
],
"(computed_style|computed_style_test)\.cc" : [ "+ui/base/ui_base_features.h" ]
diff --git a/chromium/third_party/blink/renderer/core/accessibility/BUILD.gn b/chromium/third_party/blink/renderer/core/accessibility/BUILD.gn
index e5c0007e403..1b0ec440a5e 100644
--- a/chromium/third_party/blink/renderer/core/accessibility/BUILD.gn
+++ b/chromium/third_party/blink/renderer/core/accessibility/BUILD.gn
@@ -14,9 +14,21 @@ blink_core_sources("accessibility") {
"ax_object_cache.h",
"ax_object_cache_base.h",
"axid.h",
+ "blink_ax_event_intent.cc",
+ "blink_ax_event_intent.h",
+ "scoped_blink_ax_event_intent.cc",
+ "scoped_blink_ax_event_intent.h",
]
+
+ deps = [ "//ui/accessibility:ax_base" ]
}
blink_core_tests("unit_tests") {
- sources = [ "apply_dark_mode_test.cc" ]
+ sources = [
+ "apply_dark_mode_test.cc",
+ "blink_ax_event_intent_test.cc",
+ "scoped_blink_ax_event_intent_test.cc",
+ ]
+
+ deps = [ "//ui/accessibility:ax_base" ]
}
diff --git a/chromium/third_party/blink/renderer/core/accessibility/OWNERS b/chromium/third_party/blink/renderer/core/accessibility/OWNERS
new file mode 100644
index 00000000000..5eed66eb588
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/accessibility/OWNERS
@@ -0,0 +1,4 @@
+file://third_party/blink/renderer/modules/accessibility/OWNERS
+
+# TEAM: chromium-accessibility@chromium.org
+# COMPONENT: Blink>Accessibility
diff --git a/chromium/third_party/blink/renderer/core/accessibility/ax_object_cache.h b/chromium/third_party/blink/renderer/core/accessibility/ax_object_cache.h
index f0993e9a254..db8a56963b0 100644
--- a/chromium/third_party/blink/renderer/core/accessibility/ax_object_cache.h
+++ b/chromium/third_party/blink/renderer/core/accessibility/ax_object_cache.h
@@ -31,8 +31,10 @@
#include "base/macros.h"
#include "third_party/blink/renderer/core/accessibility/axid.h"
+#include "third_party/blink/renderer/core/accessibility/blink_ax_event_intent.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/dom/document.h"
+#include "third_party/blink/renderer/platform/wtf/hash_counted_set.h"
namespace blink {
@@ -48,6 +50,10 @@ class LocalFrameView;
class CORE_EXPORT AXObjectCache : public GarbageCollected<AXObjectCache> {
public:
+ using BlinkAXEventIntentsSet = HashCountedSet<BlinkAXEventIntent,
+ BlinkAXEventIntentHash,
+ BlinkAXEventIntentHashTraits>;
+
static AXObjectCache* Create(Document&);
virtual ~AXObjectCache() = default;
@@ -88,7 +94,7 @@ class CORE_EXPORT AXObjectCache : public GarbageCollected<AXObjectCache> {
virtual void DidInsertChildrenOfNode(Node*) = 0;
// Returns true if the AXObjectCache cares about this attribute
- virtual bool HandleAttributeChanged(const QualifiedName& attr_name,
+ virtual void HandleAttributeChanged(const QualifiedName& attr_name,
Element*) = 0;
virtual void HandleFocusedUIElementChanged(Element* old_focused_node,
Element* new_focused_node) = 0;
@@ -147,6 +153,19 @@ class CORE_EXPORT AXObjectCache : public GarbageCollected<AXObjectCache> {
// Static helper functions.
static bool IsInsideFocusableElementOrARIAWidget(const Node&);
+ protected:
+ friend class ScopedBlinkAXEventIntent;
+ FRIEND_TEST_ALL_PREFIXES(ScopedBlinkAXEventIntentTest, SingleIntent);
+ FRIEND_TEST_ALL_PREFIXES(ScopedBlinkAXEventIntentTest,
+ MultipleIdenticalIntents);
+ FRIEND_TEST_ALL_PREFIXES(ScopedBlinkAXEventIntentTest,
+ NestedIndividualIntents);
+ FRIEND_TEST_ALL_PREFIXES(ScopedBlinkAXEventIntentTest, NestedMultipleIntents);
+ FRIEND_TEST_ALL_PREFIXES(ScopedBlinkAXEventIntentTest,
+ NestedIdenticalIntents);
+
+ virtual BlinkAXEventIntentsSet& ActiveEventIntents() = 0;
+
private:
friend class AXObjectCacheBase;
AXObjectCache() = default;
@@ -157,4 +176,4 @@ class CORE_EXPORT AXObjectCache : public GarbageCollected<AXObjectCache> {
} // namespace blink
-#endif
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_ACCESSIBILITY_AX_OBJECT_CACHE_H_
diff --git a/chromium/third_party/blink/renderer/core/accessibility/blink_ax_event_intent.cc b/chromium/third_party/blink/renderer/core/accessibility/blink_ax_event_intent.cc
new file mode 100644
index 00000000000..4e7b6e5a136
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/accessibility/blink_ax_event_intent.cc
@@ -0,0 +1,229 @@
+// 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/core/accessibility/blink_ax_event_intent.h"
+
+#include <limits>
+
+#include "third_party/blink/renderer/platform/wtf/hash_functions.h"
+#include "ui/accessibility/ax_enums.mojom-blink.h"
+
+namespace blink {
+
+BlinkAXEventIntent BlinkAXEventIntent::FromClearedSelection(
+ const SetSelectionBy set_selection_by) {
+ // |text_boundary| and |move_direction| are not used in this case.
+ return BlinkAXEventIntent(ax::mojom::blink::Command::kClearSelection,
+ ax::mojom::blink::TextBoundary::kCharacter,
+ ax::mojom::blink::MoveDirection::kForward);
+}
+
+BlinkAXEventIntent BlinkAXEventIntent::FromModifiedSelection(
+ const SelectionModifyAlteration alter,
+ const SelectionModifyDirection direction,
+ const TextGranularity granularity,
+ const SetSelectionBy set_selection_by,
+ const TextDirection direction_of_selection) {
+ ax::mojom::blink::Command command;
+ switch (alter) {
+ case SelectionModifyAlteration::kExtend:
+ // Includes the case when the existing selection has been shrunk.
+ command = ax::mojom::blink::Command::kExtendSelection;
+ break;
+ case SelectionModifyAlteration::kMove:
+ // The existing selection has been move by a specific |granularity|, e.g.
+ // the caret has been moved to the beginning of the next word.
+ command = ax::mojom::blink::Command::kMoveSelection;
+ break;
+ }
+
+ ax::mojom::blink::MoveDirection move_direction;
+ switch (direction) {
+ case SelectionModifyDirection::kBackward:
+ move_direction = ax::mojom::blink::MoveDirection::kBackward;
+ break;
+ case SelectionModifyDirection::kForward:
+ move_direction = ax::mojom::blink::MoveDirection::kForward;
+ break;
+ case SelectionModifyDirection::kLeft:
+ move_direction = IsLtr(direction_of_selection)
+ ? ax::mojom::blink::MoveDirection::kBackward
+ : ax::mojom::blink::MoveDirection::kForward;
+ break;
+ case SelectionModifyDirection::kRight:
+ move_direction = IsLtr(direction_of_selection)
+ ? ax::mojom::blink::MoveDirection::kForward
+ : ax::mojom::blink::MoveDirection::kBackward;
+ break;
+ }
+
+ ax::mojom::blink::TextBoundary text_boundary;
+ switch (granularity) {
+ case TextGranularity::kCharacter:
+ text_boundary = ax::mojom::blink::TextBoundary::kCharacter;
+ break;
+ case TextGranularity::kWord:
+ switch (move_direction) {
+ case ax::mojom::blink::MoveDirection::kBackward:
+ text_boundary = ax::mojom::blink::TextBoundary::kWordStart;
+ break;
+ case ax::mojom::blink::MoveDirection::kForward:
+ text_boundary = ax::mojom::blink::TextBoundary::kWordEnd;
+ break;
+ }
+ break;
+ case TextGranularity::kSentence:
+ switch (move_direction) {
+ case ax::mojom::blink::MoveDirection::kBackward:
+ text_boundary = ax::mojom::blink::TextBoundary::kSentenceStart;
+ break;
+ case ax::mojom::blink::MoveDirection::kForward:
+ text_boundary = ax::mojom::blink::TextBoundary::kSentenceEnd;
+ break;
+ }
+ break;
+ case TextGranularity::kLine:
+ switch (move_direction) {
+ case ax::mojom::blink::MoveDirection::kBackward:
+ text_boundary = ax::mojom::blink::TextBoundary::kLineStart;
+ break;
+ case ax::mojom::blink::MoveDirection::kForward:
+ text_boundary = ax::mojom::blink::TextBoundary::kLineEnd;
+ break;
+ }
+ break;
+ case TextGranularity::kParagraph:
+ switch (move_direction) {
+ case ax::mojom::blink::MoveDirection::kBackward:
+ text_boundary = ax::mojom::blink::TextBoundary::kParagraphStart;
+ break;
+ case ax::mojom::blink::MoveDirection::kForward:
+ text_boundary = ax::mojom::blink::TextBoundary::kParagraphEnd;
+ break;
+ }
+ break;
+ case TextGranularity::kSentenceBoundary:
+ text_boundary = ax::mojom::blink::TextBoundary::kSentenceStartOrEnd;
+ break;
+ case TextGranularity::kLineBoundary:
+ text_boundary = ax::mojom::blink::TextBoundary::kLineStartOrEnd;
+ break;
+ case TextGranularity::kParagraphBoundary:
+ text_boundary = ax::mojom::blink::TextBoundary::kParagraphStartOrEnd;
+ break;
+ case TextGranularity::kDocumentBoundary:
+ text_boundary = ax::mojom::blink::TextBoundary::kWebPage;
+ break;
+ }
+
+ return BlinkAXEventIntent(command, text_boundary, move_direction);
+}
+
+BlinkAXEventIntent BlinkAXEventIntent::FromNewSelection(
+ const TextGranularity granularity,
+ bool is_base_first,
+ const SetSelectionBy set_selection_by) {
+ // Unfortunately, when setting a completely new selection, |text_boundary| is
+ // not always known, or is hard to compute. For example, if a new selection
+ // has been made using the mouse, it would be expensive to compute any
+ // meaningful granularity information.
+ ax::mojom::blink::TextBoundary text_boundary;
+ switch (granularity) {
+ case TextGranularity::kCharacter:
+ text_boundary = ax::mojom::blink::TextBoundary::kCharacter;
+ break;
+ case TextGranularity::kWord:
+ text_boundary = ax::mojom::blink::TextBoundary::kWordStartOrEnd;
+ break;
+ case TextGranularity::kSentence:
+ case TextGranularity::kSentenceBoundary:
+ text_boundary = ax::mojom::blink::TextBoundary::kSentenceStartOrEnd;
+ break;
+ case TextGranularity::kLine:
+ case TextGranularity::kLineBoundary:
+ text_boundary = ax::mojom::blink::TextBoundary::kLineStartOrEnd;
+ break;
+ case TextGranularity::kParagraph:
+ case TextGranularity::kParagraphBoundary:
+ text_boundary = ax::mojom::blink::TextBoundary::kParagraphStartOrEnd;
+ break;
+ case TextGranularity::kDocumentBoundary:
+ text_boundary = ax::mojom::blink::TextBoundary::kWebPage;
+ break;
+ }
+
+ return BlinkAXEventIntent(
+ ax::mojom::blink::Command::kSetSelection, text_boundary,
+ is_base_first ? ax::mojom::blink::MoveDirection::kForward
+ : ax::mojom::blink::MoveDirection::kBackward);
+}
+
+// Creates an empty (uninitialized) instance.
+BlinkAXEventIntent::BlinkAXEventIntent() = default;
+
+BlinkAXEventIntent::BlinkAXEventIntent(
+ ax::mojom::blink::Command command,
+ ax::mojom::blink::TextBoundary text_boundary,
+ ax::mojom::blink::MoveDirection move_direction)
+ : intent_(command, text_boundary, move_direction), is_initialized_(true) {}
+
+BlinkAXEventIntent::BlinkAXEventIntent(WTF::HashTableDeletedValueType type)
+ : is_initialized_(true), is_deleted_(true) {}
+
+BlinkAXEventIntent::~BlinkAXEventIntent() = default;
+
+BlinkAXEventIntent::BlinkAXEventIntent(const BlinkAXEventIntent& intent) =
+ default;
+
+BlinkAXEventIntent& BlinkAXEventIntent::operator=(
+ const BlinkAXEventIntent& intent) = default;
+
+bool operator==(const BlinkAXEventIntent& a, const BlinkAXEventIntent& b) {
+ return BlinkAXEventIntentHash::GetHash(a) ==
+ BlinkAXEventIntentHash::GetHash(b);
+}
+
+bool operator!=(const BlinkAXEventIntent& a, const BlinkAXEventIntent& b) {
+ return !(a == b);
+}
+
+bool BlinkAXEventIntent::IsHashTableDeletedValue() const {
+ return is_deleted_;
+}
+
+std::string BlinkAXEventIntent::ToString() const {
+ if (!is_initialized())
+ return "AXEventIntent(uninitialized)";
+ if (IsHashTableDeletedValue())
+ return "AXEventIntent(is_deleted)";
+ return intent().ToString();
+}
+
+// static
+unsigned int BlinkAXEventIntentHash::GetHash(const BlinkAXEventIntent& key) {
+ // If the intent is uninitialized, it is not safe to rely on the memory being
+ // initialized to zero, because any uninitialized field that might be
+ // accidentally added in the future will produce a potentially non-zero memory
+ // value especially in the hard to control "intent_" member.
+ if (!key.is_initialized())
+ return 0u;
+ if (key.IsHashTableDeletedValue())
+ return std::numeric_limits<unsigned>::max();
+
+ unsigned hash = 1u;
+ WTF::AddIntToHash(hash, static_cast<const unsigned>(key.intent().command));
+ WTF::AddIntToHash(hash,
+ static_cast<const unsigned>(key.intent().text_boundary));
+ WTF::AddIntToHash(hash,
+ static_cast<const unsigned>(key.intent().move_direction));
+ return hash;
+}
+
+// static
+bool BlinkAXEventIntentHash::Equal(const BlinkAXEventIntent& a,
+ const BlinkAXEventIntent& b) {
+ return a == b;
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/accessibility/blink_ax_event_intent.h b/chromium/third_party/blink/renderer/core/accessibility/blink_ax_event_intent.h
new file mode 100644
index 00000000000..7b4deacebdf
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/accessibility/blink_ax_event_intent.h
@@ -0,0 +1,111 @@
+// 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_CORE_ACCESSIBILITY_BLINK_AX_EVENT_INTENT_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_ACCESSIBILITY_BLINK_AX_EVENT_INTENT_H_
+
+#include <string>
+
+#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/core/editing/selection_modifier.h"
+#include "third_party/blink/renderer/core/editing/set_selection_options.h"
+#include "third_party/blink/renderer/core/editing/text_granularity.h"
+#include "third_party/blink/renderer/platform/text/text_direction.h"
+#include "third_party/blink/renderer/platform/wtf/hash_table_deleted_value_type.h"
+#include "third_party/blink/renderer/platform/wtf/hash_traits.h"
+#include "ui/accessibility/ax_enums.mojom-blink-forward.h"
+#include "ui/accessibility/ax_event.h"
+#include "ui/accessibility/ax_event_intent.h"
+
+namespace blink {
+
+// Adapts a ui::AXEventIntent for use in a Blink HashCountedSet.
+//
+// An event intent describes what caused an accessibility event to be raised.
+// For example, a character could have been typed, a word replaced, or a line
+// deleted. Or, the selection could have been extended to the beginning of the
+// previous word, or it could have been moved to the end of the next line.
+class CORE_EXPORT BlinkAXEventIntent final {
+ public:
+ static BlinkAXEventIntent FromClearedSelection(
+ const SetSelectionBy set_selection_by);
+ static BlinkAXEventIntent FromModifiedSelection(
+ const SelectionModifyAlteration alter,
+ const SelectionModifyDirection direction,
+ const TextGranularity granularity,
+ const SetSelectionBy set_selection_by,
+ const TextDirection direction_of_selection);
+ static BlinkAXEventIntent FromNewSelection(
+ const TextGranularity granularity,
+ bool is_base_first,
+ const SetSelectionBy set_selection_by);
+
+ BlinkAXEventIntent();
+ BlinkAXEventIntent(ax::mojom::blink::Command command,
+ ax::mojom::blink::TextBoundary text_boundary,
+ ax::mojom::blink::MoveDirection move_direction);
+
+ // Used by HashCountedSet to create a deleted BlinkAXEventIntent instance.
+ explicit BlinkAXEventIntent(WTF::HashTableDeletedValueType type);
+
+ virtual ~BlinkAXEventIntent();
+
+ BlinkAXEventIntent(const BlinkAXEventIntent& intent);
+ BlinkAXEventIntent& operator=(const BlinkAXEventIntent& intent);
+
+ CORE_EXPORT friend bool operator==(const BlinkAXEventIntent& a,
+ const BlinkAXEventIntent& b);
+ CORE_EXPORT friend bool operator!=(const BlinkAXEventIntent& a,
+ const BlinkAXEventIntent& b);
+
+ const ui::AXEventIntent& intent() const { return intent_; }
+ ui::AXEventIntent& intent() { return intent_; }
+
+ // Returns "true" if this represents an initialized BlinkAXEventIntent
+ // instance.
+ bool is_initialized() const { return is_initialized_; }
+
+ // Returns "true" if this represents a deleted BlinkAXEventIntent instance.
+ bool IsHashTableDeletedValue() const;
+
+ // Returns a string representation of this instance.
+ std::string ToString() const;
+
+ private:
+ ui::AXEventIntent intent_;
+
+ // Set to "true" if this represents an initialized BlinkAXEventIntent
+ // instance. An empty (uninitialized) instance is created either by calling
+ // the default constructor or by simply zeroing out a block of memory
+ // equivalent to the size of this class. The latter may be done by the HashSet
+ // for performance reasons.
+ //
+ // This member is needed so that our hash function will never return the same
+ // value for an uninitialized and an initialized instance. Otherwise an
+ // uninitialized instance's memory may have random values.
+ bool is_initialized_ = false;
+
+ // Set to "true" if this represents a deleted BlinkAXEventIntent instance.
+ bool is_deleted_ = false;
+};
+
+struct CORE_EXPORT BlinkAXEventIntentHash final {
+ // Computes the hash of a BlinkAXEventIntent instance.
+ static unsigned GetHash(const BlinkAXEventIntent& key);
+ // Used by HashSet to compare two BlinkAXEventIntent instances.
+ static bool Equal(const BlinkAXEventIntent& a, const BlinkAXEventIntent& b);
+ // We support creating and comparing with empty (uninitialized) and deleted
+ // HashSet BlinkAXEventIntent entries.
+ static constexpr bool safe_to_compare_to_empty_or_deleted = true;
+};
+
+struct CORE_EXPORT BlinkAXEventIntentHashTraits final
+ : WTF::SimpleClassHashTraits<BlinkAXEventIntent> {
+ // Zeroed memory cannot be used for BlinkAXEventIntent.
+ static constexpr bool kEmptyValueIsZero = false;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_ACCESSIBILITY_BLINK_AX_EVENT_INTENT_H_
diff --git a/chromium/third_party/blink/renderer/core/accessibility/blink_ax_event_intent_test.cc b/chromium/third_party/blink/renderer/core/accessibility/blink_ax_event_intent_test.cc
new file mode 100644
index 00000000000..4d2a3defbb5
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/accessibility/blink_ax_event_intent_test.cc
@@ -0,0 +1,71 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/accessibility/blink_ax_event_intent.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/platform/wtf/hash_table_deleted_value_type.h"
+#include "ui/accessibility/ax_enums.mojom-blink.h"
+
+namespace blink {
+namespace test {
+
+TEST(BlinkAXEventIntentTest, Equality) {
+ BlinkAXEventIntent intent1(ax::mojom::blink::Command::kCut,
+ ax::mojom::blink::TextBoundary::kWordEnd,
+ ax::mojom::blink::MoveDirection::kForward);
+ BlinkAXEventIntent intent2(ax::mojom::blink::Command::kSetSelection,
+ ax::mojom::blink::TextBoundary::kWordEnd,
+ ax::mojom::blink::MoveDirection::kForward);
+ BlinkAXEventIntent intent3(ax::mojom::blink::Command::kSetSelection,
+ ax::mojom::blink::TextBoundary::kWordEnd,
+ ax::mojom::blink::MoveDirection::kForward);
+
+ EXPECT_NE(BlinkAXEventIntentHash::GetHash(intent1),
+ BlinkAXEventIntentHash::GetHash(intent2));
+ EXPECT_NE(BlinkAXEventIntentHash::GetHash(intent1),
+ BlinkAXEventIntentHash::GetHash(intent3));
+ EXPECT_EQ(BlinkAXEventIntentHash::GetHash(intent2),
+ BlinkAXEventIntentHash::GetHash(intent3));
+
+ EXPECT_FALSE(BlinkAXEventIntentHash::Equal(intent1, intent2));
+ EXPECT_FALSE(BlinkAXEventIntentHash::Equal(intent1, intent3));
+ EXPECT_TRUE(BlinkAXEventIntentHash::Equal(intent2, intent3));
+}
+
+TEST(BlinkAXEventIntentTest, EqualityWithEmptyValue) {
+ BlinkAXEventIntent intent1(ax::mojom::blink::Command::kCut,
+ ax::mojom::blink::TextBoundary::kWordEnd,
+ ax::mojom::blink::MoveDirection::kForward);
+ // Empty values.
+ BlinkAXEventIntent intent2;
+ BlinkAXEventIntent intent3;
+
+ EXPECT_NE(BlinkAXEventIntentHash::GetHash(intent1),
+ BlinkAXEventIntentHash::GetHash(intent2));
+ EXPECT_FALSE(BlinkAXEventIntentHash::Equal(intent1, intent2));
+
+ EXPECT_EQ(BlinkAXEventIntentHash::GetHash(intent2),
+ BlinkAXEventIntentHash::GetHash(intent3));
+ EXPECT_TRUE(BlinkAXEventIntentHash::Equal(intent2, intent3));
+}
+
+TEST(BlinkAXEventIntentTest, EqualityWithDeletedValue) {
+ BlinkAXEventIntent intent1(ax::mojom::blink::Command::kCut,
+ ax::mojom::blink::TextBoundary::kWordEnd,
+ ax::mojom::blink::MoveDirection::kForward);
+ BlinkAXEventIntent intent2(WTF::kHashTableDeletedValue);
+ BlinkAXEventIntent intent3(WTF::kHashTableDeletedValue);
+
+ EXPECT_NE(BlinkAXEventIntentHash::GetHash(intent1),
+ BlinkAXEventIntentHash::GetHash(intent2));
+ EXPECT_FALSE(BlinkAXEventIntentHash::Equal(intent1, intent2));
+
+ EXPECT_EQ(BlinkAXEventIntentHash::GetHash(intent2),
+ BlinkAXEventIntentHash::GetHash(intent3));
+ EXPECT_TRUE(BlinkAXEventIntentHash::Equal(intent2, intent3));
+}
+
+} // namespace test
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/accessibility/scoped_blink_ax_event_intent.cc b/chromium/third_party/blink/renderer/core/accessibility/scoped_blink_ax_event_intent.cc
new file mode 100644
index 00000000000..11f599ff8b1
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/accessibility/scoped_blink_ax_event_intent.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/core/accessibility/scoped_blink_ax_event_intent.h"
+
+#include "base/macros.h"
+#include "third_party/blink/renderer/core/accessibility/ax_object_cache.h"
+
+namespace blink {
+
+ScopedBlinkAXEventIntent::ScopedBlinkAXEventIntent(
+ const BlinkAXEventIntent& intent,
+ Document* document)
+ : document_(document) {
+ DCHECK(document_);
+ DCHECK(document_->IsActive());
+
+ if (!intent.is_initialized())
+ return;
+ intents_.push_back(intent);
+
+ if (AXObjectCache* cache = document_->ExistingAXObjectCache()) {
+ AXObjectCache::BlinkAXEventIntentsSet& active_intents =
+ cache->ActiveEventIntents();
+ active_intents.insert(intent);
+ }
+}
+
+ScopedBlinkAXEventIntent::ScopedBlinkAXEventIntent(
+ const Vector<BlinkAXEventIntent>& intents,
+ Document* document)
+ : intents_(intents), document_(document) {
+ DCHECK(document_);
+ DCHECK(document_->IsActive());
+ if (AXObjectCache* cache = document_->ExistingAXObjectCache()) {
+ AXObjectCache::BlinkAXEventIntentsSet& active_intents =
+ cache->ActiveEventIntents();
+
+ for (const auto& intent : intents) {
+ if (intent.is_initialized())
+ active_intents.insert(intent);
+ }
+ }
+}
+
+ScopedBlinkAXEventIntent::~ScopedBlinkAXEventIntent() {
+ // If a conservative GC is required, |document_| may become nullptr.
+ if (!document_ || !document_->IsActive())
+ return;
+
+ if (AXObjectCache* cache = document_->ExistingAXObjectCache()) {
+ AXObjectCache::BlinkAXEventIntentsSet& active_intents =
+ cache->ActiveEventIntents();
+
+ for (const auto& intent : intents_) {
+ DCHECK(active_intents.Contains(intent));
+ active_intents.erase(intent);
+ }
+ }
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/accessibility/scoped_blink_ax_event_intent.h b/chromium/third_party/blink/renderer/core/accessibility/scoped_blink_ax_event_intent.h
new file mode 100644
index 00000000000..c3005146258
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/accessibility/scoped_blink_ax_event_intent.h
@@ -0,0 +1,54 @@
+// 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_CORE_ACCESSIBILITY_SCOPED_BLINK_AX_EVENT_INTENT_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_ACCESSIBILITY_SCOPED_BLINK_AX_EVENT_INTENT_H_
+
+#include "third_party/blink/renderer/core/accessibility/blink_ax_event_intent.h"
+#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/core/dom/document.h"
+#include "third_party/blink/renderer/platform/heap/handle.h"
+#include "third_party/blink/renderer/platform/heap/persistent.h"
+#include "third_party/blink/renderer/platform/wtf/vector.h"
+
+namespace blink {
+
+// Annotates all accessibility events that are raised while an instance of this
+// class is alive with a specific intent or intents. Multiple instances with
+// different intents could be alive at the same time.
+//
+// An event intent is a description of what caused an accessibility event and
+// may include user actions such as paste, or page actions such as a text
+// insertion. Before firing a bunch of accessibility events that have the same
+// cause, create an instance of ScopedBlinkAXEventIntent. Multiple event intents
+// could be in effect at the same time, such as "selection move" and "text
+// insertion". As long as an instance of ScopedBlinkAXEventIntent is alive, all
+// accessibility events that are raised will be annotated with the same intent
+// or intents.
+class CORE_EXPORT ScopedBlinkAXEventIntent final {
+ STACK_ALLOCATED();
+
+ public:
+ ScopedBlinkAXEventIntent(const BlinkAXEventIntent& intent,
+ Document* document);
+ ScopedBlinkAXEventIntent(const Vector<BlinkAXEventIntent>& intents,
+ Document* document);
+ virtual ~ScopedBlinkAXEventIntent();
+ ScopedBlinkAXEventIntent(const ScopedBlinkAXEventIntent& intent) = delete;
+ ScopedBlinkAXEventIntent& operator=(const ScopedBlinkAXEventIntent& intent) =
+ delete;
+
+ const Vector<BlinkAXEventIntent>& intents() const { return intents_; }
+
+ private:
+ Vector<BlinkAXEventIntent> intents_;
+
+ // This class is stack allocated, and therefore no WeakPersistent handle is
+ // required for |document_| and no trace method is necessary.
+ Document* const document_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_ACCESSIBILITY_SCOPED_BLINK_AX_EVENT_INTENT_H_
diff --git a/chromium/third_party/blink/renderer/core/accessibility/scoped_blink_ax_event_intent_test.cc b/chromium/third_party/blink/renderer/core/accessibility/scoped_blink_ax_event_intent_test.cc
new file mode 100644
index 00000000000..21d75313c9f
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/accessibility/scoped_blink_ax_event_intent_test.cc
@@ -0,0 +1,199 @@
+// 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/core/accessibility/scoped_blink_ax_event_intent.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/core/accessibility/ax_context.h"
+#include "third_party/blink/renderer/core/accessibility/ax_object_cache.h"
+#include "third_party/blink/renderer/core/accessibility/blink_ax_event_intent.h"
+#include "third_party/blink/renderer/core/dom/document.h"
+#include "third_party/blink/renderer/core/testing/core_unit_test_helper.h"
+#include "ui/accessibility/ax_enums.mojom-blink.h"
+
+namespace blink {
+
+using ScopedBlinkAXEventIntentTest = RenderingTest;
+
+TEST_F(ScopedBlinkAXEventIntentTest, SingleIntent) {
+ AXContext ax_context(GetDocument());
+ AXObjectCache* cache = GetDocument().ExistingAXObjectCache();
+ ASSERT_NE(nullptr, cache);
+
+ {
+ ScopedBlinkAXEventIntent scoped_intent(
+ {ax::mojom::blink::Command::kCut,
+ ax::mojom::blink::TextBoundary::kWordEnd,
+ ax::mojom::blink::MoveDirection::kForward},
+ &GetDocument());
+
+ EXPECT_TRUE(
+ cache->ActiveEventIntents().Contains(scoped_intent.intents()[0]));
+ EXPECT_EQ(1u, cache->ActiveEventIntents().size());
+ }
+
+ EXPECT_TRUE(cache->ActiveEventIntents().IsEmpty());
+}
+
+TEST_F(ScopedBlinkAXEventIntentTest, MultipleIdenticalIntents) {
+ AXContext ax_context(GetDocument());
+ AXObjectCache* cache = GetDocument().ExistingAXObjectCache();
+ ASSERT_NE(nullptr, cache);
+
+ {
+ ScopedBlinkAXEventIntent scoped_intent(
+ {{ax::mojom::blink::Command::kCut,
+ ax::mojom::blink::TextBoundary::kWordEnd,
+ ax::mojom::blink::MoveDirection::kForward},
+ {ax::mojom::blink::Command::kCut,
+ ax::mojom::blink::TextBoundary::kWordEnd,
+ ax::mojom::blink::MoveDirection::kForward}},
+ &GetDocument());
+
+ EXPECT_TRUE(
+ cache->ActiveEventIntents().Contains(scoped_intent.intents()[0]));
+ EXPECT_EQ(2u,
+ cache->ActiveEventIntents().count(scoped_intent.intents()[0]));
+ EXPECT_EQ(1u, cache->ActiveEventIntents().size());
+ }
+
+ EXPECT_TRUE(cache->ActiveEventIntents().IsEmpty());
+}
+
+TEST_F(ScopedBlinkAXEventIntentTest, NestedIndividualIntents) {
+ AXContext ax_context(GetDocument());
+ AXObjectCache* cache = GetDocument().ExistingAXObjectCache();
+ ASSERT_NE(nullptr, cache);
+
+ {
+ ScopedBlinkAXEventIntent scoped_intent1(
+ {ax::mojom::blink::Command::kType,
+ ax::mojom::blink::TextBoundary::kCharacter,
+ ax::mojom::blink::MoveDirection::kForward},
+ &GetDocument());
+
+ {
+ ScopedBlinkAXEventIntent scoped_intent2(
+ {ax::mojom::blink::Command::kCut,
+ ax::mojom::blink::TextBoundary::kWordEnd,
+ ax::mojom::blink::MoveDirection::kForward},
+ &GetDocument());
+
+ EXPECT_TRUE(
+ cache->ActiveEventIntents().Contains(scoped_intent1.intents()[0]));
+ EXPECT_TRUE(
+ cache->ActiveEventIntents().Contains(scoped_intent2.intents()[0]));
+ EXPECT_EQ(1u,
+ cache->ActiveEventIntents().count(scoped_intent1.intents()[0]));
+ EXPECT_EQ(1u,
+ cache->ActiveEventIntents().count(scoped_intent2.intents()[0]));
+ EXPECT_EQ(2u, cache->ActiveEventIntents().size());
+ }
+
+ EXPECT_TRUE(
+ cache->ActiveEventIntents().Contains(scoped_intent1.intents()[0]));
+ EXPECT_EQ(1u,
+ cache->ActiveEventIntents().count(scoped_intent1.intents()[0]));
+ EXPECT_EQ(1u, cache->ActiveEventIntents().size());
+ }
+
+ EXPECT_TRUE(cache->ActiveEventIntents().IsEmpty());
+}
+
+TEST_F(ScopedBlinkAXEventIntentTest, NestedMultipleIntents) {
+ AXContext ax_context(GetDocument());
+ AXObjectCache* cache = GetDocument().ExistingAXObjectCache();
+ ASSERT_NE(nullptr, cache);
+
+ {
+ ScopedBlinkAXEventIntent scoped_intent1(
+ {{ax::mojom::blink::Command::kType,
+ ax::mojom::blink::TextBoundary::kCharacter,
+ ax::mojom::blink::MoveDirection::kForward},
+ {ax::mojom::blink::Command::kSetSelection,
+ ax::mojom::blink::TextBoundary::kWordEnd,
+ ax::mojom::blink::MoveDirection::kForward}},
+ &GetDocument());
+
+ {
+ ScopedBlinkAXEventIntent scoped_intent2(
+ {{ax::mojom::blink::Command::kCut,
+ ax::mojom::blink::TextBoundary::kWordEnd,
+ ax::mojom::blink::MoveDirection::kForward},
+ {ax::mojom::blink::Command::kClearSelection,
+ ax::mojom::blink::TextBoundary::kWordEnd,
+ ax::mojom::blink::MoveDirection::kForward}},
+ &GetDocument());
+
+ EXPECT_TRUE(
+ cache->ActiveEventIntents().Contains(scoped_intent1.intents()[0]));
+ EXPECT_TRUE(
+ cache->ActiveEventIntents().Contains(scoped_intent1.intents()[1]));
+ EXPECT_TRUE(
+ cache->ActiveEventIntents().Contains(scoped_intent2.intents()[0]));
+ EXPECT_TRUE(
+ cache->ActiveEventIntents().Contains(scoped_intent2.intents()[1]));
+ EXPECT_EQ(1u,
+ cache->ActiveEventIntents().count(scoped_intent1.intents()[0]));
+ EXPECT_EQ(1u,
+ cache->ActiveEventIntents().count(scoped_intent1.intents()[1]));
+ EXPECT_EQ(1u,
+ cache->ActiveEventIntents().count(scoped_intent2.intents()[0]));
+ EXPECT_EQ(1u,
+ cache->ActiveEventIntents().count(scoped_intent2.intents()[1]));
+ EXPECT_EQ(4u, cache->ActiveEventIntents().size());
+ }
+
+ EXPECT_TRUE(
+ cache->ActiveEventIntents().Contains(scoped_intent1.intents()[0]));
+ EXPECT_TRUE(
+ cache->ActiveEventIntents().Contains(scoped_intent1.intents()[1]));
+ EXPECT_EQ(1u,
+ cache->ActiveEventIntents().count(scoped_intent1.intents()[0]));
+ EXPECT_EQ(1u,
+ cache->ActiveEventIntents().count(scoped_intent1.intents()[1]));
+ EXPECT_EQ(2u, cache->ActiveEventIntents().size());
+ }
+
+ EXPECT_TRUE(cache->ActiveEventIntents().IsEmpty());
+}
+
+TEST_F(ScopedBlinkAXEventIntentTest, NestedIdenticalIntents) {
+ AXContext ax_context(GetDocument());
+ AXObjectCache* cache = GetDocument().ExistingAXObjectCache();
+ ASSERT_NE(nullptr, cache);
+
+ {
+ ScopedBlinkAXEventIntent scoped_intent1(
+ {ax::mojom::blink::Command::kType,
+ ax::mojom::blink::TextBoundary::kCharacter,
+ ax::mojom::blink::MoveDirection::kForward},
+ &GetDocument());
+
+ {
+ // Create a second, identical intent.
+ ScopedBlinkAXEventIntent scoped_intent2(
+ {ax::mojom::blink::Command::kType,
+ ax::mojom::blink::TextBoundary::kCharacter,
+ ax::mojom::blink::MoveDirection::kForward},
+ &GetDocument());
+
+ EXPECT_TRUE(
+ cache->ActiveEventIntents().Contains(scoped_intent1.intents()[0]));
+ EXPECT_EQ(2u,
+ cache->ActiveEventIntents().count(scoped_intent1.intents()[0]));
+ EXPECT_EQ(1u, cache->ActiveEventIntents().size());
+ }
+
+ EXPECT_TRUE(
+ cache->ActiveEventIntents().Contains(scoped_intent1.intents()[0]));
+ EXPECT_EQ(1u,
+ cache->ActiveEventIntents().count(scoped_intent1.intents()[0]));
+ EXPECT_EQ(1u, cache->ActiveEventIntents().size());
+ }
+
+ EXPECT_TRUE(cache->ActiveEventIntents().IsEmpty());
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/animation/BUILD.gn b/chromium/third_party/blink/renderer/core/animation/BUILD.gn
index d2a6c96563d..b2cd411ccd6 100644
--- a/chromium/third_party/blink/renderer/core/animation/BUILD.gn
+++ b/chromium/third_party/blink/renderer/core/animation/BUILD.gn
@@ -35,6 +35,8 @@ blink_core_sources("animation") {
"animation_time_delta.h",
"animation_timeline.cc",
"animation_timeline.h",
+ "animation_utils.cc",
+ "animation_utils.h",
"basic_shape_interpolation_functions.cc",
"basic_shape_interpolation_functions.h",
"color_property_functions.cc",
@@ -56,6 +58,8 @@ blink_core_sources("animation") {
"css/css_animation_update.h",
"css/css_animations.cc",
"css/css_animations.h",
+ "css/css_keyframe_effect_model.cc",
+ "css/css_keyframe_effect_model.h",
"css/css_timing_data.cc",
"css/css_timing_data.h",
"css/css_transition.cc",
@@ -206,6 +210,8 @@ blink_core_sources("animation") {
"sampled_effect.h",
"scroll_timeline.cc",
"scroll_timeline.h",
+ "scroll_timeline_offset.cc",
+ "scroll_timeline_offset.h",
"scroll_timeline_util.cc",
"scroll_timeline_util.h",
"side_index.h",
@@ -278,6 +284,7 @@ blink_core_tests("unit_tests") {
"animation_test_helper.cc",
"animation_test_helper.h",
"animation_time_delta_test.cc",
+ "animation_utils_test.cc",
"compositor_animations_test.cc",
"css/css_animations_test.cc",
"css/css_transition_data_test.cc",
diff --git a/chromium/third_party/blink/renderer/core/animation/OWNERS b/chromium/third_party/blink/renderer/core/animation/OWNERS
index 35dc357ee11..ef3593179c5 100644
--- a/chromium/third_party/blink/renderer/core/animation/OWNERS
+++ b/chromium/third_party/blink/renderer/core/animation/OWNERS
@@ -1,4 +1,5 @@
flackr@chromium.org
+kevers@chromium.org
majidvp@chromium.org
smcgruer@chromium.org
diff --git a/chromium/third_party/blink/renderer/core/animation/animation.cc b/chromium/third_party/blink/renderer/core/animation/animation.cc
index 56a74a8418a..b17d3bddbd4 100644
--- a/chromium/third_party/blink/renderer/core/animation/animation.cc
+++ b/chromium/third_party/blink/renderer/core/animation/animation.cc
@@ -37,13 +37,17 @@
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/renderer/core/animation/animation_timeline.h"
+#include "third_party/blink/renderer/core/animation/animation_utils.h"
+#include "third_party/blink/renderer/core/animation/css/css_animation.h"
#include "third_party/blink/renderer/core/animation/css/css_animations.h"
+#include "third_party/blink/renderer/core/animation/css/css_transition.h"
#include "third_party/blink/renderer/core/animation/document_timeline.h"
#include "third_party/blink/renderer/core/animation/element_animations.h"
#include "third_party/blink/renderer/core/animation/keyframe_effect.h"
#include "third_party/blink/renderer/core/animation/pending_animations.h"
#include "third_party/blink/renderer/core/animation/scroll_timeline.h"
#include "third_party/blink/renderer/core/animation/scroll_timeline_util.h"
+#include "third_party/blink/renderer/core/animation/timing_calculations.h"
#include "third_party/blink/renderer/core/css/properties/css_property_ref.h"
#include "third_party/blink/renderer/core/css/resolver/style_resolver.h"
#include "third_party/blink/renderer/core/css/style_change_reason.h"
@@ -97,14 +101,14 @@ double Min(base::Optional<double> a, double b) {
return b;
}
-PseudoPriority ConvertStringtoPriority(const String& pseudo) {
- if (pseudo.IsNull())
+PseudoPriority ConvertPseudoIdtoPriority(const PseudoId& pseudo) {
+ if (pseudo == kPseudoIdNone)
return PseudoPriority::kNone;
- if (pseudo == "::marker")
+ if (pseudo == kPseudoIdMarker)
return PseudoPriority::kMarker;
- if (pseudo == "::before")
+ if (pseudo == kPseudoIdBefore)
return PseudoPriority::kBefore;
- if (pseudo == "::after")
+ if (pseudo == kPseudoIdAfter)
return PseudoPriority::kAfter;
return PseudoPriority::kOther;
}
@@ -156,6 +160,25 @@ void RecordCompositorAnimationFailureReasons(
}
}
}
+
+Element* OriginatingElement(Element* owning_element) {
+ if (owning_element->IsPseudoElement()) {
+ return owning_element->parentElement();
+ }
+ return owning_element;
+}
+
+AtomicString GetCSSTransitionCSSPropertyName(const Animation* animation) {
+ CSSPropertyID property_id =
+ To<CSSTransition>(animation)->TransitionCSSProperty().PropertyID();
+ if (property_id == CSSPropertyID::kVariable ||
+ property_id == CSSPropertyID::kInvalid)
+ return AtomicString();
+ return To<CSSTransition>(animation)
+ ->TransitionCSSProperty()
+ .GetCSSPropertyName()
+ .ToAtomicString();
+}
} // namespace
Animation* Animation::Create(AnimationEffect* effect,
@@ -214,6 +237,7 @@ Animation::Animation(ExecutionContext* execution_context,
has_queued_microtask_(false),
outdated_(false),
finished_(true),
+ committed_finish_notification_(false),
compositor_state_(nullptr),
compositor_pending_(false),
compositor_group_(0),
@@ -266,15 +290,12 @@ Document* Animation::GetDocument() const {
}
base::Optional<double> Animation::TimelineTime() const {
- return timeline_ ? timeline_->CurrentTime() : base::nullopt;
+ return timeline_ ? timeline_->currentTime() : base::nullopt;
}
// https://drafts.csswg.org/web-animations/#setting-the-current-time-of-an-animation.
-void Animation::setCurrentTimeForBinding(
- base::Optional<double> new_current_time,
- ExceptionState& exception_state) {
- // TODO(crbug.com/924159): Update this after we add support for inactive
- // timelines and unresolved timeline.currentTime
+void Animation::setCurrentTime(base::Optional<double> new_current_time,
+ ExceptionState& exception_state) {
if (!new_current_time) {
// If the current time is resolved, then throw a TypeError.
if (CurrentTimeInternal()) {
@@ -305,20 +326,9 @@ void Animation::setCurrentTimeForBinding(
NotifyProbe();
}
-void Animation::setCurrentTimeForBinding(double new_current_time,
- bool is_null,
- ExceptionState& exception_state) {
- setCurrentTimeForBinding(
- is_null ? base::nullopt : base::make_optional(new_current_time),
- exception_state);
-}
-
-void Animation::setCurrentTime(double new_current_time,
- bool is_null,
- ExceptionState& exception_state) {
- setCurrentTimeForBinding(
- is_null ? base::nullopt : base::make_optional(new_current_time),
- exception_state);
+void Animation::setCurrentTime(base::Optional<double> new_current_time) {
+ NonThrowableExceptionState exception_state;
+ setCurrentTime(new_current_time, exception_state);
}
// https://drafts.csswg.org/web-animations/#setting-the-current-time-of-an-animation
@@ -355,14 +365,8 @@ base::Optional<double> Animation::startTime() const {
: base::nullopt;
}
-double Animation::startTime(bool& is_null) const {
- base::Optional<double> result = startTime();
- is_null = !result;
- return result.value_or(0);
-}
-
// https://drafts.csswg.org/web-animations/#the-current-time-of-an-animation
-base::Optional<double> Animation::currentTimeForBinding() const {
+base::Optional<double> Animation::currentTime() const {
// 1. If the animation’s hold time is resolved,
// The current time is the animation’s hold time.
if (hold_time_.has_value())
@@ -389,22 +393,6 @@ base::Optional<double> Animation::currentTimeForBinding() const {
return SecondsToMilliseconds(current_time);
}
-double Animation::currentTimeForBinding(bool& is_null) {
- base::Optional<double> result = currentTimeForBinding();
- is_null = !result;
- return result.value_or(0);
-}
-
-double Animation::currentTime() const {
- return currentTimeForBinding().value_or(Timing::NullValue());
-}
-
-double Animation::currentTime(bool& is_null) {
- base::Optional<double> result = currentTimeForBinding();
- is_null = !result;
- return result.value_or(0);
-}
-
base::Optional<double> Animation::CurrentTimeInternal() const {
return hold_time_ ? hold_time_ : CalculateCurrentTime();
}
@@ -423,10 +411,6 @@ bool Animation::PreCommit(
int compositor_group,
const PaintArtifactCompositor* paint_artifact_compositor,
bool start_on_compositor) {
- // TODO(crbug.com/916117): Revisit this condition as part of handling
- // inactive timelines work.
- if (timeline_ && timeline_->IsScrollTimeline() && !timeline_->IsActive())
- return false;
bool soft_change =
compositor_state_ &&
@@ -476,7 +460,7 @@ bool Animation::PreCommit(
return true;
}
-void Animation::PostCommit(double timeline_time) {
+void Animation::PostCommit() {
compositor_pending_ = false;
if (!compositor_state_ || compositor_state_->pending_action == kNone)
@@ -493,10 +477,10 @@ bool Animation::HasLowerCompositeOrdering(
const Animation* animation1,
const Animation* animation2,
CompareAnimationsOrdering compare_animation_type) {
- AnimationClassPriority priority1 = AnimationPriority(*animation1);
- AnimationClassPriority priority2 = AnimationPriority(*animation2);
- if (priority1 != priority2)
- return priority1 < priority2;
+ AnimationClassPriority anim_priority1 = AnimationPriority(*animation1);
+ AnimationClassPriority anim_priority2 = AnimationPriority(*animation2);
+ if (anim_priority1 != anim_priority2)
+ return anim_priority1 < anim_priority2;
// If the the animation class is CssAnimation or CssTransition, then first
// compare the owning element of animation1 and animation2, sort two of them
@@ -504,49 +488,74 @@ bool Animation::HasLowerCompositeOrdering(
// The specs:
// https://drafts.csswg.org/css-animations-2/#animation-composite-order
// https://drafts.csswg.org/css-transitions-2/#animation-composite-order
- if (priority1 != kDefaultPriority && animation1->effect() &&
- animation2->effect()) {
- // TODO(crbug.com/1043778): Implement and use OwningElement on CSSAnimation
- // and CSSTransition.
- auto* effect1 = DynamicTo<KeyframeEffect>(animation1->effect());
- auto* effect2 = DynamicTo<KeyframeEffect>(animation2->effect());
- Element* target1 = effect1->target();
- Element* target2 = effect2->target();
-
- // The tree position comparison would take a longer time, thus affec the
+ if (anim_priority1 != kDefaultPriority) {
+ Element* owning_element1 = animation1->OwningElement();
+ Element* owning_element2 = animation2->OwningElement();
+
+ // Both animations are either CSS transitions or CSS animations with owning
+ // elements.
+ DCHECK(owning_element1 && owning_element2);
+ Element* originating_element1 = OriginatingElement(owning_element1);
+ Element* originating_element2 = OriginatingElement(owning_element2);
+
+ // The tree position comparison would take a longer time, thus affect the
// performance. We only do it when it comes to getAnimation.
- if (*target1 != *target2) {
+ if (originating_element1 != originating_element2) {
if (compare_animation_type == CompareAnimationsOrdering::kTreeOrder) {
- return target1->compareDocumentPosition(target2) &
+ // Since pseudo elements are compared by their originating element,
+ // they sort before their children.
+ return originating_element1->compareDocumentPosition(
+ originating_element2) &
Node::kDocumentPositionFollowing;
} else {
- return target1 < target2;
+ return originating_element1 < originating_element2;
}
}
// A pseudo-element has a higher composite ordering than its originating
- // element, but lower than the originating element's children.
+ // element, hence kPseudoIdNone is sorted earliest.
// Two pseudo-elements sharing the same originating element are sorted
// as follows:
// ::marker
// ::before
// other pseudo-elements (ordered by selector)
// ::after
- const String& pseudo1 = effect1->pseudoElement();
- const String& pseudo2 = effect2->pseudoElement();
- PseudoPriority priority1 = ConvertStringtoPriority(pseudo1);
- PseudoPriority priority2 = ConvertStringtoPriority(pseudo2);
+ const PseudoId pseudo1 = owning_element1->GetPseudoId();
+ const PseudoId pseudo2 = owning_element2->GetPseudoId();
+ PseudoPriority priority1 = ConvertPseudoIdtoPriority(pseudo1);
+ PseudoPriority priority2 = ConvertPseudoIdtoPriority(pseudo2);
if (priority1 != priority2)
return priority1 < priority2;
- if (priority1 == kOther && pseudo1 != pseudo2)
- return CodeUnitCompareLessThan(pseudo1, pseudo2);
-
- // For two animatiions with the same target (including the pseudo-element
- // selector) compare the SequenceNumber for now.
- // TODO(crbug.com/1045835): Sort animation1 and animation2 based on their
- // position in the computed value of "animation-name" property for
- // CSSAnimations and transition property for CSSTransitions.
+
+ // The following if statement is not reachable, but the implementation
+ // matches the specification for composite ordering
+ if (priority1 == kOther && pseudo1 != pseudo2) {
+ return CodeUnitCompareLessThan(
+ PseudoElement::PseudoElementNameForEvents(pseudo1),
+ PseudoElement::PseudoElementNameForEvents(pseudo2));
+ }
+ if (anim_priority1 == kCssAnimationPriority) {
+ // When comparing two CSSAnimations with the same owning element, we sort
+ // A and B based on their position in the computed value of the
+ // animation-name property of the (common) owning element.
+ return To<CSSAnimation>(animation1)->AnimationIndex() <
+ To<CSSAnimation>(animation2)->AnimationIndex();
+ } else {
+ // First compare the transition generation of two transitions, then
+ // compare them by the property name.
+ if (To<CSSTransition>(animation1)->TransitionGeneration() !=
+ To<CSSTransition>(animation2)->TransitionGeneration()) {
+ return To<CSSTransition>(animation1)->TransitionGeneration() <
+ To<CSSTransition>(animation2)->TransitionGeneration();
+ }
+ AtomicString css_property_name1 =
+ GetCSSTransitionCSSPropertyName(animation1);
+ AtomicString css_property_name2 =
+ GetCSSTransitionCSSPropertyName(animation2);
+ if (css_property_name1 && css_property_name2)
+ return css_property_name1.Utf8() < css_property_name2.Utf8();
+ }
return animation1->SequenceNumber() < animation2->SequenceNumber();
}
// If the anmiations are not-CSS WebAnimation just compare them via generation
@@ -707,16 +716,6 @@ base::Optional<double> Animation::CalculateCurrentTime() const {
// https://drafts.csswg.org/web-animations/#setting-the-start-time-of-an-animation
void Animation::setStartTime(base::Optional<double> start_time_ms,
ExceptionState& exception_state) {
- // TODO(crbug.com/916117): Implement setting start time for scroll-linked
- // animations.
- if (timeline_ && timeline_->IsScrollTimeline()) {
- exception_state.ThrowDOMException(
- DOMExceptionCode::kNotSupportedError,
- "Scroll-linked WebAnimation currently does not support setting start"
- " time.");
- return;
- }
-
bool had_start_time = start_time_.has_value();
// 1. Let timeline time be the current time value of the timeline that
@@ -743,8 +742,15 @@ void Animation::setStartTime(base::Optional<double> start_time_ms,
// 5. Set animation’s start time to new start time.
base::Optional<double> new_start_time;
- if (start_time_ms)
+ if (start_time_ms) {
new_start_time = MillisecondsToSeconds(start_time_ms.value());
+ // Snap to timeline time if within floating point tolerance to ensure
+ // deterministic behavior in phase transitions.
+ if (timeline_time && IsWithinAnimationTimeEpsilon(timeline_time.value(),
+ new_start_time.value())) {
+ new_start_time = timeline_time.value();
+ }
+ }
start_time_ = new_start_time;
// 6. Update animation’s hold time based on the first matching condition from
@@ -779,23 +785,21 @@ void Animation::setStartTime(base::Optional<double> start_time_ms,
// Update user agent.
base::Optional<double> new_current_time = CurrentTimeInternal();
- if (previous_current_time != new_current_time) {
+ // Even when the animation is not outdated,call SetOutdated to ensure
+ // the animation is tracked by its timeline for future timing
+ // updates.
+ if (previous_current_time != new_current_time ||
+ (!had_start_time && start_time_)) {
SetOutdated();
- } else if (!had_start_time && start_time_) {
- // Even though this animation is not outdated, time to effect change is
- // infinity until start time is set.
- ForceServiceOnNextFrame();
}
SetCompositorPending(/*effect_changed=*/false);
NotifyProbe();
}
-void Animation::setStartTime(double start_time_ms,
- bool is_null,
- ExceptionState& exception_state) {
- setStartTime(is_null ? base::nullopt : base::make_optional(start_time_ms),
- exception_state);
+void Animation::setStartTime(base::Optional<double> start_time_ms) {
+ NonThrowableExceptionState exception_state;
+ setStartTime(start_time_ms, exception_state);
}
// https://drafts.csswg.org/web-animations-1/#setting-the-associated-effect
@@ -926,10 +930,11 @@ const char* Animation::PlayStateString(AnimationPlayState play_state) {
Animation::AnimationPlayState Animation::CalculateAnimationPlayState() const {
// 1. All of the following conditions are true:
// * The current time of animation is unresolved, and
+ // * the start time of animation is unresolved, and
// * animation does not have either a pending play task or a pending pause
// task,
// then idle.
- if (!CurrentTimeInternal() && !PendingInternal())
+ if (!CurrentTimeInternal() && !start_time_ && !PendingInternal())
return kIdle;
// 2. Either of the following conditions are true:
@@ -1004,18 +1009,36 @@ void Animation::pause(ExceptionState& exception_state) {
if (pending_pause_ || CalculateAnimationPlayState() == kPaused)
return;
- // 3. If the animation’s current time is unresolved, perform the steps
+ // 3. Let has finite timeline be true if animation has an associated timeline
+ // that is not monotonically increasing.
+ bool has_finite_timeline =
+ timeline_ && !timeline_->IsMonotonicallyIncreasing();
+
+ // 4. If the animation’s current time is unresolved, perform the steps
// according to the first matching condition from below:
- // 3a. If animation’s playback rate is ≥ 0,
- // Let animation’s hold time be zero.
- // 3b. Otherwise,
- // If associated effect end for animation is positive infinity, throw an
- // "InvalidStateError" DOMException and abort these steps. Otherwise,
- // let animation’s hold time be associated effect end.
+ // 4a. If animation’s playback rate is ≥ 0,
+ // Update either animation’s start time or hold time as follows:
+ // If has finite timeline is true,
+ // Set animation’s start time to zero.
+ // Otherwise,
+ // Set animation’s hold time to zero.
+ // 4b. Otherwise,
+ // If associated effect end for animation is positive infinity,
+ // throw an "InvalidStateError" DOMException and abort these
+ // steps.
+ // Otherwise,
+ // Update either animation’s start time or hold time as follows:
+ // If has finite timeline is true,
+ // let animation’s start time be associated effect end.
+ // Otherwise,
+ // let animation’s hold time be associated effect end.
base::Optional<double> current_time = CurrentTimeInternal();
if (!current_time) {
if (playback_rate_ >= 0) {
- hold_time_ = 0;
+ if (has_finite_timeline)
+ start_time_ = 0;
+ else
+ hold_time_ = 0;
} else {
if (EffectEnd() == std::numeric_limits<double>::infinity()) {
exception_state.ThrowDOMException(
@@ -1023,30 +1046,35 @@ void Animation::pause(ExceptionState& exception_state) {
"Cannot play reversed Animation with infinite target effect end.");
return;
}
- hold_time_ = EffectEnd();
+ if (has_finite_timeline)
+ start_time_ = EffectEnd();
+ else
+ hold_time_ = EffectEnd();
}
}
- // 4. Let has pending ready promise be a boolean flag that is initially false.
- // 5. If animation has a pending play task, cancel that task and let has
+ // 5. Let has pending ready promise be a boolean flag that is initially false.
+ // 6. If animation has a pending play task, cancel that task and let has
// pending ready promise be true.
- // 6. If has pending ready promise is false, set animation’s current ready
+ // 7. If has pending ready promise is false, set animation’s current ready
// promise to a new promise in the relevant Realm of animation.
if (pending_play_)
pending_play_ = false;
else if (ready_promise_)
ready_promise_->Reset();
- // 7. Schedule a task to be executed at the first possible moment after the
- // user agent has performed any processing necessary to suspend the
- // playback of animation’s associated effect, if any.
+ // 8. Schedule a task to be executed at the first possible moment where both
+ // of the following conditions are true:
+ // 8a. the user agent has performed any processing necessary to suspend
+ // the playback of animation’s associated effect, if any.
+ // 8b. the animation is associated with a timeline that is not inactive.
pending_pause_ = true;
pending_play_ = false;
SetOutdated();
SetCompositorPending(false);
- // 8. Run the procedure to update an animation’s finished state for animation
+ // 9. Run the procedure to update an animation’s finished state for animation
// with the did seek flag set to false (continuous) , and thesynchronously
// notify flag set to false.
UpdateFinishedState(UpdateType::kContinuous, NotificationType::kAsync);
@@ -1079,51 +1107,63 @@ void Animation::PlayInternal(AutoRewind auto_rewind,
// 1. Let aborted pause be a boolean flag that is true if animation has a
// pending pause task, and false otherwise.
// 2. Let has pending ready promise be a boolean flag that is initially false.
+ // 3. Let performed seek be a boolean flag that is initially false.
+ // 4. Let has finite timeline be true if animation has an associated timeline
+ // that is not monotonically increasing.
bool aborted_pause = pending_pause_;
bool has_pending_ready_promise = false;
+ bool performed_seek = false;
+ bool has_finite_timeline =
+ timeline_ && !timeline_->IsMonotonicallyIncreasing();
- // 3. Perform the steps corresponding to the first matching condition from the
+ // 5. Perform the steps corresponding to the first matching condition from the
// following, if any:
//
- // 3a If animation’s effective playback rate > 0, the auto-rewind flag is true
+ // 5a If animation’s effective playback rate > 0, the auto-rewind flag is true
// and either animation’s:
// current time is unresolved, or
// current time < zero, or
// current time ≥ target effect end,
- // Set animation’s hold time to zero.
+ // 5a1. Set performed seek to true.
+ // 5a2. Update either animation’s start time or hold time as follows:
+ // If has finite timeline is true,
+ // Set animation’s start time to zero.
+ // Otherwise,
+ // Set animation’s hold time to zero.
//
- // 3b If animation’s effective playback rate < 0, the auto-rewind flag is true
+ // 5b If animation’s effective playback rate < 0, the auto-rewind flag is true
// and either animation’s:
// current time is unresolved, or
// current time ≤ zero, or
// current time > target effect end,
- // If target effect end is positive infinity, throw an "InvalidStateError"
- // DOMException and abort these steps. Otherwise, set animation’s hold time
- // to target effect end.
+ // 5b1.If associated effect end is positive infinity,
+ // throw an "InvalidStateError" DOMException and abort these steps.
+ // 5b2.Otherwise,
+ // 5b2a Set performed seek to true.
+ // 5b2b Update either animation’s start time or hold time as follows:
+ // If has finite timeline is true,
+ // Set animation’s start time to associated effect end.
+ // Otherwise,
+ // Set animation’s hold time to associated effect end.
//
- // 3c If animation’s effective playback rate = 0 and animation’s current time
+ // 5c If animation’s effective playback rate = 0 and animation’s current time
// is unresolved,
- // Set animation’s hold time to zero.
+ // 5c1. Set performed seek to true.
+ // 5c2. Update either animation’s start time or hold time as follows:
+ // If has finite timeline is true,
+ // Set animation’s start time to zero.
+ // Otherwise,
+ // Set animation’s hold time to zero.
double effective_playback_rate = EffectivePlaybackRate();
base::Optional<double> current_time = CurrentTimeInternal();
- // TODO(crbug.com/1012073): This should be able to be extracted into a
- // function in AnimationTimeline that each child class can override for their
- // own special behavior.
- double initial_hold_time = 0;
- if (timeline_ && timeline_->IsScrollTimeline() && timeline_->IsActive()) {
- base::Optional<double> timeline_time = timeline_->CurrentTimeSeconds();
- if (timeline_time) {
- // TODO(crbug.com/924159): Once inactive timelines are supported we need
- // to re-evaluate if it is desired behavior to adjust the hold time when
- // playback rate is set before play().
- initial_hold_time = timeline_time.value() * effective_playback_rate;
- }
- }
-
if (effective_playback_rate > 0 && auto_rewind == AutoRewind::kEnabled &&
(!current_time || current_time < 0 || current_time >= EffectEnd())) {
- hold_time_ = initial_hold_time;
+ performed_seek = true;
+ if (has_finite_timeline)
+ start_time_ = 0;
+ else
+ hold_time_ = 0;
} else if (effective_playback_rate < 0 &&
auto_rewind == AutoRewind::kEnabled &&
(!current_time || current_time <= 0 ||
@@ -1134,43 +1174,54 @@ void Animation::PlayInternal(AutoRewind auto_rewind,
"Cannot play reversed Animation with infinite target effect end.");
return;
}
- hold_time_ = initial_hold_time + EffectEnd();
+ performed_seek = true;
+ if (has_finite_timeline)
+ start_time_ = EffectEnd();
+ else
+ hold_time_ = EffectEnd();
} else if (effective_playback_rate == 0 && !current_time) {
- hold_time_ = initial_hold_time;
+ performed_seek = true;
+ if (has_finite_timeline)
+ start_time_ = 0;
+ else
+ hold_time_ = 0;
}
- // 4. If animation has a pending play task or a pending pause task,
- // 4.1 Cancel that task.
- // 4.2 Set has pending ready promise to true.
+ // 6. If animation has a pending play task or a pending pause task,
+ // 6.1 Cancel that task.
+ // 6.2 Set has pending ready promise to true.
if (pending_play_ || pending_pause_) {
pending_play_ = pending_pause_ = false;
has_pending_ready_promise = true;
}
- // 5. If the following three conditions are all satisfied:
+ // 7. If the following three conditions are all satisfied:
// animation’s hold time is unresolved, and
+ // performed seek is false, and
// aborted pause is false, and
// animation does not have a pending playback rate,
// abort this procedure.
- if (!hold_time_ && !aborted_pause && !pending_playback_rate_)
+ if (!hold_time_ && !performed_seek && !aborted_pause &&
+ !pending_playback_rate_)
return;
- // 6. If animation’s hold time is resolved, let its start time be unresolved.
+ // 8. If animation’s hold time is resolved, let its start time be unresolved.
if (hold_time_)
start_time_ = base::nullopt;
- // 7. If has pending ready promise is false, let animation’s current ready
+ // 9. If has pending ready promise is false, let animation’s current ready
// promise be a new promise in the relevant Realm of animation.
if (ready_promise_ && !has_pending_ready_promise)
ready_promise_->Reset();
- // 8. Schedule a task to run as soon as animation is ready.
+ // 10. Schedule a task to run as soon as animation is ready.
pending_play_ = true;
finished_ = false;
+ committed_finish_notification_ = false;
SetOutdated();
SetCompositorPending(/*effect_changed=*/false);
- // 9. Run the procedure to update an animation’s finished state for animation
+ // 11. Run the procedure to update an animation’s finished state for animation
// with the did seek flag set to false, and the synchronously notify flag
// set to false.
// Boolean valued arguments replaced with enumerated values for clarity.
@@ -1312,15 +1363,18 @@ void Animation::UpdateFinishedState(UpdateType update_type,
// 4. Set the current finished state.
AnimationPlayState play_state = CalculateAnimationPlayState();
if (play_state == kFinished) {
- // 5. Setup finished notification.
- if (notification_type == NotificationType::kSync)
- CommitFinishNotification();
- else
- ScheduleAsyncFinish();
+ if (!committed_finish_notification_) {
+ // 5. Setup finished notification.
+ if (notification_type == NotificationType::kSync)
+ CommitFinishNotification();
+ else
+ ScheduleAsyncFinish();
+ }
} else {
// 6. If not finished but the current finished promise is already resolved,
// create a new promise.
- finished_ = pending_finish_notification_ = false;
+ finished_ = pending_finish_notification_ = committed_finish_notification_ =
+ false;
if (finished_promise_ &&
finished_promise_->GetState() == AnimationPromise::kResolved) {
finished_promise_->Reset();
@@ -1359,6 +1413,9 @@ void Animation::AsyncFinishMicrotask() {
// Refer to 'finished notification steps' in
// https://drafts.csswg.org/web-animations-1/#updating-the-finished-state
void Animation::CommitFinishNotification() {
+ if (committed_finish_notification_)
+ return;
+
pending_finish_notification_ = false;
// 1. If animation’s play state is not equal to finished, abort these steps.
@@ -1373,6 +1430,8 @@ void Animation::CommitFinishNotification() {
// 3. Create an AnimationPlaybackEvent, finishEvent.
QueueFinishedEvent();
+
+ committed_finish_notification_ = true;
}
// https://drafts.csswg.org/web-animations/#setting-the-playback-rate-of-an-animation
@@ -1548,9 +1607,6 @@ void Animation::ApplyPendingPlaybackRate() {
void Animation::setPlaybackRate(double playback_rate,
ExceptionState& exception_state) {
- // TODO(crbug.com/924159): Update this after we add support for inactive
- // timelines and unresolved timeline.currentTime
-
base::Optional<double> start_time_before = start_time_;
// 1. Clear any pending playback rate on animation.
@@ -1560,10 +1616,10 @@ void Animation::setPlaybackRate(double playback_rate,
// 4. If previous time is resolved, set the current time of animation to
// previous time
pending_playback_rate_ = base::nullopt;
- double previous_current_time = currentTime();
+ double previous_current_time = currentTime().value_or(Timing::NullValue());
playback_rate_ = playback_rate;
if (!Timing::IsNull(previous_current_time)) {
- setCurrentTime(previous_current_time, false, exception_state);
+ setCurrentTime(previous_current_time, exception_state);
}
// Adds a UseCounter to check if setting playbackRate causes a compensatory
@@ -1644,8 +1700,8 @@ Animation::CheckCanStartAnimationOnCompositorInternal() const {
// reason to composite it. Additionally, mutating the timeline playback rate
// is a debug feature available via devtools; we don't support this on the
// compositor currently and there is no reason to do so.
- auto* document_timeline = DynamicTo<DocumentTimeline>(*timeline_);
- if (!document_timeline || document_timeline->PlaybackRate() != 1)
+ if (timeline_->IsDocumentTimeline() &&
+ To<DocumentTimeline>(*timeline_).PlaybackRate() != 1)
reasons |= CompositorAnimations::kInvalidAnimationOrEffect;
// An Animation without an effect cannot produce a visual, so there is no
@@ -1658,10 +1714,6 @@ Animation::CheckCanStartAnimationOnCompositorInternal() const {
if (!Playing())
reasons |= CompositorAnimations::kInvalidAnimationOrEffect;
- // TODO(crbug.com/916117): Support accelerated scroll linked animations.
- if (timeline_->IsScrollTimeline())
- reasons |= CompositorAnimations::kInvalidAnimationOrEffect;
-
return reasons;
}
@@ -1669,7 +1721,6 @@ void Animation::StartAnimationOnCompositor(
const PaintArtifactCompositor* paint_artifact_compositor) {
DCHECK_EQ(CheckCanStartAnimationOnCompositor(paint_artifact_compositor),
CompositorAnimations::kNoFailure);
- DCHECK(IsA<DocumentTimeline>(*timeline_));
bool reversed = EffectivePlaybackRate() < 0;
@@ -1683,11 +1734,7 @@ void Animation::StartAnimationOnCompositor(
// Asynchronous updates have an associated pending play or pending pause
// task associated with them.
if (start_time_ && !PendingInternal()) {
- start_time = To<DocumentTimeline>(*timeline_)
- .ZeroTime()
- .since_origin()
- .InSecondsF() +
- start_time_.value();
+ start_time = timeline_->ZeroTimeInSeconds() + start_time_.value();
if (reversed) {
start_time =
start_time.value() - (EffectEnd() / fabs(EffectivePlaybackRate()));
@@ -1793,7 +1840,7 @@ bool Animation::Update(TimingUpdateReason reason) {
UpdateFinishedState(UpdateType::kContinuous, NotificationType::kAsync);
if (content_) {
- base::Optional<double> inherited_time = idle || !timeline_->CurrentTime()
+ base::Optional<double> inherited_time = idle || !timeline_->currentTime()
? base::nullopt
: CurrentTimeInternal();
@@ -1824,7 +1871,12 @@ bool Animation::Update(TimingUpdateReason reason) {
DCHECK(!outdated_);
NotifyProbe();
- return !finished_ || TimeToEffectChange();
+ return !finished_ || TimeToEffectChange() ||
+ // Always return true for not idle animations attached to not
+ // monotonically increasing timelines even if the animation is
+ // finished. This is required to accommodate cases where timeline ticks
+ // back in time.
+ (!idle && !timeline_->IsMonotonicallyIncreasing());
}
void Animation::QueueFinishedEvent() {
@@ -1965,6 +2017,8 @@ void Animation::AttachCompositorTimeline() {
return;
compositor_timeline->AnimationAttached(*this);
+ // Note that while we attach here but we don't detach because the
+ // |compositor_timeline| is detached in its destructor.
if (compositor_timeline->GetAnimationTimeline()->IsScrollTimeline())
document_->AttachCompositorTimeline(compositor_timeline);
}
@@ -1978,33 +2032,16 @@ void Animation::DetachCompositorTimeline() {
return;
compositor_timeline->AnimationDestroyed(*this);
-
- if (compositor_timeline->GetAnimationTimeline()->IsScrollTimeline())
- document_->DetachCompositorTimeline(compositor_timeline);
}
void Animation::UpdateCompositorScrollTimeline() {
if (!compositor_animation_ || !timeline_)
return;
- Node* scroll_source = To<ScrollTimeline>(*timeline_).ResolvedScrollSource();
- LayoutBox* box = scroll_source ? scroll_source->GetLayoutBox() : nullptr;
-
- base::Optional<double> start_scroll_offset;
- base::Optional<double> end_scroll_offset;
- if (box) {
- double current_offset;
- double max_offset;
- To<ScrollTimeline>(*timeline_)
- .GetCurrentAndMaxOffset(box, current_offset, max_offset);
-
- double resolved_start_scroll_offset = 0;
- double resolved_end_scroll_offset = max_offset;
- To<ScrollTimeline>(*timeline_)
- .ResolveScrollStartAndEnd(box, max_offset, resolved_start_scroll_offset,
- resolved_end_scroll_offset);
- start_scroll_offset = resolved_start_scroll_offset;
- end_scroll_offset = resolved_end_scroll_offset;
- }
+ auto& timeline = To<ScrollTimeline>(*timeline_);
+ Node* scroll_source = timeline.ResolvedScrollSource();
+ auto start_scroll_offset = timeline.GetResolvedStartScrollOffset();
+ auto end_scroll_offset = timeline.GetResolvedEndScrollOffset();
+
compositor_animation_->GetAnimation()->UpdateScrollTimeline(
scroll_timeline_util::GetCompositorScrollElementId(scroll_source),
start_scroll_offset, end_scroll_offset);
@@ -2184,7 +2221,7 @@ bool Animation::IsReplaceable() {
return false;
// 4. The animation is associated with a monotonically increasing timeline.
- if (!timeline_ || timeline_->IsScrollTimeline())
+ if (!timeline_ || !timeline_->IsMonotonicallyIncreasing())
return false;
// 5. The animation has an associated effect.
@@ -2323,21 +2360,18 @@ void Animation::commitStyles(ExceptionState& exception_state) {
// 6. Update style attribute for inline style.
ActiveInterpolationsMap interpolations_map =
To<KeyframeEffect>(effect())->InterpolationsForCommitStyles();
- StyleResolver& resolver = target->GetDocument().EnsureStyleResolver();
- scoped_refptr<ComputedStyle> style =
- resolver.StyleForInterpolations(*target, interpolations_map);
- for (const auto& property : animation_properties) {
- if (!property.IsCSSProperty())
- continue;
-
- CSSPropertyRef ref(property.GetCSSPropertyName(), target->GetDocument());
- const CSSValue* value = ref.GetProperty().CSSValueFromComputedStyle(
- *style, target->GetLayoutObject(), false);
- inline_style->setProperty(target->GetExecutionContext(),
- property.GetCSSPropertyName().ToAtomicString(),
- value->CssText(), "", ASSERT_NO_EXCEPTION);
- }
+ AnimationUtils::ForEachInterpolatedPropertyValue(
+ target, animation_properties, interpolations_map,
+ WTF::BindRepeating(
+ [](CSSStyleDeclaration* inline_style, Element* target,
+ PropertyHandle property, const CSSValue* value) {
+ inline_style->setProperty(
+ target->GetExecutionContext(),
+ property.GetCSSPropertyName().ToAtomicString(),
+ value->CssText(), "", ASSERT_NO_EXCEPTION);
+ },
+ WrapWeakPersistent(inline_style), WrapWeakPersistent(target)));
}
void Animation::Trace(Visitor* visitor) {
diff --git a/chromium/third_party/blink/renderer/core/animation/animation.h b/chromium/third_party/blink/renderer/core/animation/animation.h
index a71d09d7af4..c9bb999fd50 100644
--- a/chromium/third_party/blink/renderer/core/animation/animation.h
+++ b/chromium/third_party/blink/renderer/core/animation/animation.h
@@ -142,21 +142,10 @@ class CORE_EXPORT Animation : public EventTargetWithInlineData,
void cancel();
- base::Optional<double> currentTimeForBinding() const;
- // TODO(crbug.com/1060971): Remove |is_null| version.
- double currentTimeForBinding(bool& is_null); // DEPRECATED
- void setCurrentTimeForBinding(base::Optional<double> new_current_time,
- ExceptionState& exception_state);
- // TODO(crbug.com/1060971): Remove |is_null| version.
- void setCurrentTimeForBinding(double new_current_time, // DEPRECATED
- bool is_null,
- ExceptionState& exception_state);
-
- double currentTime() const;
- double currentTime(bool& is_null);
- void setCurrentTime(double new_current_time,
- bool is_null,
- ExceptionState& = ASSERT_NO_EXCEPTION);
+ base::Optional<double> currentTime() const;
+ void setCurrentTime(base::Optional<double> new_current_time,
+ ExceptionState& exception_state);
+ void setCurrentTime(base::Optional<double> new_current_time);
base::Optional<double> UnlimitedCurrentTime() const;
@@ -214,14 +203,9 @@ class CORE_EXPORT Animation : public EventTargetWithInlineData,
Document* GetDocument() const;
base::Optional<double> startTime() const;
- // TODO(crbug.com/1060971): Remove |is_null| version.
- double startTime(bool& is_null) const; // DEPRECATED
base::Optional<double> StartTimeInternal() const { return start_time_; }
virtual void setStartTime(base::Optional<double>, ExceptionState&);
- // TODO(crbug.com/1060971): Remove |is_null| version.
- void setStartTime(double, // DEPRECATED
- bool is_null,
- ExceptionState& = ASSERT_NO_EXCEPTION);
+ void setStartTime(base::Optional<double>);
const AnimationEffect* effect() const { return content_.Get(); }
AnimationEffect* effect() { return content_.Get(); }
@@ -266,7 +250,7 @@ class CORE_EXPORT Animation : public EventTargetWithInlineData,
bool PreCommit(int compositor_group,
const PaintArtifactCompositor*,
bool start_on_compositor);
- void PostCommit(double timeline_time);
+ void PostCommit();
unsigned SequenceNumber() const override { return sequence_number_; }
@@ -422,6 +406,7 @@ class CORE_EXPORT Animation : public EventTargetWithInlineData,
// control.
bool pending_pause_;
bool pending_play_;
+ // Indicates finish notification queued but not processed.
bool pending_finish_notification_;
bool has_queued_microtask_;
@@ -429,7 +414,11 @@ class CORE_EXPORT Animation : public EventTargetWithInlineData,
// has changed by means other than the ordinary progression of time
bool outdated_;
+ // Indicates the animation is no longer active. Cancelled animation is marked
+ // as finished_.
bool finished_;
+ // Indicates finish notification has been handled.
+ bool committed_finish_notification_;
// Holds a 'finished' event queued for asynchronous dispatch via the
// ScriptedAnimationController. This object remains active until the
// event is actually dispatched.
diff --git a/chromium/third_party/blink/renderer/core/animation/animation.idl b/chromium/third_party/blink/renderer/core/animation/animation.idl
index 88a3b8763e8..3399bc18b91 100644
--- a/chromium/third_party/blink/renderer/core/animation/animation.idl
+++ b/chromium/third_party/blink/renderer/core/animation/animation.idl
@@ -42,9 +42,9 @@ enum ReplaceState { "active", "removed", "persisted" };
[Measure] attribute AnimationEffect? effect;
// TODO(suzyh): Make timeline mutable.
[RuntimeEnabled=WebAnimationsAPI] readonly attribute AnimationTimeline? timeline;
- [Measure, RaisesException=Setter] attribute double? startTime;
- [Measure, RaisesException=Setter, ImplementedAs=currentTimeForBinding] attribute double? currentTime;
- [Measure, RaisesException=Setter] attribute double playbackRate;
+ [Measure, RaisesException=Setter] attribute double? startTime;
+ [Measure, RaisesException=Setter] attribute double? currentTime;
+ [Measure, RaisesException=Setter] attribute double playbackRate;
[Measure] readonly attribute AnimationPlayState playState;
[RuntimeEnabled=WebAnimationsAPI, Measure] readonly attribute ReplaceState replaceState;
[Measure] readonly attribute boolean pending;
diff --git a/chromium/third_party/blink/renderer/core/animation/animation_sim_test.cc b/chromium/third_party/blink/renderer/core/animation/animation_sim_test.cc
index 02dd56510e9..1e633ee1596 100644
--- a/chromium/third_party/blink/renderer/core/animation/animation_sim_test.cc
+++ b/chromium/third_party/blink/renderer/core/animation/animation_sim_test.cc
@@ -34,7 +34,6 @@ TEST_F(AnimationSimTest, CustomPropertyBaseComputedStyle) {
// around and not be valid in the exit frame of the next custom property
// animation.
- ScopedCSSVariables2ForTest css_variables2(true);
ScopedWebAnimationsAPIForTest web_animations(true);
SimRequest main_resource("https://example.com/", "text/html");
diff --git a/chromium/third_party/blink/renderer/core/animation/animation_test.cc b/chromium/third_party/blink/renderer/core/animation/animation_test.cc
index 3fa3a8e4784..a141a63fe3a 100644
--- a/chromium/third_party/blink/renderer/core/animation/animation_test.cc
+++ b/chromium/third_party/blink/renderer/core/animation/animation_test.cc
@@ -56,6 +56,9 @@
#include "third_party/blink/renderer/core/paint/paint_layer.h"
#include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
#include "third_party/blink/renderer/core/testing/core_unit_test_helper.h"
+#include "third_party/blink/renderer/platform/animation/compositor_animation.h"
+#include "third_party/blink/renderer/platform/animation/compositor_keyframe_model.h"
+#include "third_party/blink/renderer/platform/animation/compositor_target_property.h"
#include "third_party/blink/renderer/platform/bindings/microtask.h"
#include "third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
@@ -94,7 +97,7 @@ class AnimationAnimationTestNoCompositing : public RenderingTest {
timeline = GetDocument().Timeline();
timeline->ResetForTesting();
animation = timeline->Play(nullptr);
- animation->setStartTime(0, false);
+ animation->setStartTime(0);
animation->setEffect(MakeAnimation());
}
@@ -206,9 +209,7 @@ class AnimationAnimationTestNoCompositing : public RenderingTest {
return animation->Update(kTimingUpdateForAnimationFrame);
}
- void SimulateAwaitReady() {
- SimulateFrame(last_frame_time);
- }
+ void SimulateAwaitReady() { SimulateFrame(last_frame_time); }
void SimulateMicrotask() {
Microtask::PerformCheckpoint(V8PerIsolateData::MainThreadIsolate());
@@ -253,7 +254,7 @@ TEST_F(AnimationAnimationTestNoCompositing, InitialState) {
EXPECT_TRUE(animation->pending());
EXPECT_FALSE(animation->Paused());
EXPECT_EQ(1, animation->playbackRate());
- EXPECT_FALSE(animation->startTime());
+ EXPECT_FALSE(animation->startTime().has_value());
StartTimeline();
EXPECT_EQ("finished", animation->playState());
@@ -280,7 +281,7 @@ TEST_F(AnimationAnimationTestNoCompositing, CurrentTimeDoesNotSetOutdated) {
TEST_F(AnimationAnimationTestNoCompositing, SetCurrentTime) {
EXPECT_EQ("running", animation->playState());
- animation->setCurrentTime(10000, false);
+ animation->setCurrentTime(10000);
EXPECT_EQ("running", animation->playState());
EXPECT_EQ(10000, animation->currentTime());
@@ -290,14 +291,14 @@ TEST_F(AnimationAnimationTestNoCompositing, SetCurrentTime) {
}
TEST_F(AnimationAnimationTestNoCompositing, SetCurrentTimeNegative) {
- animation->setCurrentTime(-10000, false);
+ animation->setCurrentTime(-10000);
EXPECT_EQ("running", animation->playState());
EXPECT_EQ(-10000, animation->currentTime());
SimulateFrame(20000);
EXPECT_EQ(10000, animation->currentTime());
animation->setPlaybackRate(-2);
- animation->setCurrentTime(-10000, false);
+ animation->setCurrentTime(-10000);
EXPECT_EQ("finished", animation->playState());
// A seek can set current time outside the range [0, EffectEnd()].
EXPECT_EQ(-10000, animation->currentTime());
@@ -325,12 +326,12 @@ TEST_F(AnimationAnimationTestNoCompositing,
EXPECT_EQ(10000, animation->currentTime());
EXPECT_EQ("running", animation->playState());
- animation->setCurrentTime(-10000, false);
+ animation->setCurrentTime(-10000);
EXPECT_EQ("finished", animation->playState());
}
TEST_F(AnimationAnimationTestNoCompositing, SetCurrentTimePastContentEnd) {
- animation->setCurrentTime(50000, false);
+ animation->setCurrentTime(50000);
EXPECT_EQ("finished", animation->playState());
EXPECT_EQ(50000, animation->currentTime());
@@ -340,7 +341,7 @@ TEST_F(AnimationAnimationTestNoCompositing, SetCurrentTimePastContentEnd) {
// Reversing the play direction changes the play state from finished to
// running.
animation->setPlaybackRate(-2);
- animation->setCurrentTime(50000, false);
+ animation->setCurrentTime(50000);
EXPECT_EQ("running", animation->playState());
EXPECT_EQ(50000, animation->currentTime());
SimulateAwaitReady();
@@ -352,16 +353,16 @@ TEST_F(AnimationAnimationTestNoCompositing, SetCurrentTimePastContentEnd) {
TEST_F(AnimationAnimationTestNoCompositing, SetCurrentTimeMax) {
double limit = std::numeric_limits<double>::max();
- animation->setCurrentTime(limit, false);
- ExpectRelativeErrorWithinEpsilon(limit, animation->currentTime());
+ animation->setCurrentTime(limit);
+ ExpectRelativeErrorWithinEpsilon(limit, animation->currentTime().value());
SimulateFrame(100000);
- ExpectRelativeErrorWithinEpsilon(limit, animation->currentTime());
+ ExpectRelativeErrorWithinEpsilon(limit, animation->currentTime().value());
}
TEST_F(AnimationAnimationTestNoCompositing, SetCurrentTimeSetsStartTime) {
EXPECT_EQ(0, animation->startTime());
- animation->setCurrentTime(1000, false);
+ animation->setCurrentTime(1000);
EXPECT_EQ(-1000, animation->startTime());
SimulateFrame(1000);
@@ -374,7 +375,7 @@ TEST_F(AnimationAnimationTestNoCompositing, SetStartTime) {
EXPECT_EQ("running", animation->playState());
EXPECT_EQ(0, animation->startTime());
EXPECT_EQ(20000, animation->currentTime());
- animation->setStartTime(10000, false);
+ animation->setStartTime(10000);
EXPECT_EQ("running", animation->playState());
EXPECT_EQ(10000, animation->startTime());
EXPECT_EQ(10000, animation->currentTime());
@@ -382,20 +383,20 @@ TEST_F(AnimationAnimationTestNoCompositing, SetStartTime) {
SimulateFrame(30000);
EXPECT_EQ(10000, animation->startTime());
EXPECT_EQ(20000, animation->currentTime());
- animation->setStartTime(-20000, false);
+ animation->setStartTime(-20000);
EXPECT_EQ("finished", animation->playState());
}
TEST_F(AnimationAnimationTestNoCompositing, SetStartTimeLimitsAnimation) {
// Setting the start time is a seek operation, which is not constrained by the
// normal limits on the animation.
- animation->setStartTime(-50000, false);
+ animation->setStartTime(-50000);
EXPECT_EQ("finished", animation->playState());
EXPECT_TRUE(animation->Limited());
EXPECT_EQ(50000, animation->currentTime());
animation->setPlaybackRate(-1);
EXPECT_EQ("running", animation->playState());
- animation->setStartTime(-100000, false);
+ animation->setStartTime(-100000);
EXPECT_EQ("finished", animation->playState());
EXPECT_EQ(-100000, animation->currentTime());
EXPECT_TRUE(animation->Limited());
@@ -405,14 +406,14 @@ TEST_F(AnimationAnimationTestNoCompositing, SetStartTimeOnLimitedAnimation) {
// The setStartTime method is a seek and thus not constrained by the normal
// limits on the animation.
SimulateFrame(30000);
- animation->setStartTime(-10000, false);
+ animation->setStartTime(-10000);
EXPECT_EQ("finished", animation->playState());
EXPECT_EQ(40000, animation->currentTime());
EXPECT_TRUE(animation->Limited());
- animation->setCurrentTime(50000, false);
+ animation->setCurrentTime(50000);
EXPECT_EQ(50000, animation->currentTime());
- animation->setStartTime(-40000, false);
+ animation->setStartTime(-40000);
EXPECT_EQ(70000, animation->currentTime());
EXPECT_EQ("finished", animation->playState());
EXPECT_TRUE(animation->Limited());
@@ -425,7 +426,7 @@ TEST_F(AnimationAnimationTestNoCompositing, StartTimePauseFinish) {
EXPECT_TRUE(animation->pending());
SimulateAwaitReady();
EXPECT_FALSE(animation->pending());
- EXPECT_FALSE(animation->startTime());
+ EXPECT_FALSE(animation->startTime().has_value());
animation->finish(exception_state);
EXPECT_EQ("finished", animation->playState());
EXPECT_FALSE(animation->pending());
@@ -454,14 +455,14 @@ TEST_F(AnimationAnimationTestNoCompositing, StartTimeFinishPause) {
EXPECT_TRUE(animation->pending());
SimulateAwaitReady();
EXPECT_FALSE(animation->pending());
- EXPECT_FALSE(animation->startTime());
+ EXPECT_FALSE(animation->startTime().has_value());
}
TEST_F(AnimationAnimationTestNoCompositing, StartTimeWithZeroPlaybackRate) {
animation->setPlaybackRate(0);
EXPECT_EQ("running", animation->playState());
SimulateAwaitReady();
- EXPECT_TRUE(animation->startTime());
+ EXPECT_TRUE(animation->startTime().has_value());
SimulateFrame(10000);
EXPECT_EQ("running", animation->playState());
@@ -494,12 +495,12 @@ TEST_F(AnimationAnimationTestNoCompositing, PausePlay) {
TEST_F(AnimationAnimationTestNoCompositing, PlayRewindsToStart) {
// Auto-replay when starting from limit.
- animation->setCurrentTime(30000, false);
+ animation->setCurrentTime(30000);
animation->play();
EXPECT_EQ(0, animation->currentTime());
// Auto-replay when starting past the upper bound.
- animation->setCurrentTime(40000, false);
+ animation->setCurrentTime(40000);
animation->play();
EXPECT_EQ(0, animation->currentTime());
EXPECT_EQ("running", animation->playState());
@@ -509,7 +510,7 @@ TEST_F(AnimationAnimationTestNoCompositing, PlayRewindsToStart) {
// from a negative value of current time.
SimulateFrame(10000);
EXPECT_FALSE(animation->pending());
- animation->setCurrentTime(-10000, false);
+ animation->setCurrentTime(-10000);
EXPECT_EQ("running", animation->playState());
EXPECT_FALSE(animation->pending());
animation->play();
@@ -528,7 +529,7 @@ TEST_F(AnimationAnimationTestNoCompositing, PlayRewindsToEnd) {
EXPECT_EQ(30000, animation->currentTime());
// Snap to end if playing a reversed animation starting past the upper limit.
- animation->setCurrentTime(40000, false);
+ animation->setCurrentTime(40000);
EXPECT_EQ("running", animation->playState());
EXPECT_TRUE(animation->pending());
animation->play();
@@ -541,7 +542,7 @@ TEST_F(AnimationAnimationTestNoCompositing, PlayRewindsToEnd) {
// Snap to the end if playing a reversed animation starting with a negative
// value for current time.
- animation->setCurrentTime(-10000, false);
+ animation->setCurrentTime(-10000);
animation->play();
EXPECT_EQ(30000, animation->currentTime());
EXPECT_EQ("running", animation->playState());
@@ -560,11 +561,11 @@ TEST_F(AnimationAnimationTestNoCompositing,
animation->play();
EXPECT_EQ(0, animation->currentTime());
- animation->setCurrentTime(40000, false);
+ animation->setCurrentTime(40000);
animation->play();
EXPECT_EQ(40000, animation->currentTime());
- animation->setCurrentTime(-10000, false);
+ animation->setCurrentTime(-10000);
animation->play();
EXPECT_EQ(-10000, animation->currentTime());
}
@@ -582,7 +583,7 @@ TEST_F(AnimationAnimationTestNoCompositing,
}
TEST_F(AnimationAnimationTestNoCompositing, Reverse) {
- animation->setCurrentTime(10000, false);
+ animation->setCurrentTime(10000);
animation->pause();
animation->reverse();
EXPECT_EQ("running", animation->playState());
@@ -599,7 +600,7 @@ TEST_F(AnimationAnimationTestNoCompositing, Reverse) {
TEST_F(AnimationAnimationTestNoCompositing,
ReverseHoldsCurrentTimeWithPlaybackRateZero) {
- animation->setCurrentTime(10000, false);
+ animation->setCurrentTime(10000);
animation->setPlaybackRate(0);
animation->pause();
animation->reverse();
@@ -613,27 +614,27 @@ TEST_F(AnimationAnimationTestNoCompositing,
}
TEST_F(AnimationAnimationTestNoCompositing, ReverseSeeksToStart) {
- animation->setCurrentTime(-10000, false);
+ animation->setCurrentTime(-10000);
animation->setPlaybackRate(-1);
animation->reverse();
EXPECT_EQ(0, animation->currentTime());
}
TEST_F(AnimationAnimationTestNoCompositing, ReverseSeeksToEnd) {
- animation->setCurrentTime(40000, false);
+ animation->setCurrentTime(40000);
animation->reverse();
EXPECT_EQ(30000, animation->currentTime());
}
TEST_F(AnimationAnimationTestNoCompositing, ReverseBeyondLimit) {
- animation->setCurrentTime(40000, false);
+ animation->setCurrentTime(40000);
animation->setPlaybackRate(-1);
animation->reverse();
EXPECT_EQ("running", animation->playState());
EXPECT_TRUE(animation->pending());
EXPECT_EQ(0, animation->currentTime());
- animation->setCurrentTime(-10000, false);
+ animation->setCurrentTime(-10000);
animation->reverse();
EXPECT_EQ("running", animation->playState());
EXPECT_TRUE(animation->pending());
@@ -659,7 +660,7 @@ TEST_F(AnimationAnimationTestNoCompositing, Finish) {
TEST_F(AnimationAnimationTestNoCompositing, FinishAfterEffectEnd) {
NonThrowableExceptionState exception_state;
// OK to set current time out of bounds.
- animation->setCurrentTime(40000, false);
+ animation->setCurrentTime(40000);
animation->finish(exception_state);
// The finish method triggers a snap to the upper boundary.
EXPECT_EQ(30000, animation->currentTime());
@@ -667,7 +668,7 @@ TEST_F(AnimationAnimationTestNoCompositing, FinishAfterEffectEnd) {
TEST_F(AnimationAnimationTestNoCompositing, FinishBeforeStart) {
NonThrowableExceptionState exception_state;
- animation->setCurrentTime(-10000, false);
+ animation->setCurrentTime(-10000);
animation->setPlaybackRate(-1);
animation->finish(exception_state);
EXPECT_EQ(0, animation->currentTime());
@@ -677,7 +678,7 @@ TEST_F(AnimationAnimationTestNoCompositing,
FinishDoesNothingWithPlaybackRateZero) {
// Cannot finish an animation that has a playback rate of zero.
DummyExceptionStateForTesting exception_state;
- animation->setCurrentTime(10000, false);
+ animation->setCurrentTime(10000);
animation->setPlaybackRate(0);
animation->finish(exception_state);
EXPECT_EQ(10000, animation->currentTime());
@@ -692,7 +693,7 @@ TEST_F(AnimationAnimationTestNoCompositing, FinishRaisesException) {
timing.iteration_count = std::numeric_limits<double>::infinity();
animation->setEffect(MakeGarbageCollected<KeyframeEffect>(
nullptr, MakeEmptyEffectModel(), timing));
- animation->setCurrentTime(10000, false);
+ animation->setCurrentTime(10000);
DummyExceptionStateForTesting exception_state;
animation->finish(exception_state);
@@ -788,7 +789,7 @@ TEST_F(AnimationAnimationTestNoCompositing, SetPlaybackRateZero) {
SimulateFrame(20000);
EXPECT_EQ(10000, animation->currentTime());
- animation->setCurrentTime(20000, false);
+ animation->setCurrentTime(20000);
EXPECT_EQ(20000, animation->currentTime());
}
@@ -862,13 +863,13 @@ TEST_F(AnimationAnimationTestNoCompositing, UpdatePlaybackRateWhileRunning) {
TEST_F(AnimationAnimationTestNoCompositing, SetEffect) {
animation = timeline->Play(nullptr);
- animation->setStartTime(0, false);
+ animation->setStartTime(0);
AnimationEffect* effect1 = MakeAnimation();
AnimationEffect* effect2 = MakeAnimation();
animation->setEffect(effect1);
EXPECT_EQ(effect1, animation->effect());
EXPECT_EQ(0, animation->currentTime());
- animation->setCurrentTime(15000, false);
+ animation->setCurrentTime(15000);
animation->setEffect(effect2);
EXPECT_EQ(15000, animation->currentTime());
EXPECT_EQ(nullptr, effect1->GetAnimationForTesting());
@@ -877,7 +878,7 @@ TEST_F(AnimationAnimationTestNoCompositing, SetEffect) {
}
TEST_F(AnimationAnimationTestNoCompositing, SetEffectLimitsAnimation) {
- animation->setCurrentTime(20000, false);
+ animation->setCurrentTime(20000);
animation->setEffect(MakeAnimation(10));
EXPECT_EQ(20000, animation->currentTime());
EXPECT_TRUE(animation->Limited());
@@ -886,7 +887,7 @@ TEST_F(AnimationAnimationTestNoCompositing, SetEffectLimitsAnimation) {
}
TEST_F(AnimationAnimationTestNoCompositing, SetEffectUnlimitsAnimation) {
- animation->setCurrentTime(40000, false);
+ animation->setCurrentTime(40000);
animation->setEffect(MakeAnimation(60));
EXPECT_FALSE(animation->Limited());
EXPECT_EQ(40000, animation->currentTime());
@@ -919,7 +920,7 @@ TEST_F(AnimationAnimationTestNoCompositing, AnimationsReturnTimeToNextEffect) {
auto* keyframe_effect = MakeGarbageCollected<KeyframeEffect>(
nullptr, MakeEmptyEffectModel(), timing);
animation = timeline->Play(keyframe_effect);
- animation->setStartTime(0, false);
+ animation->setStartTime(0);
// Next effect change at end of start delay.
SimulateFrame(0);
@@ -949,7 +950,7 @@ TEST_F(AnimationAnimationTestNoCompositing, AnimationsReturnTimeToNextEffect) {
EXPECT_EQ(base::nullopt, animation->TimeToEffectChange());
// Reset to start of animation. Next effect at the end of the start delay.
- animation->setCurrentTime(0, false);
+ animation->setCurrentTime(0);
SimulateFrame(3000);
EXPECT_EQ(AnimationTimeDelta::FromSecondsD(1),
animation->TimeToEffectChange());
@@ -966,7 +967,7 @@ TEST_F(AnimationAnimationTestNoCompositing, AnimationsReturnTimeToNextEffect) {
EXPECT_EQ(base::nullopt, animation->TimeToEffectChange());
// Reversed animation from end time. Next effect after end delay.
- animation->setCurrentTime(3000, false);
+ animation->setCurrentTime(3000);
animation->setPlaybackRate(-1);
animation->Update(kTimingUpdateOnDemand);
SimulateFrame(3000);
@@ -995,7 +996,7 @@ TEST_F(AnimationAnimationTestNoCompositing, TimeToNextEffectWhenPaused) {
TEST_F(AnimationAnimationTestNoCompositing,
TimeToNextEffectWhenCancelledBeforeStart) {
EXPECT_EQ(AnimationTimeDelta(), animation->TimeToEffectChange());
- animation->setCurrentTime(-8000, false);
+ animation->setCurrentTime(-8000);
animation->setPlaybackRate(2);
EXPECT_EQ("running", animation->playState());
animation->cancel();
@@ -1010,7 +1011,7 @@ TEST_F(AnimationAnimationTestNoCompositing,
TEST_F(AnimationAnimationTestNoCompositing,
TimeToNextEffectWhenCancelledBeforeStartReverse) {
EXPECT_EQ(AnimationTimeDelta(), animation->TimeToEffectChange());
- animation->setCurrentTime(9000, false);
+ animation->setCurrentTime(9000);
animation->setPlaybackRate(-3);
EXPECT_EQ("running", animation->playState());
animation->cancel();
@@ -1058,13 +1059,13 @@ TEST_F(AnimationAnimationTestNoCompositing, HasLowerCompositeOrdering) {
TEST_F(AnimationAnimationTestNoCompositing, PlayAfterCancel) {
animation->cancel();
EXPECT_EQ("idle", animation->playState());
- EXPECT_TRUE(std::isnan(animation->currentTime()));
- EXPECT_FALSE(animation->startTime());
+ EXPECT_FALSE(animation->currentTime().has_value());
+ EXPECT_FALSE(animation->startTime().has_value());
animation->play();
EXPECT_EQ("running", animation->playState());
EXPECT_TRUE(animation->pending());
EXPECT_EQ(0, animation->currentTime());
- EXPECT_FALSE(animation->startTime());
+ EXPECT_FALSE(animation->startTime().has_value());
SimulateAwaitReady();
EXPECT_FALSE(animation->pending());
EXPECT_EQ(0, animation->currentTime());
@@ -1078,19 +1079,19 @@ TEST_F(AnimationAnimationTestNoCompositing, PlayAfterCancel) {
TEST_F(AnimationAnimationTestNoCompositing, PlayBackwardsAfterCancel) {
animation->setPlaybackRate(-1);
- animation->setCurrentTime(15000, false);
+ animation->setCurrentTime(15000);
animation->cancel();
EXPECT_EQ("idle", animation->playState());
EXPECT_FALSE(animation->pending());
- EXPECT_TRUE(std::isnan(animation->currentTime()));
- EXPECT_FALSE(animation->startTime());
+ EXPECT_FALSE(animation->currentTime().has_value());
+ EXPECT_FALSE(animation->startTime().has_value());
// Snap to the end of the animation.
animation->play();
EXPECT_EQ("running", animation->playState());
EXPECT_TRUE(animation->pending());
EXPECT_EQ(30000, animation->currentTime());
- EXPECT_FALSE(animation->startTime());
+ EXPECT_FALSE(animation->startTime().has_value());
SimulateAwaitReady();
EXPECT_FALSE(animation->pending());
EXPECT_EQ(30000, animation->startTime());
@@ -1105,15 +1106,15 @@ TEST_F(AnimationAnimationTestNoCompositing, ReverseAfterCancel) {
animation->cancel();
EXPECT_EQ("idle", animation->playState());
EXPECT_FALSE(animation->pending());
- EXPECT_TRUE(std::isnan(animation->currentTime()));
- EXPECT_FALSE(animation->startTime());
+ EXPECT_FALSE(animation->currentTime().has_value());
+ EXPECT_FALSE(animation->startTime().has_value());
// Reverse snaps to the end of the animation.
animation->reverse();
EXPECT_EQ("running", animation->playState());
EXPECT_TRUE(animation->pending());
EXPECT_EQ(30000, animation->currentTime());
- EXPECT_FALSE(animation->startTime());
+ EXPECT_FALSE(animation->startTime().has_value());
SimulateAwaitReady();
EXPECT_FALSE(animation->pending());
EXPECT_EQ(30000, animation->startTime());
@@ -1128,8 +1129,8 @@ TEST_F(AnimationAnimationTestNoCompositing, FinishAfterCancel) {
NonThrowableExceptionState exception_state;
animation->cancel();
EXPECT_EQ("idle", animation->playState());
- EXPECT_TRUE(std::isnan(animation->currentTime()));
- EXPECT_FALSE(animation->startTime());
+ EXPECT_FALSE(animation->currentTime().has_value());
+ EXPECT_FALSE(animation->startTime().has_value());
animation->finish(exception_state);
EXPECT_EQ("finished", animation->playState());
@@ -1140,17 +1141,17 @@ TEST_F(AnimationAnimationTestNoCompositing, FinishAfterCancel) {
TEST_F(AnimationAnimationTestNoCompositing, PauseAfterCancel) {
animation->cancel();
EXPECT_EQ("idle", animation->playState());
- EXPECT_TRUE(std::isnan(animation->currentTime()));
- EXPECT_FALSE(animation->startTime());
+ EXPECT_FALSE(animation->currentTime().has_value());
+ EXPECT_FALSE(animation->startTime().has_value());
animation->pause();
EXPECT_EQ("paused", animation->playState());
EXPECT_TRUE(animation->pending());
EXPECT_EQ(0, animation->currentTime());
- EXPECT_FALSE(animation->startTime());
+ EXPECT_FALSE(animation->startTime().has_value());
SimulateAwaitReady();
EXPECT_FALSE(animation->pending());
EXPECT_EQ(0, animation->currentTime());
- EXPECT_FALSE(animation->startTime());
+ EXPECT_FALSE(animation->startTime().has_value());
}
// crbug.com/1052217
@@ -1402,6 +1403,149 @@ TEST_F(AnimationAnimationTestCompositing, InfiniteDurationAnimation) {
animation->CheckCanStartAnimationOnCompositor(nullptr));
}
+TEST_F(AnimationAnimationTestCompositing,
+ ScrollLinkedAnimationCanBeComposited) {
+ ResetWithCompositedAnimation();
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ #scroller { will-change: transform; overflow: scroll; width: 100px; height: 100px; }
+ #target { width: 100px; height: 200px; will-change: opacity;}
+ #spacer { width: 200px; height: 2000px; }
+ </style>
+ <div id ='scroller'>
+ <div id ='target'></div>
+ <div id ='spacer'></div>
+ </div>
+ )HTML");
+
+ // Create ScrollTimeline
+ LayoutBoxModelObject* scroller =
+ ToLayoutBoxModelObject(GetLayoutObjectByElementId("scroller"));
+ PaintLayerScrollableArea* scrollable_area = scroller->GetScrollableArea();
+ scrollable_area->SetScrollOffset(ScrollOffset(0, 20),
+ mojom::blink::ScrollType::kProgrammatic);
+ ScrollTimelineOptions* options = ScrollTimelineOptions::Create();
+ DoubleOrScrollTimelineAutoKeyword time_range =
+ DoubleOrScrollTimelineAutoKeyword::FromDouble(100);
+ options->setTimeRange(time_range);
+ options->setScrollSource(GetElementById("scroller"));
+ ScrollTimeline* scroll_timeline =
+ ScrollTimeline::Create(GetDocument(), options, ASSERT_NO_EXCEPTION);
+
+ // Create KeyframeEffect
+ Timing timing;
+ timing.iteration_duration = AnimationTimeDelta::FromSecondsD(30);
+
+ Persistent<StringKeyframe> start_keyframe =
+ MakeGarbageCollected<StringKeyframe>();
+ start_keyframe->SetCSSPropertyValue(CSSPropertyID::kOpacity, "1.0",
+ SecureContextMode::kInsecureContext,
+ nullptr);
+ Persistent<StringKeyframe> end_keyframe =
+ MakeGarbageCollected<StringKeyframe>();
+ end_keyframe->SetCSSPropertyValue(CSSPropertyID::kOpacity, "0.0",
+ SecureContextMode::kInsecureContext,
+ nullptr);
+
+ StringKeyframeVector keyframes;
+ keyframes.push_back(start_keyframe);
+ keyframes.push_back(end_keyframe);
+
+ Element* element = GetElementById("target");
+ auto* model = MakeGarbageCollected<StringKeyframeEffectModel>(keyframes);
+
+ // Create scroll-linked animation
+ NonThrowableExceptionState exception_state;
+ Animation* scroll_animation = Animation::Create(
+ MakeGarbageCollected<KeyframeEffect>(element, model, timing),
+ scroll_timeline, exception_state);
+
+ model->SnapshotAllCompositorKeyframesIfNecessary(
+ *element, *ComputedStyle::Create(), nullptr);
+ scroll_animation->play();
+ EXPECT_EQ(scroll_animation->CheckCanStartAnimationOnCompositor(nullptr),
+ CompositorAnimations::kNoFailure);
+}
+
+TEST_F(AnimationAnimationTestCompositing,
+ StartScrollLinkedAnimationWithStartTimeIfApplicable) {
+ ResetWithCompositedAnimation();
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ #scroller { will-change: transform; overflow: scroll; width: 100px; height: 100px; }
+ #target { width: 100px; height: 200px; will-change: opacity;}
+ #spacer { width: 200px; height: 700px; }
+ </style>
+ <div id ='scroller'>
+ <div id ='target'></div>
+ <div id ='spacer'></div>
+ </div>
+ )HTML");
+
+ // Create ScrollTimeline
+ LayoutBoxModelObject* scroller =
+ ToLayoutBoxModelObject(GetLayoutObjectByElementId("scroller"));
+ PaintLayerScrollableArea* scrollable_area = scroller->GetScrollableArea();
+ scrollable_area->SetScrollOffset(ScrollOffset(0, 100),
+ mojom::blink::ScrollType::kProgrammatic);
+ ScrollTimelineOptions* options = ScrollTimelineOptions::Create();
+ DoubleOrScrollTimelineAutoKeyword time_range =
+ DoubleOrScrollTimelineAutoKeyword::FromDouble(100);
+ options->setTimeRange(time_range);
+ options->setScrollSource(GetElementById("scroller"));
+ ScrollTimeline* scroll_timeline =
+ ScrollTimeline::Create(GetDocument(), options, ASSERT_NO_EXCEPTION);
+
+ // Create KeyframeEffect
+ Timing timing;
+ timing.iteration_duration = AnimationTimeDelta::FromSecondsD(30);
+
+ Persistent<StringKeyframe> start_keyframe =
+ MakeGarbageCollected<StringKeyframe>();
+ start_keyframe->SetCSSPropertyValue(CSSPropertyID::kOpacity, "1.0",
+ SecureContextMode::kInsecureContext,
+ nullptr);
+ Persistent<StringKeyframe> end_keyframe =
+ MakeGarbageCollected<StringKeyframe>();
+ end_keyframe->SetCSSPropertyValue(CSSPropertyID::kOpacity, "0.0",
+ SecureContextMode::kInsecureContext,
+ nullptr);
+
+ StringKeyframeVector keyframes;
+ keyframes.push_back(start_keyframe);
+ keyframes.push_back(end_keyframe);
+
+ Element* element = GetElementById("target");
+ auto* model = MakeGarbageCollected<StringKeyframeEffectModel>(keyframes);
+
+ KeyframeEffect* keyframe_effect =
+ MakeGarbageCollected<KeyframeEffect>(element, model, timing);
+
+ // Create scroll-linked animation
+ NonThrowableExceptionState exception_state;
+ Animation* scroll_animation =
+ Animation::Create(keyframe_effect, scroll_timeline, exception_state);
+
+ model->SnapshotAllCompositorKeyframesIfNecessary(
+ *element, *ComputedStyle::Create(), nullptr);
+ const double TEST_START_TIME = 10;
+ scroll_animation->setStartTime(TEST_START_TIME);
+ scroll_animation->play();
+ EXPECT_EQ(scroll_animation->CheckCanStartAnimationOnCompositor(nullptr),
+ CompositorAnimations::kNoFailure);
+ // Start the animation on compositor. The time offset of the compositor
+ // keyframe should be unset if we start the animation with its start time.
+ scroll_animation->PreCommit(1, nullptr, true);
+ cc::KeyframeModel* keyframe_model =
+ keyframe_effect->GetAnimationForTesting()
+ ->GetCompositorAnimation()
+ ->CcAnimation()
+ ->GetKeyframeModel(compositor_target_property::OPACITY);
+ EXPECT_EQ(keyframe_model->start_time() - base::TimeTicks(),
+ base::TimeDelta::FromMilliseconds(TEST_START_TIME));
+ EXPECT_EQ(keyframe_model->time_offset(), base::TimeDelta());
+}
+
// Verifies correctness of scroll linked animation current and start times in
// various animation states.
TEST_F(AnimationAnimationTestNoCompositing, ScrollLinkedAnimationCreation) {
@@ -1433,33 +1577,25 @@ TEST_F(AnimationAnimationTestNoCompositing, ScrollLinkedAnimationCreation) {
Animation::Create(MakeAnimation(), scroll_timeline, exception_state);
// Verify start and current times in Idle state.
- bool is_null;
- scroll_animation->startTime(is_null);
- EXPECT_TRUE(is_null);
- scroll_animation->currentTime(is_null);
- EXPECT_TRUE(is_null);
+ EXPECT_FALSE(scroll_animation->startTime().has_value());
+ EXPECT_FALSE(scroll_animation->currentTime().has_value());
scroll_animation->play();
// Verify start and current times in Pending state.
- scroll_animation->startTime(is_null);
- EXPECT_TRUE(is_null);
- EXPECT_EQ(20, scroll_animation->currentTime(is_null));
- EXPECT_FALSE(is_null);
+ EXPECT_EQ(0, scroll_animation->startTime());
+ EXPECT_EQ(20, scroll_animation->currentTime());
UpdateAllLifecyclePhasesForTest();
// Verify start and current times in Playing state.
- EXPECT_EQ(0, scroll_animation->startTime(is_null));
- EXPECT_FALSE(is_null);
- EXPECT_EQ(20, scroll_animation->currentTime(is_null));
- EXPECT_FALSE(is_null);
+ EXPECT_EQ(0, scroll_animation->startTime());
+ EXPECT_EQ(20, scroll_animation->currentTime());
// Verify current time after scroll.
scrollable_area->SetScrollOffset(ScrollOffset(0, 40),
mojom::blink::ScrollType::kProgrammatic);
SimulateFrameForScrollAnimations();
- EXPECT_EQ(40, scroll_animation->currentTime(is_null));
- EXPECT_FALSE(is_null);
+ EXPECT_EQ(40, scroll_animation->currentTime());
}
TEST_F(AnimationAnimationTestNoCompositing,
@@ -1491,7 +1627,7 @@ TEST_F(AnimationAnimationTestNoCompositing,
EXPECT_TRUE(animation->Update(kTimingUpdateForAnimationFrame));
// Asynchronous completion.
- animation->setCurrentTime(50000, false);
+ animation->setCurrentTime(50000);
EXPECT_EQ("finished", animation->playState());
EXPECT_FALSE(animation->Update(kTimingUpdateForAnimationFrame));
}
@@ -1511,7 +1647,7 @@ TEST_F(AnimationAnimationTestNoCompositing,
EXPECT_TRUE(animation->HasPendingActivity());
// Resolving the finished promise clears the pending activity.
- animation->setCurrentTime(50000, false);
+ animation->setCurrentTime(50000);
EXPECT_EQ("finished", animation->playState());
SimulateMicrotask();
EXPECT_FALSE(animation->Update(kTimingUpdateForAnimationFrame));
@@ -1562,7 +1698,7 @@ TEST_F(AnimationAnimationTestNoCompositing,
EXPECT_TRUE(animation->HasPendingActivity());
// Finishing the animation asynchronously clears the pending activity.
- animation->setCurrentTime(50000, false);
+ animation->setCurrentTime(50000);
EXPECT_EQ("finished", animation->playState());
SimulateMicrotask();
EXPECT_FALSE(animation->Update(kTimingUpdateForAnimationFrame));
diff --git a/chromium/third_party/blink/renderer/core/animation/animation_test_helper.cc b/chromium/third_party/blink/renderer/core/animation/animation_test_helper.cc
index 88cc4e0ac9a..5fd3f69222c 100644
--- a/chromium/third_party/blink/renderer/core/animation/animation_test_helper.cc
+++ b/chromium/third_party/blink/renderer/core/animation/animation_test_helper.cc
@@ -36,6 +36,31 @@ void SetV8ObjectPropertyAsNumber(v8::Isolate* isolate,
.ToChecked();
}
+KeyframeEffect* CreateSimpleKeyframeEffectForTest(Element* target,
+ CSSPropertyID property,
+ String value_start,
+ String value_end) {
+ Timing timing;
+ timing.iteration_duration = AnimationTimeDelta::FromSecondsD(1000);
+
+ StringKeyframe* start_keyframe = MakeGarbageCollected<StringKeyframe>();
+ start_keyframe->SetOffset(0.0);
+ start_keyframe->SetCSSPropertyValue(
+ property, value_start, SecureContextMode::kSecureContext, nullptr);
+
+ StringKeyframe* end_keyframe = MakeGarbageCollected<StringKeyframe>();
+ end_keyframe->SetOffset(1.0);
+ end_keyframe->SetCSSPropertyValue(property, value_end,
+ SecureContextMode::kSecureContext, nullptr);
+
+ StringKeyframeVector keyframes;
+ keyframes.push_back(start_keyframe);
+ keyframes.push_back(end_keyframe);
+
+ auto* model = MakeGarbageCollected<StringKeyframeEffectModel>(keyframes);
+ return MakeGarbageCollected<KeyframeEffect>(target, model, timing);
+}
+
void EnsureInterpolatedValueCached(const ActiveInterpolations& interpolations,
Document& document,
Element* element) {
diff --git a/chromium/third_party/blink/renderer/core/animation/animation_test_helper.h b/chromium/third_party/blink/renderer/core/animation/animation_test_helper.h
index 516eb7e6a45..d1ba4a8df79 100644
--- a/chromium/third_party/blink/renderer/core/animation/animation_test_helper.h
+++ b/chromium/third_party/blink/renderer/core/animation/animation_test_helper.h
@@ -14,6 +14,7 @@ namespace blink {
class Document;
class Element;
+class KeyframeEffect;
void SetV8ObjectPropertyAsString(v8::Isolate*,
v8::Local<v8::Object>,
@@ -24,6 +25,14 @@ void SetV8ObjectPropertyAsNumber(v8::Isolate*,
const StringView& name,
double value);
+// Creates a KeyframeEffect with two keyframes corresponding to
+// value_start (offset 0.0) and value_end (offset 1.0). Default blink::Timing
+// values are used, except for iteration_duration which is set to 1000ms.
+KeyframeEffect* CreateSimpleKeyframeEffectForTest(Element*,
+ CSSPropertyID,
+ String value_start,
+ String value_end);
+
// Ensures that a set of interpolations actually computes and caches their
// internal interpolated value, so that tests can retrieve them.
//
diff --git a/chromium/third_party/blink/renderer/core/animation/animation_timeline.cc b/chromium/third_party/blink/renderer/core/animation/animation_timeline.cc
index df6a5297fe7..365b6c84aac 100644
--- a/chromium/third_party/blink/renderer/core/animation/animation_timeline.cc
+++ b/chromium/third_party/blink/renderer/core/animation/animation_timeline.cc
@@ -38,21 +38,7 @@ bool CompareAnimations(const Member<Animation>& left,
Animation::CompareAnimationsOrdering::kPointerOrder);
}
-double AnimationTimeline::currentTime(bool& is_null) {
- base::Optional<base::TimeDelta> result = CurrentPhaseAndTime().time;
-
- is_null = !result.has_value();
- return result ? result->InMillisecondsF()
- : std::numeric_limits<double>::quiet_NaN();
-}
-
-double AnimationTimeline::currentTime() {
- base::Optional<base::TimeDelta> result = CurrentPhaseAndTime().time;
- return result ? result->InMillisecondsF()
- : std::numeric_limits<double>::quiet_NaN();
-}
-
-base::Optional<double> AnimationTimeline::CurrentTime() {
+base::Optional<double> AnimationTimeline::currentTime() {
base::Optional<base::TimeDelta> result = CurrentPhaseAndTime().time;
return result ? base::make_optional(result->InMillisecondsF())
: base::nullopt;
@@ -230,6 +216,12 @@ void AnimationTimeline::ScheduleServiceOnNextFrame() {
document_->View()->ScheduleAnimation();
}
+void AnimationTimeline::MarkAnimationsCompositorPending(bool source_changed) {
+ for (const auto& animation : animations_) {
+ animation->SetCompositorPending(source_changed);
+ }
+}
+
void AnimationTimeline::Trace(Visitor* visitor) {
visitor->Trace(document_);
visitor->Trace(animations_needing_update_);
diff --git a/chromium/third_party/blink/renderer/core/animation/animation_timeline.h b/chromium/third_party/blink/renderer/core/animation/animation_timeline.h
index 1c024f2ecc4..6494c55f335 100644
--- a/chromium/third_party/blink/renderer/core/animation/animation_timeline.h
+++ b/chromium/third_party/blink/renderer/core/animation/animation_timeline.h
@@ -35,9 +35,7 @@ class CORE_EXPORT AnimationTimeline : public ScriptWrappable {
AnimationTimeline(Document*);
~AnimationTimeline() override = default;
- double currentTime(bool& is_null);
- double currentTime();
- base::Optional<double> CurrentTime();
+ base::Optional<double> currentTime();
base::Optional<double> CurrentTimeSeconds();
String phase();
@@ -45,6 +43,11 @@ class CORE_EXPORT AnimationTimeline : public ScriptWrappable {
virtual bool IsDocumentTimeline() const { return false; }
virtual bool IsScrollTimeline() const { return false; }
virtual bool IsActive() const = 0;
+ virtual double ZeroTimeInSeconds() = 0;
+ // https://drafts.csswg.org/web-animations/#monotonically-increasing-timeline
+ // A timeline is monotonically increasing if its reported current time is
+ // always greater than or equal than its previously reported current time.
+ bool IsMonotonicallyIncreasing() const { return IsDocumentTimeline(); }
// Returns the initial start time for animations that are linked to this
// timeline. This method gets invoked when initializing the start time of an
// animation on this timeline for the first time. It exists because the
@@ -85,6 +88,8 @@ class CORE_EXPORT AnimationTimeline : public ScriptWrappable {
}
virtual CompositorAnimationTimeline* EnsureCompositorTimeline() = 0;
+ void MarkAnimationsCompositorPending(bool source_changed = false);
+
void Trace(Visitor*) override;
protected:
diff --git a/chromium/third_party/blink/renderer/core/animation/animation_timeline.idl b/chromium/third_party/blink/renderer/core/animation/animation_timeline.idl
index 19013b3dd53..0c36488ff89 100644
--- a/chromium/third_party/blink/renderer/core/animation/animation_timeline.idl
+++ b/chromium/third_party/blink/renderer/core/animation/animation_timeline.idl
@@ -9,7 +9,6 @@ enum TimelinePhase { "inactive", "before", "active", "after" };
RuntimeEnabled=WebAnimationsAPI,
Exposed=Window
] interface AnimationTimeline {
- // TODO(crbug.com/1060971): Remove ImplementedAs.
- [ImplementedAs=CurrentTime] readonly attribute double? currentTime;
+ readonly attribute double? currentTime;
[RuntimeEnabled=ScrollTimeline] readonly attribute TimelinePhase phase;
};
diff --git a/chromium/third_party/blink/renderer/core/animation/animation_utils.cc b/chromium/third_party/blink/renderer/core/animation/animation_utils.cc
new file mode 100644
index 00000000000..e1932701bd4
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/animation/animation_utils.cc
@@ -0,0 +1,56 @@
+// 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/core/animation/animation_utils.h"
+
+#include "third_party/blink/renderer/core/css/properties/computed_style_utils.h"
+#include "third_party/blink/renderer/core/css/properties/css_property_ref.h"
+#include "third_party/blink/renderer/core/css/resolver/style_resolver.h"
+#include "third_party/blink/renderer/core/dom/document.h"
+#include "third_party/blink/renderer/core/style/computed_style.h"
+
+namespace blink {
+
+const CSSValue* AnimationUtils::KeyframeValueFromComputedStyle(
+ const PropertyHandle& property,
+ const ComputedStyle& style,
+ const Document& document,
+ const LayoutObject* layout_object) {
+ if (property.IsCSSCustomProperty()) {
+ // Holds registration and creates temporary CSSProperty.
+ CSSPropertyRef custom_ref(property.GetCSSPropertyName(), document);
+ return ComputedStyleUtils::ComputedPropertyValue(custom_ref.GetProperty(),
+ style, layout_object);
+ }
+
+ return ComputedStyleUtils::ComputedPropertyValue(property.GetCSSProperty(),
+ style, layout_object);
+}
+
+void AnimationUtils::ForEachInterpolatedPropertyValue(
+ Element* target,
+ const PropertyHandleSet& properties,
+ ActiveInterpolationsMap& interpolations,
+ base::RepeatingCallback<void(PropertyHandle, const CSSValue*)> callback) {
+ if (!target)
+ return;
+
+ StyleResolver& resolver = target->GetDocument().EnsureStyleResolver();
+ scoped_refptr<ComputedStyle> style =
+ resolver.StyleForInterpolations(*target, interpolations);
+
+ for (const auto& property : properties) {
+ if (!property.IsCSSProperty())
+ continue;
+
+ const CSSValue* value = KeyframeValueFromComputedStyle(
+ property, *style, target->GetDocument(), target->GetLayoutObject());
+ if (!value)
+ continue;
+
+ callback.Run(property, value);
+ }
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/animation/animation_utils.h b/chromium/third_party/blink/renderer/core/animation/animation_utils.h
new file mode 100644
index 00000000000..8ba868826d5
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/animation/animation_utils.h
@@ -0,0 +1,36 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_ANIMATION_UTILS_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_ANIMATION_UTILS_H_
+
+#include "third_party/blink/renderer/core/animation/interpolation.h"
+#include "third_party/blink/renderer/core/animation/keyframe.h"
+#include "third_party/blink/renderer/core/animation/property_handle.h"
+#include "third_party/blink/renderer/core/dom/element.h"
+
+namespace blink {
+
+class CORE_EXPORT AnimationUtils {
+ STATIC_ONLY(AnimationUtils);
+
+ public:
+ static const CSSValue* KeyframeValueFromComputedStyle(const PropertyHandle&,
+ const ComputedStyle&,
+ const Document&,
+ const LayoutObject*);
+
+ // Resolves the value of each property in properties, based on the underlying
+ // value including any animation effects included in the interpolations map.
+ // A callback is triggered for each property with the resolved value.
+ static void ForEachInterpolatedPropertyValue(
+ Element* target,
+ const PropertyHandleSet& properties,
+ ActiveInterpolationsMap& interpolations,
+ base::RepeatingCallback<void(PropertyHandle, const CSSValue*)> callback);
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_ANIMATION_UTILS_H_
diff --git a/chromium/third_party/blink/renderer/core/animation/animation_utils_test.cc b/chromium/third_party/blink/renderer/core/animation/animation_utils_test.cc
new file mode 100644
index 00000000000..bc30f2089e7
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/animation/animation_utils_test.cc
@@ -0,0 +1,117 @@
+// 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/core/animation/animation_utils.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/core/animation/animation_input_helpers.h"
+#include "third_party/blink/renderer/core/animation/invalidatable_interpolation.h"
+#include "third_party/blink/renderer/core/css/properties/css_property_ref.h"
+#include "third_party/blink/renderer/core/css/resolver/style_resolver.h"
+#include "third_party/blink/renderer/core/dom/document.h"
+#include "third_party/blink/renderer/core/style/computed_style.h"
+#include "third_party/blink/renderer/core/testing/core_unit_test_helper.h"
+#include "third_party/googletest/src/googletest/include/gtest/gtest.h"
+
+namespace blink {
+
+class AnimationUtilsTest : public RenderingTest {
+ public:
+ AnimationUtilsTest() = default;
+
+ StringKeyframe* AddKeyframe(StringKeyframeVector& keyframes, double offset) {
+ StringKeyframe* keyframe = MakeGarbageCollected<StringKeyframe>();
+ keyframe->SetOffset(offset);
+ keyframes.push_back(keyframe);
+ return keyframe;
+ }
+
+ void AddProperty(StringKeyframe* keyframe,
+ CSSPropertyID property_id,
+ String value) {
+ keyframe->SetCSSPropertyValue(property_id, value,
+ SecureContextMode::kInsecureContext,
+ /*style_sheet_contents=*/nullptr);
+ }
+
+ void AddInterpolation(ActiveInterpolationsMap& interpolations_map,
+ const StringKeyframeVector& keyframes,
+ PropertyHandle property_handle) {
+ ActiveInterpolationsMap::AddResult entry =
+ interpolations_map.insert(property_handle, ActiveInterpolations());
+ ActiveInterpolations& active_interpolations = entry.stored_value->value;
+
+ PropertySpecificKeyframe* from_keyframe =
+ CreatePropertySpecificKeyframe(keyframes[0], property_handle, 0);
+ PropertySpecificKeyframe* to_keyframe =
+ CreatePropertySpecificKeyframe(keyframes[1], property_handle, 1);
+
+ Interpolation* interpolation =
+ MakeGarbageCollected<InvalidatableInterpolation>(
+ property_handle, from_keyframe, to_keyframe);
+ interpolation->Interpolate(/*iteration=*/0, /*progress=*/1);
+ active_interpolations.push_back(interpolation);
+ }
+
+ PropertySpecificKeyframe* CreatePropertySpecificKeyframe(
+ Keyframe* keyframe,
+ PropertyHandle property_handle,
+ double offset) {
+ return keyframe->CreatePropertySpecificKeyframe(
+ property_handle, EffectModel::kCompositeReplace, offset);
+ }
+};
+
+TEST_F(AnimationUtilsTest, ForEachInterpolatedPropertyValue) {
+ SetBodyInnerHTML("<div id='target' style='left:10px'></div>");
+ Element* target = GetElementById("target");
+
+ PropertyHandleSet properties;
+ properties.insert(PropertyHandle(GetCSSPropertyLeft()));
+ properties.insert(PropertyHandle(GetCSSPropertyTop()));
+
+ HashMap<String, String> map;
+ ActiveInterpolationsMap interpolations_map;
+
+ base::RepeatingCallback<void(PropertyHandle, const CSSValue*)> callback =
+ WTF::BindRepeating(
+ [](HashMap<String, String>* map, PropertyHandle property,
+ const CSSValue* value) {
+ String property_name =
+ AnimationInputHelpers::PropertyHandleToKeyframeAttribute(
+ property);
+ map->Set(property_name, value->CssText());
+ },
+ WTF::Unretained(&map));
+
+ AnimationUtils::ForEachInterpolatedPropertyValue(
+ target, properties, interpolations_map, callback);
+ EXPECT_EQ(2U, map.size());
+ EXPECT_EQ("10px", map.at("left"));
+ EXPECT_EQ("auto", map.at("top"));
+
+ map.clear();
+
+ StringKeyframeVector keyframes;
+ StringKeyframe* fromKeyframe = AddKeyframe(keyframes, 0);
+ AddProperty(fromKeyframe, CSSPropertyID::kLeft, "10px");
+ AddProperty(fromKeyframe, CSSPropertyID::kTop, "auto");
+
+ StringKeyframe* toKeyframe = AddKeyframe(keyframes, 1);
+ AddProperty(toKeyframe, CSSPropertyID::kLeft, "20px");
+ AddProperty(toKeyframe, CSSPropertyID::kTop, "40px");
+
+ AddInterpolation(interpolations_map, keyframes,
+ PropertyHandle(GetCSSPropertyLeft()));
+ AddInterpolation(interpolations_map, keyframes,
+ PropertyHandle(GetCSSPropertyTop()));
+
+ AnimationUtils::ForEachInterpolatedPropertyValue(
+ target, properties, interpolations_map, callback);
+ EXPECT_EQ(2U, map.size());
+ EXPECT_EQ("20px", map.at("left"));
+ EXPECT_EQ("40px", map.at("top"));
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/animation/compositor_animations_test.cc b/chromium/third_party/blink/renderer/core/animation/compositor_animations_test.cc
index 28975a1cf5e..d0434ff195f 100644
--- a/chromium/third_party/blink/renderer/core/animation/compositor_animations_test.cc
+++ b/chromium/third_party/blink/renderer/core/animation/compositor_animations_test.cc
@@ -349,6 +349,7 @@ class AnimationCompositorAnimationsTest : public PaintTestConfigurations,
compositor_keyframe_value_(
MakeGarbageCollected<CompositorKeyframeDouble>(offset)) {}
bool IsNeutral() const final { return true; }
+ bool IsRevert() const final { return false; }
PropertySpecificKeyframe* CloneWithOffset(double) const final {
NOTREACHED();
return nullptr;
@@ -616,11 +617,14 @@ TEST_P(AnimationCompositorAnimationsTest,
RegisterProperty(GetDocument(), "--bar", "<length>", "10px", false);
RegisterProperty(GetDocument(), "--loo", "<color>", "rgb(0, 0, 0)", false);
RegisterProperty(GetDocument(), "--x", "<number>", "0", false);
+ RegisterProperty(GetDocument(), "--y", "<number>", "200", false);
+ RegisterProperty(GetDocument(), "--z", "<number>", "200", false);
SetCustomProperty("--foo", "10");
SetCustomProperty("--bar", "10px");
SetCustomProperty("--loo", "rgb(0, 255, 0)");
SetCustomProperty("--x", "5");
+ UpdateAllLifecyclePhasesForTest();
auto style = GetDocument().EnsureStyleResolver().StyleForElement(element_);
EXPECT_TRUE(style->NonInheritedVariables());
EXPECT_TRUE(style->NonInheritedVariables()
@@ -635,6 +639,8 @@ TEST_P(AnimationCompositorAnimationsTest,
EXPECT_TRUE(style->NonInheritedVariables()
->GetData(AtomicString("--x"))
.value_or(nullptr));
+ EXPECT_TRUE(style->GetVariableData("--y"));
+ EXPECT_TRUE(style->GetVariableData("--z"));
NiceMock<MockCSSPaintImageGenerator>* mock_generator =
MakeGarbageCollected<NiceMock<MockCSSPaintImageGenerator>>();
@@ -648,6 +654,8 @@ TEST_P(AnimationCompositorAnimationsTest,
mock_generator->AddCustomProperty("--foo");
mock_generator->AddCustomProperty("--bar");
mock_generator->AddCustomProperty("--loo");
+ mock_generator->AddCustomProperty("--y");
+ mock_generator->AddCustomProperty("--z");
auto* ident = MakeGarbageCollected<CSSCustomIdentValue>("foopainter");
CSSPaintValue* paint_value = MakeGarbageCollected<CSSPaintValue>(ident);
paint_value->CreateGeneratorForTesting(GetDocument());
@@ -694,6 +702,18 @@ TEST_P(AnimationCompositorAnimationsTest,
EXPECT_EQ(
DuplicateSingleKeyframeAndTestIsCandidateOnResult(non_used_keyframe),
CompositorAnimations::kUnsupportedCSSProperty);
+
+ // Implicitly initial values are supported.
+ StringKeyframe* y_keyframe = CreateReplaceOpKeyframe("--y", "1000");
+ EXPECT_EQ(DuplicateSingleKeyframeAndTestIsCandidateOnResult(y_keyframe),
+ CompositorAnimations::kNoFailure);
+
+ // Implicitly initial values are not supported when the property
+ // has been referenced.
+ SetCustomProperty("opacity", "var(--z)");
+ StringKeyframe* z_keyframe = CreateReplaceOpKeyframe("--z", "1000");
+ EXPECT_EQ(DuplicateSingleKeyframeAndTestIsCandidateOnResult(z_keyframe),
+ CompositorAnimations::kUnsupportedCSSProperty);
}
TEST_P(AnimationCompositorAnimationsTest,
@@ -2021,7 +2041,7 @@ TEST_P(AnimationCompositorAnimationsTest,
const cc::PictureLayer* layer =
composited_layer_mapping->MainGraphicsLayer()->CcLayer();
ASSERT_NE(nullptr, layer);
- EXPECT_TRUE(layer->double_sided());
+ EXPECT_FALSE(layer->should_check_backface_visibility());
// Change the backface visibility, while the compositor animation is
// happening.
@@ -2030,7 +2050,7 @@ TEST_P(AnimationCompositorAnimationsTest,
// Make sure the setting made it to both blink and all the way to CC.
EXPECT_EQ(transform->GetBackfaceVisibilityForTesting(),
TransformPaintPropertyNode::BackfaceVisibility::kHidden);
- EXPECT_FALSE(layer->double_sided())
+ EXPECT_TRUE(layer->should_check_backface_visibility())
<< "Change to hidden did not get propagated to CC";
// Make sure the animation state is initialized in paint properties after
// blink pushing new paint properties without animation state change.
diff --git a/chromium/third_party/blink/renderer/core/animation/css/css_animation.cc b/chromium/third_party/blink/renderer/core/animation/css/css_animation.cc
index a6724f1e76e..3f471eb89fe 100644
--- a/chromium/third_party/blink/renderer/core/animation/css/css_animation.cc
+++ b/chromium/third_party/blink/renderer/core/animation/css/css_animation.cc
@@ -13,14 +13,16 @@ namespace blink {
CSSAnimation::CSSAnimation(ExecutionContext* execution_context,
AnimationTimeline* timeline,
AnimationEffect* content,
+ int animation_index,
const String& animation_name)
: Animation(execution_context, timeline, content),
+ animation_index_(animation_index),
animation_name_(animation_name),
ignore_css_play_state_(false) {
// The owning_element does not always equal to the target element of an
// animation. The following spec gives an example:
// https://drafts.csswg.org/css-animations-2/#owning-element-section
- owning_element_ = To<KeyframeEffect>(effect())->target();
+ owning_element_ = To<KeyframeEffect>(effect())->EffectTarget();
}
String CSSAnimation::playState() const {
diff --git a/chromium/third_party/blink/renderer/core/animation/css/css_animation.h b/chromium/third_party/blink/renderer/core/animation/css/css_animation.h
index b9ac74010a6..74d8594b83e 100644
--- a/chromium/third_party/blink/renderer/core/animation/css/css_animation.h
+++ b/chromium/third_party/blink/renderer/core/animation/css/css_animation.h
@@ -19,6 +19,7 @@ class CORE_EXPORT CSSAnimation : public Animation {
CSSAnimation(ExecutionContext*,
AnimationTimeline*,
AnimationEffect*,
+ int animation_index,
const String& animation_name);
bool IsCSSAnimation() const final { return true; }
@@ -27,6 +28,10 @@ class CORE_EXPORT CSSAnimation : public Animation {
Element* OwningElement() const override { return owning_element_; }
const String& animationName() const { return animation_name_; }
+ int AnimationIndex() const { return animation_index_; }
+ void SetAnimationIndex(wtf_size_t absolute_position) {
+ animation_index_ = absolute_position;
+ }
// Animation overrides.
// Various operations may affect the computed values of properties on
@@ -82,6 +87,10 @@ class CORE_EXPORT CSSAnimation : public Animation {
bool was_paused_;
};
+ // animation_index_ represents the absolute position of an animation within
+ // the same owning element. This index helps resolve the animation ordering
+ // when comparing two animations with the same owning element.
+ int animation_index_;
AtomicString animation_name_;
// When set, the web-animation API is overruling the animation-play-state
diff --git a/chromium/third_party/blink/renderer/core/animation/css/css_animation_update.h b/chromium/third_party/blink/renderer/core/animation/css/css_animation_update.h
index 1d9d400ae0c..9f0ce355fbc 100644
--- a/chromium/third_party/blink/renderer/core/animation/css/css_animation_update.h
+++ b/chromium/third_party/blink/renderer/core/animation/css/css_animation_update.h
@@ -28,12 +28,14 @@ class NewCSSAnimation {
public:
NewCSSAnimation(AtomicString name,
size_t name_index,
+ size_t position_index,
const InertEffect& effect,
Timing timing,
StyleRuleKeyframes* style_rule,
const Vector<EAnimPlayState>& play_state_list)
: name(name),
name_index(name_index),
+ position_index(position_index),
effect(effect),
timing(timing),
style_rule(style_rule),
@@ -47,6 +49,7 @@ class NewCSSAnimation {
AtomicString name;
size_t name_index;
+ size_t position_index;
Member<const InertEffect> effect;
Timing timing;
Member<StyleRuleKeyframes> style_rule;
@@ -109,13 +112,14 @@ class CORE_EXPORT CSSAnimationUpdate final {
void StartAnimation(const AtomicString& animation_name,
size_t name_index,
+ wtf_size_t position_index,
const InertEffect& effect,
const Timing& timing,
StyleRuleKeyframes* style_rule,
const Vector<EAnimPlayState>& play_state_list) {
new_animations_.push_back(NewCSSAnimation(animation_name, name_index,
- effect, timing, style_rule,
- play_state_list));
+ position_index, effect, timing,
+ style_rule, play_state_list));
}
void CancelAnimation(wtf_size_t index, const Animation& animation) {
cancelled_animation_indices_.push_back(index);
diff --git a/chromium/third_party/blink/renderer/core/animation/css/css_animations.cc b/chromium/third_party/blink/renderer/core/animation/css/css_animations.cc
index 7708587c3a0..fd85f0af7a1 100644
--- a/chromium/third_party/blink/renderer/core/animation/css/css_animations.cc
+++ b/chromium/third_party/blink/renderer/core/animation/css/css_animations.cc
@@ -39,8 +39,10 @@
#include "third_party/blink/renderer/core/animation/compositor_animations.h"
#include "third_party/blink/renderer/core/animation/css/compositor_keyframe_value_factory.h"
#include "third_party/blink/renderer/core/animation/css/css_animation.h"
+#include "third_party/blink/renderer/core/animation/css/css_keyframe_effect_model.h"
#include "third_party/blink/renderer/core/animation/css/css_transition.h"
#include "third_party/blink/renderer/core/animation/css_interpolation_types_map.h"
+#include "third_party/blink/renderer/core/animation/document_animations.h"
#include "third_party/blink/renderer/core/animation/document_timeline.h"
#include "third_party/blink/renderer/core/animation/element_animations.h"
#include "third_party/blink/renderer/core/animation/inert_effect.h"
@@ -84,28 +86,22 @@ using PropertySet = HashSet<const CSSProperty*>;
namespace {
-StringKeyframeEffectModel* CreateKeyframeEffectModel(
- StyleResolver* resolver,
- const Element* animating_element,
- Element& element,
- const ComputedStyle* style,
+// Processes keyframe rules, extracting the timing function and properties being
+// animated for each keyframe. The extraction process is doing more work that
+// strictly required for the setup to step 5 in the spec
+// (https://drafts.csswg.org/css-animations-2/#keyframes) as an optimization
+// to avoid needing to process each rule multiple times to extract different
+// properties.
+StringKeyframeVector ProcessKeyframesRule(
+ const StyleRuleKeyframes* keyframes_rule,
+ const Document& document,
const ComputedStyle* parent_style,
- const AtomicString& name,
- TimingFunction* default_timing_function,
- size_t animation_index) {
- // When the animating element is null, use its parent for scoping purposes.
- const Element* element_for_scoping =
- animating_element ? animating_element : &element;
- const StyleRuleKeyframes* keyframes_rule =
- resolver->FindKeyframesRule(element_for_scoping, name);
- DCHECK(keyframes_rule);
-
+ TimingFunction* default_timing_function) {
StringKeyframeVector keyframes;
+ PropertySet specified_properties_for_use_counter;
const HeapVector<Member<StyleRuleKeyframe>>& style_keyframes =
keyframes_rule->Keyframes();
- // Construct and populate the style for each keyframe
- PropertySet specified_properties_for_use_counter;
for (wtf_size_t i = 0; i < style_keyframes.size(); ++i) {
const StyleRuleKeyframe* style_keyframe = style_keyframes[i].Get();
auto* keyframe = MakeGarbageCollected<StringKeyframe>();
@@ -145,55 +141,252 @@ StringKeyframeEffectModel* CreateKeyframeEffectModel(
for (const CSSProperty* property : specified_properties_for_use_counter) {
DCHECK(isValidCSSPropertyID(property->PropertyID()));
- element_for_scoping->GetDocument().CountAnimatedProperty(
- property->PropertyID());
+ document.CountAnimatedProperty(property->PropertyID());
}
- // Merge duplicate keyframes.
std::stable_sort(keyframes.begin(), keyframes.end(),
[](const Member<Keyframe>& a, const Member<Keyframe>& b) {
return a->CheckedOffset() < b->CheckedOffset();
});
- wtf_size_t target_index = 0;
- for (wtf_size_t i = 1; i < keyframes.size(); i++) {
- if (keyframes[i]->CheckedOffset() ==
- keyframes[target_index]->CheckedOffset()) {
- for (const auto& property : keyframes[i]->Properties()) {
- keyframes[target_index]->SetCSSPropertyValue(
- property.GetCSSProperty(),
- keyframes[i]->CssPropertyValue(property));
- }
+ return keyframes;
+}
+
+// Finds the index of a keyframe with matching offset and easing.
+base::Optional<int> FindIndexOfMatchingKeyframe(
+ const StringKeyframeVector& keyframes,
+ wtf_size_t start_index,
+ double offset,
+ const TimingFunction& easing) {
+ for (wtf_size_t i = start_index; i < keyframes.size(); i++) {
+ StringKeyframe* keyframe = keyframes[i];
+
+ // Keyframes are sorted by offset. Search can stop once we hit and offset
+ // that exceeds the target value.
+ if (offset < keyframe->CheckedOffset())
+ break;
+
+ if (easing.ToString() == keyframe->Easing().ToString())
+ return i;
+ }
+ return base::nullopt;
+}
+
+// Tests conditions for inserting a bounding keyframe, which are outlined in
+// steps 6 and 7 of the spec for keyframe construction.
+// https://drafts.csswg.org/css-animations-2/#keyframes
+bool NeedsBoundaryKeyframe(StringKeyframe* candidate,
+ double offset,
+ const PropertySet& animated_properties,
+ const PropertySet& bounding_properties,
+ TimingFunction* default_timing_function) {
+ if (!candidate)
+ return true;
+
+ if (candidate->CheckedOffset() != offset)
+ return true;
+
+ if (bounding_properties.size() == animated_properties.size())
+ return false;
+
+ return candidate->Easing().ToString() != default_timing_function->ToString();
+}
+
+StringKeyframeEffectModel* CreateKeyframeEffectModel(
+ StyleResolver* resolver,
+ const Element* animating_element,
+ Element& element,
+ const ComputedStyle* style,
+ const ComputedStyle* parent_style,
+ const AtomicString& name,
+ TimingFunction* default_timing_function,
+ size_t animation_index) {
+ // The algorithm for constructing string keyframes for a CSS animation is
+ // covered in the following spec:
+ // https://drafts.csswg.org/css-animations-2/#keyframes
+
+ // For a given target (pseudo-)element, element, animation name, and
+ // position of the animation in element’s animation-name list, keyframe
+ // objects are generated as follows:
+
+ // 1. Let default timing function be the timing function at the position
+ // of the resolved value of the animation-timing-function for element,
+ // repeating the list as necessary as described in CSS Animations 1 §4.2
+ // The animation-name property.
+
+ // 2. Find the last @keyframes at-rule in document order with <keyframes-name>
+ // matching name.
+ // If there is no @keyframes at-rule with <keyframes-name> matching name,
+ // abort this procedure. In this case no animation is generated, and any
+ // existing animation matching name is canceled.
+
+ const StyleRuleKeyframes* keyframes_rule =
+ resolver->FindKeyframesRule(&element, name);
+ DCHECK(keyframes_rule);
+
+ // 3. Let keyframes be an empty sequence of keyframe objects.
+ StringKeyframeVector keyframes;
+
+ // 4. Let animated properties be an empty set of longhand CSS property names.
+ PropertySet animated_properties;
+
+ // Start and end properties are also tracked to simplify the process of
+ // determining if the first and last keyframes are missing properties.
+ PropertySet start_properties;
+ PropertySet end_properties;
+
+ // Properties that have already been processed at the current keyframe.
+ PropertySet current_offset_properties;
+
+ // 5. Perform a stable sort of the keyframe blocks in the @keyframes rule by
+ // the offset specified in the keyframe selector, and iterate over the
+ // result in reverse applying the following steps:
+ keyframes = ProcessKeyframesRule(keyframes_rule, element.GetDocument(),
+ parent_style, default_timing_function);
+
+ double last_offset = 1;
+ wtf_size_t merged_frame_count = 0;
+ for (wtf_size_t i = keyframes.size(); i > 0; --i) {
+ // 5.1 Let keyframe offset be the value of the keyframe selector converted
+ // to a value in the range 0 ≤ keyframe offset ≤ 1.
+ int source_index = i - 1;
+ StringKeyframe* rule_keyframe = keyframes[source_index];
+ double keyframe_offset = rule_keyframe->CheckedOffset();
+
+ // 5.2 Let keyframe timing function be the value of the last valid
+ // declaration of animation-timing-function specified on the keyframe
+ // block, or, if there is no such valid declaration, default timing
+ // function.
+ const TimingFunction& easing = rule_keyframe->Easing();
+
+ // 5.3 After converting keyframe timing function to its canonical form (e.g.
+ // such that step-end becomes steps(1, end)) let keyframe refer to the
+ // existing keyframe in keyframes with matching keyframe offset and
+ // timing function, if any.
+ // If there is no such existing keyframe, let keyframe be a new empty
+ // keyframe with offset, keyframe offset, and timing function, keyframe
+ // timing function, and prepend it to keyframes.
+
+ // Prevent stomping a rule override by tracking properties applied at
+ // the current offset.
+ if (last_offset != keyframe_offset) {
+ current_offset_properties.clear();
+ last_offset = keyframe_offset;
+ }
+
+ // Avoid unnecessary creation of extra keyframes by merging into
+ // existing keyframes.
+ base::Optional<int> existing_keyframe_index = FindIndexOfMatchingKeyframe(
+ keyframes, source_index + merged_frame_count + 1, keyframe_offset,
+ easing);
+ int target_index;
+ if (existing_keyframe_index) {
+ // Merge keyframe propoerties.
+ target_index = existing_keyframe_index.value();
+ merged_frame_count++;
} else {
- target_index++;
- keyframes[target_index] = keyframes[i];
+ target_index = source_index + merged_frame_count;
+ if (target_index != source_index) {
+ // Move keyframe to fill the gap.
+ keyframes[target_index] = keyframes[source_index];
+ source_index = target_index;
+ }
+ }
+
+ // 5.4 Iterate over all declarations in the keyframe block and add them to
+ // keyframe such that:
+ // * All variable references are resolved to their current values.
+ // * Each shorthand property is expanded to its longhand subproperties.
+ // * All logical properties are converted to their equivalent physical
+ // properties.
+ // * For any expanded physical longhand properties that appear more than
+ // once, only the last declaration in source order is added.
+ // Note, since multiple keyframe blocks may specify the same keyframe
+ // offset, and since this algorithm iterates over these blocks in
+ // reverse, this implies that if any properties are encountered that
+ // have already added at this same keyframe offset, they should be
+ // skipped.
+ // * All property values are replaced with their computed values.
+ // 5.5 Add each physical longhand property name that was added to keyframe
+ // to animated properties.
+
+ // TODO(crbug.com/1070627): Convert logical properties.
+ StringKeyframe* keyframe = keyframes[target_index];
+ for (const auto& property : rule_keyframe->Properties()) {
+ const CSSProperty& css_property = property.GetCSSProperty();
+
+ // Since processing keyframes in reverse order, skipping properties that
+ // have already been inserted prevents overwriting a later merged
+ // keyframe.
+ if (current_offset_properties.Contains(&css_property))
+ continue;
+
+ if (source_index != target_index) {
+ keyframe->SetCSSPropertyValue(
+ css_property, rule_keyframe->CssPropertyValue(property));
+ }
+
+ current_offset_properties.insert(&css_property);
+ animated_properties.insert(&css_property);
+ if (keyframe_offset == 0)
+ start_properties.insert(&css_property);
+ else if (keyframe_offset == 1)
+ end_properties.insert(&css_property);
}
}
- if (!keyframes.IsEmpty())
- keyframes.Shrink(target_index + 1);
- // Add 0% and 100% keyframes if absent.
+ // Compact the vector of keyframes if any keyframes have been merged.
+ keyframes.EraseAt(0, merged_frame_count);
+
+ // 6. If there is no keyframe in keyframes with offset 0, or if amongst the
+ // keyframes in keyframes with offset 0 not all of the properties in
+ // animated properties are present,
+ //
+ // 6.1 Let initial keyframe be the keyframe in keyframes with offset 0 and
+ // timing function default timing function.
+ // 6.2 If there is no such keyframe, let initial keyframe be a new empty
+ // keyframe with offset 0, and timing function default timing function,
+ // and add it to keyframes after the last keyframe with offset 0.
+ // 6.3 For each property in animated properties that is not present in some
+ // other keyframe with offset 0, add the computed value of that property
+ // for element to the keyframe.
StringKeyframe* start_keyframe = keyframes.IsEmpty() ? nullptr : keyframes[0];
- if (!start_keyframe || keyframes[0]->CheckedOffset() != 0) {
+ if (NeedsBoundaryKeyframe(start_keyframe, 0, animated_properties,
+ start_properties, default_timing_function)) {
start_keyframe = MakeGarbageCollected<StringKeyframe>();
start_keyframe->SetOffset(0);
start_keyframe->SetEasing(default_timing_function);
keyframes.push_front(start_keyframe);
}
+
+ // 7. Similarly, if there is no keyframe in keyframes with offset 1, or if
+ // amongst the keyframes in keyframes with offset 1 not all of the
+ // properties in animated properties are present,
+ //
+ // 7.1 Let final keyframe be the keyframe in keyframes with offset 1 and
+ // timing function default timing function.
+ // 7.2 If there is no such keyframe, let final keyframe be a new empty
+ // keyframe with offset 1, and timing function default timing function,
+ // and add it to keyframes after the last keyframe with offset 1.
+ // 7.3 For each property in animated properties that is not present in some
+ // other keyframe with offset 1, add the computed value of that property
+ // for element to the keyframe.
StringKeyframe* end_keyframe = keyframes[keyframes.size() - 1];
- if (end_keyframe->CheckedOffset() != 1) {
+ if (NeedsBoundaryKeyframe(end_keyframe, 1, animated_properties,
+ end_properties, default_timing_function)) {
end_keyframe = MakeGarbageCollected<StringKeyframe>();
end_keyframe->SetOffset(1);
end_keyframe->SetEasing(default_timing_function);
keyframes.push_back(end_keyframe);
}
+
DCHECK_GE(keyframes.size(), 2U);
DCHECK_EQ(keyframes.front()->CheckedOffset(), 0);
DCHECK_EQ(keyframes.back()->CheckedOffset(), 1);
- auto* model = MakeGarbageCollected<StringKeyframeEffectModel>(
- keyframes, EffectModel::kCompositeReplace, &keyframes[0]->Easing());
+ auto* model = MakeGarbageCollected<CssKeyframeEffectModel>(
+ keyframes, EffectModel::kCompositeReplace, &start_keyframe->Easing());
if (animation_index > 0 && model->HasSyntheticKeyframes()) {
- UseCounter::Count(element_for_scoping->GetDocument(),
+ UseCounter::Count(element.GetDocument(),
WebFeature::kCSSAnimationsStackedNeutralKeyframe);
}
return model;
@@ -214,7 +407,13 @@ std::unique_ptr<TypedInterpolationValue> SampleAnimation(
DCHECK_LE(sample.size(), 1u);
if (sample.IsEmpty())
return nullptr;
- return To<TransitionInterpolation>(*sample.at(0)).GetInterpolatedValue();
+ if (auto* transition_interpolation =
+ DynamicTo<TransitionInterpolation>(*sample.at(0)))
+ return transition_interpolation->GetInterpolatedValue();
+ // TODO(crbug.com/1086167): The *sample.at(0) could be
+ // InvalidtableInterpolation pointer. In this case, we currently return a
+ // nullptr, but we will need to support the InvalidtableInterpolation type.
+ return nullptr;
}
// Returns the start time of an animation given the start delay. A negative
@@ -363,8 +562,6 @@ void CSSAnimations::CalculateAnimationUpdate(CSSAnimationUpdate& update,
const CSSAnimationData* animation_data = style.Animations();
const CSSAnimations* css_animations =
element_animations ? &element_animations->CssAnimations() : nullptr;
- const Element* element_for_scoping =
- animating_element ? animating_element : &element;
Vector<bool> cancel_running_animation_flags(
css_animations ? css_animations->running_animations_.size() : 0);
@@ -396,7 +593,7 @@ void CSSAnimations::CalculateAnimationUpdate(CSSAnimationUpdate& update,
timing.timing_function = Timing().timing_function;
StyleRuleKeyframes* keyframes_rule =
- resolver->FindKeyframesRule(element_for_scoping, name);
+ resolver->FindKeyframesRule(&element, name);
if (!keyframes_rule)
continue; // Cancel the animation if there's no style rule for it.
@@ -422,7 +619,7 @@ void CSSAnimations::CalculateAnimationUpdate(CSSAnimationUpdate& update,
CSSAnimation* animation =
DynamicTo<CSSAnimation>(existing_animation->animation.Get());
-
+ animation->SetAnimationIndex(i);
const bool was_paused =
CSSTimingData::GetRepeated(existing_animation->play_state_list,
i) == EAnimPlayState::kPaused;
@@ -460,7 +657,7 @@ void CSSAnimations::CalculateAnimationUpdate(CSSAnimationUpdate& update,
} else {
DCHECK(!is_animation_style_change);
update.StartAnimation(
- name, name_index,
+ name, name_index, i,
*MakeGarbageCollected<InertEffect>(
CreateKeyframeEffectModel(resolver, animating_element, element,
&style, parent_style, name,
@@ -608,7 +805,7 @@ void CSSAnimations::MaybeApplyPendingUpdate(Element* element) {
auto* animation = MakeGarbageCollected<CSSAnimation>(
element->GetExecutionContext(), &(element->GetDocument().Timeline()),
- effect, entry.name);
+ effect, entry.position_index, entry.name);
animation->play();
if (inert_animation->Paused())
animation->pause();
@@ -680,14 +877,15 @@ void CSSAnimations::MaybeApplyPendingUpdate(Element* element) {
KeyframeEffect::kTransitionPriority, event_delegate);
auto* animation = MakeGarbageCollected<CSSTransition>(
element->GetExecutionContext(), &(element->GetDocument().Timeline()),
- transition_effect, property);
+ transition_effect,
+ element->GetDocument().GetDocumentAnimations().TransitionGeneration(),
+ property);
animation->play();
// Set the current time as the start time for retargeted transitions
if (retargeted_compositor_transitions.Contains(property)) {
- animation->setStartTime(element->GetDocument().Timeline().currentTime(),
- false);
+ animation->setStartTime(element->GetDocument().Timeline().currentTime());
}
animation->Update(kTimingUpdateOnDemand);
running_transition.animation = animation;
@@ -1056,6 +1254,12 @@ bool IsCustomPropertyHandle(const PropertyHandle& property) {
return property.IsCSSCustomProperty();
}
+bool IsFontAffectingPropertyHandle(const PropertyHandle& property) {
+ if (property.IsCSSCustomProperty() || !property.IsCSSProperty())
+ return false;
+ return property.GetCSSProperty().AffectsFont();
+}
+
// TODO(alancutter): CSS properties and presentation attributes may have
// identical effects. By grouping them in the same set we introduce a bug where
// arbitrary hash iteration will determine the order the apply in and thus which
@@ -1294,6 +1498,13 @@ void CSSAnimations::TransitionEventDelegate::OnEventCondition(
Timing::Phase current_phase) {
if (current_phase == previous_phase_)
return;
+ // Our implement of transition_generation is slightly different from the spec
+ // We increment the transition_generation per transition event instead of per
+ // style change event. A state transition would trigger one or more events.
+ // Thus, the spec version increments more than is necessary to ensure a change
+ // in transition generation. Spec defines style-change-event:
+ // https://drafts.csswg.org/css-transitions-1/#style-change-event
+ GetDocument().GetDocumentAnimations().IncrementTrasitionGeneration();
if (GetDocument().HasListenerType(Document::kTransitionRunListener)) {
if (previous_phase_ == Timing::kPhaseNone) {
@@ -1430,6 +1641,7 @@ bool CSSAnimations::IsAnimationAffectingProperty(const CSSProperty& property) {
case CSSPropertyID::kTransitionProperty:
case CSSPropertyID::kTransitionTimingFunction:
case CSSPropertyID::kUnicodeBidi:
+ case CSSPropertyID::kWebkitWritingMode:
case CSSPropertyID::kWillChange:
case CSSPropertyID::kWritingMode:
return true;
@@ -1459,6 +1671,28 @@ bool CSSAnimations::IsAnimatingCustomProperties(
IsCustomPropertyHandle);
}
+bool CSSAnimations::IsAnimatingStandardProperties(
+ const ElementAnimations* element_animations,
+ const CSSBitset* bitset,
+ KeyframeEffect::Priority priority) {
+ if (!element_animations || !bitset)
+ return false;
+ return element_animations->GetEffectStack().AffectsProperties(*bitset,
+ priority);
+}
+
+bool CSSAnimations::IsAnimatingFontAffectingProperties(
+ const ElementAnimations* element_animations) {
+ return element_animations &&
+ element_animations->GetEffectStack().AffectsProperties(
+ IsFontAffectingPropertyHandle);
+}
+
+bool CSSAnimations::IsAnimatingRevert(
+ const ElementAnimations* element_animations) {
+ return element_animations && element_animations->GetEffectStack().HasRevert();
+}
+
void CSSAnimations::Trace(Visitor* visitor) {
visitor->Trace(transitions_);
visitor->Trace(pending_update_);
diff --git a/chromium/third_party/blink/renderer/core/animation/css/css_animations.h b/chromium/third_party/blink/renderer/core/animation/css/css_animations.h
index b6b99f74c68..57f29e16901 100644
--- a/chromium/third_party/blink/renderer/core/animation/css/css_animations.h
+++ b/chromium/third_party/blink/renderer/core/animation/css/css_animations.h
@@ -39,6 +39,7 @@
#include "third_party/blink/renderer/core/animation/interpolation.h"
#include "third_party/blink/renderer/core/css/css_keyframes_rule.h"
#include "third_party/blink/renderer/core/css/css_property_value_set.h"
+#include "third_party/blink/renderer/core/css/properties/css_bitset.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/element.h"
#include "third_party/blink/renderer/platform/wtf/hash_map.h"
@@ -61,6 +62,11 @@ class CORE_EXPORT CSSAnimations final {
static bool IsAnimationAffectingProperty(const CSSProperty&);
static bool IsAffectedByKeyframesFromScope(const Element&, const TreeScope&);
static bool IsAnimatingCustomProperties(const ElementAnimations*);
+ static bool IsAnimatingStandardProperties(const ElementAnimations*,
+ const CSSBitset*,
+ KeyframeEffect::Priority);
+ static bool IsAnimatingFontAffectingProperties(const ElementAnimations*);
+ static bool IsAnimatingRevert(const ElementAnimations*);
static void CalculateAnimationUpdate(CSSAnimationUpdate&,
const Element* animating_element,
Element&,
diff --git a/chromium/third_party/blink/renderer/core/animation/css/css_keyframe_effect_model.cc b/chromium/third_party/blink/renderer/core/animation/css/css_keyframe_effect_model.cc
new file mode 100644
index 00000000000..8bfce642f24
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/animation/css/css_keyframe_effect_model.cc
@@ -0,0 +1,122 @@
+// 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/core/animation/css/css_keyframe_effect_model.h"
+
+#include "third_party/blink/renderer/core/animation/animation_input_helpers.h"
+#include "third_party/blink/renderer/core/animation/animation_utils.h"
+#include "third_party/blink/renderer/core/animation/property_handle.h"
+#include "third_party/blink/renderer/core/animation/string_keyframe.h"
+#include "third_party/blink/renderer/core/css/properties/css_property.h"
+
+namespace blink {
+
+namespace {
+
+using MissingPropertyValueMap = HashMap<String, String>;
+
+void ResolveUnderlyingPropertyValues(Element& element,
+ const PropertyHandleSet& properties,
+ MissingPropertyValueMap& map) {
+ // TODO(crbug.com/1069235): Should sample the underlying animation.
+ ActiveInterpolationsMap empty_interpolations_map;
+ AnimationUtils::ForEachInterpolatedPropertyValue(
+ &element, properties, empty_interpolations_map,
+ WTF::BindRepeating(
+ [](MissingPropertyValueMap* map, PropertyHandle property,
+ const CSSValue* value) {
+ if (property.IsCSSProperty()) {
+ String property_name =
+ AnimationInputHelpers::PropertyHandleToKeyframeAttribute(
+ property);
+ map->Set(property_name, value->CssText());
+ }
+ },
+ WTF::Unretained(&map)));
+}
+
+void AddMissingProperties(const MissingPropertyValueMap& property_map,
+ const PropertyHandleSet& all_properties,
+ const PropertyHandleSet& keyframe_properties,
+ StringKeyframe* keyframe) {
+ for (const auto& property : all_properties) {
+ if (keyframe_properties.Contains(property))
+ continue;
+
+ String property_name =
+ AnimationInputHelpers::PropertyHandleToKeyframeAttribute(property);
+ if (property_map.Contains(property_name)) {
+ const String& value = property_map.at(property_name);
+ if (property.IsCSSCustomProperty()) {
+ keyframe->SetCSSPropertyValue(property.CustomPropertyName(), value,
+ SecureContextMode::kInsecureContext,
+ nullptr);
+ } else {
+ keyframe->SetCSSPropertyValue(
+ property.GetCSSProperty().PropertyID(), value,
+ SecureContextMode::kInsecureContext, nullptr);
+ }
+ }
+ }
+}
+
+} // namespace
+
+KeyframeEffectModelBase::KeyframeVector
+CssKeyframeEffectModel::GetComputedKeyframes(Element* element) {
+ const KeyframeEffectModelBase::KeyframeVector& keyframes = GetFrames();
+ if (!element)
+ return keyframes;
+
+ KeyframeEffectModelBase::KeyframeVector computed_keyframes;
+
+ // Lazy resolution of values for missing properties.
+ PropertyHandleSet all_properties = Properties();
+ PropertyHandleSet from_properties;
+ PropertyHandleSet to_properties;
+
+ Vector<double> computed_offsets =
+ KeyframeEffectModelBase::GetComputedOffsets(keyframes);
+ computed_keyframes.ReserveInitialCapacity(keyframes.size());
+ for (wtf_size_t i = 0; i < keyframes.size(); i++) {
+ Keyframe* keyframe = keyframes[i];
+ // TODO(crbug.com/1070627): Use computed values, prune variable references,
+ // and convert logical properties to physical properties.
+ computed_keyframes.push_back(keyframe->Clone());
+ double offset = computed_offsets[i];
+ if (offset == 0) {
+ for (const auto& property : keyframe->Properties()) {
+ from_properties.insert(property);
+ }
+ } else if (offset == 1) {
+ for (const auto& property : keyframe->Properties()) {
+ to_properties.insert(property);
+ }
+ }
+ }
+
+ // Add missing properties from the bounding keyframes.
+ MissingPropertyValueMap missing_property_value_map;
+ if (from_properties.size() < all_properties.size() ||
+ to_properties.size() < all_properties.size()) {
+ ResolveUnderlyingPropertyValues(*element, all_properties,
+ missing_property_value_map);
+ }
+ if (from_properties.size() < all_properties.size() &&
+ !computed_keyframes.IsEmpty()) {
+ AddMissingProperties(
+ missing_property_value_map, all_properties, from_properties,
+ DynamicTo<StringKeyframe>(computed_keyframes[0].Get()));
+ }
+ if (to_properties.size() < all_properties.size() &&
+ !computed_keyframes.IsEmpty()) {
+ wtf_size_t index = keyframes.size() - 1;
+ AddMissingProperties(
+ missing_property_value_map, all_properties, to_properties,
+ DynamicTo<StringKeyframe>(computed_keyframes[index].Get()));
+ }
+ return computed_keyframes;
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/animation/css/css_keyframe_effect_model.h b/chromium/third_party/blink/renderer/core/animation/css/css_keyframe_effect_model.h
new file mode 100644
index 00000000000..8ccb38983fc
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/animation/css/css_keyframe_effect_model.h
@@ -0,0 +1,42 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// This variant of the keyframe effect model performs additional processing
+// for computed keyframes. The algorithm for constructing keyframes for a CSS
+// animation is covered in the following spec:
+// https://drafts.csswg.org/css-animations-2/#keyframes
+//
+// Most of the steps for constructing computed keyframes are handled during
+// the construction process; however, evaluation of computed property values
+// is handled as a lazy operation when fetching the keyframes.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_CSS_CSS_KEYFRAME_EFFECT_MODEL_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_CSS_CSS_KEYFRAME_EFFECT_MODEL_H_
+
+#include "third_party/blink/renderer/core/animation/keyframe_effect_model.h"
+
+namespace blink {
+
+class CssKeyframeEffectModel : public StringKeyframeEffectModel {
+ public:
+ explicit CssKeyframeEffectModel(
+ const KeyframeVector& keyframes,
+ CompositeOperation composite = kCompositeReplace,
+ scoped_refptr<TimingFunction> default_keyframe_easing = nullptr)
+ : StringKeyframeEffectModel(keyframes,
+ composite,
+ std::move(default_keyframe_easing)) {}
+
+ // Overridden to fill in missing property values for generated "from" and "to"
+ // keyframes. TODO(crbug.com/1070627): Also perform the following steps:
+ // 1) filter variables from keyframes, 2) use computed values for properties
+ // rather than values from the keyframes rule, and 3) switch logical to
+ // physical properties.
+ KeyframeEffectModelBase::KeyframeVector GetComputedKeyframes(
+ Element* element) override;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_CSS_CSS_KEYFRAME_EFFECT_MODEL_H_
diff --git a/chromium/third_party/blink/renderer/core/animation/css/css_transition.cc b/chromium/third_party/blink/renderer/core/animation/css/css_transition.cc
index 4c422485122..be18131ce01 100644
--- a/chromium/third_party/blink/renderer/core/animation/css/css_transition.cc
+++ b/chromium/third_party/blink/renderer/core/animation/css/css_transition.cc
@@ -13,12 +13,14 @@ namespace blink {
CSSTransition::CSSTransition(ExecutionContext* execution_context,
AnimationTimeline* timeline,
AnimationEffect* content,
+ uint64_t transition_generation,
const PropertyHandle& transition_property)
: Animation(execution_context, timeline, content),
transition_property_(transition_property) {
// The owning_element does not always equal to the target element of an
// animation.
- owning_element_ = To<KeyframeEffect>(effect())->target();
+ owning_element_ = To<KeyframeEffect>(effect())->EffectTarget();
+ transition_generation_ = transition_generation;
}
AtomicString CSSTransition::transitionProperty() const {
diff --git a/chromium/third_party/blink/renderer/core/animation/css/css_transition.h b/chromium/third_party/blink/renderer/core/animation/css/css_transition.h
index 07b5debd496..3cc07c039ab 100644
--- a/chromium/third_party/blink/renderer/core/animation/css/css_transition.h
+++ b/chromium/third_party/blink/renderer/core/animation/css/css_transition.h
@@ -19,6 +19,7 @@ class CORE_EXPORT CSSTransition : public Animation {
CSSTransition(ExecutionContext*,
AnimationTimeline*,
AnimationEffect*,
+ uint64_t transition_generation,
const PropertyHandle& transition_property);
bool IsCSSTransition() const final { return true; }
@@ -26,6 +27,7 @@ class CORE_EXPORT CSSTransition : public Animation {
void ClearOwningElement() final { owning_element_ = nullptr; }
Element* OwningElement() const override { return owning_element_; }
+ uint64_t TransitionGeneration() const { return transition_generation_; }
AtomicString transitionProperty() const;
const CSSProperty& TransitionCSSProperty() const {
return transition_property_.GetCSSProperty();
@@ -57,6 +59,7 @@ class CORE_EXPORT CSSTransition : public Animation {
// to which the transition-property property was applied that generated the
// animation.
Member<Element> owning_element_;
+ uint64_t transition_generation_;
};
template <>
struct DowncastTraits<CSSTransition> {
diff --git a/chromium/third_party/blink/renderer/core/animation/css_interpolation_environment.cc b/chromium/third_party/blink/renderer/core/animation/css_interpolation_environment.cc
index bb8bb38fdbc..237c8b1a086 100644
--- a/chromium/third_party/blink/renderer/core/animation/css_interpolation_environment.cc
+++ b/chromium/third_party/blink/renderer/core/animation/css_interpolation_environment.cc
@@ -19,7 +19,7 @@ const CSSValue* CSSInterpolationEnvironment::Resolve(
if (!value)
return value;
return cascade_->Resolve(property.GetCSSPropertyName(), *value,
- *cascade_resolver_);
+ CascadeOrigin::kAnimation, *cascade_resolver_);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/animation/css_interpolation_type.cc b/chromium/third_party/blink/renderer/core/animation/css_interpolation_type.cc
index fcc56d7d292..64f4ad96ace 100644
--- a/chromium/third_party/blink/renderer/core/animation/css_interpolation_type.cc
+++ b/chromium/third_party/blink/renderer/core/animation/css_interpolation_type.cc
@@ -12,6 +12,10 @@
#include "third_party/blink/renderer/core/animation/string_keyframe.h"
#include "third_party/blink/renderer/core/css/computed_style_css_value_mapping.h"
#include "third_party/blink/renderer/core/css/css_custom_property_declaration.h"
+#include "third_party/blink/renderer/core/css/css_inherited_value.h"
+#include "third_party/blink/renderer/core/css/css_initial_value.h"
+#include "third_party/blink/renderer/core/css/css_revert_value.h"
+#include "third_party/blink/renderer/core/css/css_unset_value.h"
#include "third_party/blink/renderer/core/css/css_value.h"
#include "third_party/blink/renderer/core/css/css_variable_reference_value.h"
#include "third_party/blink/renderer/core/css/parser/css_tokenizer.h"
@@ -124,6 +128,27 @@ class ResolvedRegisteredCustomPropertyChecker
scoped_refptr<CSSVariableData> resolved_tokens_;
};
+class RevertChecker : public CSSInterpolationType::ConversionChecker {
+ public:
+ RevertChecker(const PropertyHandle& property_handle,
+ const CSSValue* resolved_value)
+ : property_handle_(property_handle), resolved_value_(resolved_value) {
+ DCHECK(RuntimeEnabledFeatures::CSSRevertEnabled());
+ }
+
+ private:
+ bool IsValid(const InterpolationEnvironment& environment,
+ const InterpolationValue&) const final {
+ const auto& css_environment = To<CSSInterpolationEnvironment>(environment);
+ const CSSValue* current_resolved_value = css_environment.Resolve(
+ property_handle_, cssvalue::CSSRevertValue::Create());
+ return DataEquivalent(resolved_value_.Get(), current_resolved_value);
+ }
+
+ PropertyHandle property_handle_;
+ Persistent<const CSSValue> resolved_value_;
+};
+
CSSInterpolationType::CSSInterpolationType(
PropertyHandle property,
const PropertyRegistration* registration)
@@ -183,6 +208,14 @@ InterpolationValue CSSInterpolationType::MaybeConvertSingleInternal(
value = resolved_value;
}
+ if (value->IsRevertValue()) {
+ DCHECK(RuntimeEnabledFeatures::CSSRevertEnabled());
+ value = css_environment.Resolve(GetProperty(), value);
+ DCHECK(value);
+ conversion_checkers.push_back(
+ std::make_unique<RevertChecker>(GetProperty(), value));
+ }
+
bool is_inherited = CssProperty().IsInherited();
if (value->IsInitialValue() || (value->IsUnsetValue() && !is_inherited)) {
return MaybeConvertInitial(state, conversion_checkers);
@@ -205,6 +238,68 @@ InterpolationValue CSSInterpolationType::MaybeConvertCustomPropertyDeclaration(
const AtomicString& name = declaration.GetName();
DCHECK_EQ(GetProperty().CustomPropertyName(), name);
+ if (RuntimeEnabledFeatures::CSSCascadeEnabled()) {
+ const CSSValue* value = &declaration;
+ value = css_environment.Resolve(GetProperty(), value);
+ DCHECK(value) << "CSSVarCycleInterpolationType should have handled nullptr";
+
+ if (declaration.IsRevert()) {
+ DCHECK(RuntimeEnabledFeatures::CSSRevertEnabled());
+ conversion_checkers.push_back(
+ std::make_unique<RevertChecker>(GetProperty(), value));
+ }
+ if (const auto* resolved_declaration =
+ DynamicTo<CSSCustomPropertyDeclaration>(value)) {
+ // If Resolve returned a different CSSCustomPropertyDeclaration, var()
+ // references were substituted.
+ if (resolved_declaration != &declaration) {
+ conversion_checkers.push_back(
+ std::make_unique<ResolvedRegisteredCustomPropertyChecker>(
+ declaration, resolved_declaration->Value()));
+ }
+ }
+
+ // Unfortunately we transport CSS-wide keywords inside the
+ // CSSCustomPropertyDeclaration. Expand those keywords into real CSSValues
+ // if present.
+ bool is_inherited = Registration().Inherits();
+ if (const auto* resolved_declaration =
+ DynamicTo<CSSCustomPropertyDeclaration>(value)) {
+ if (resolved_declaration->IsInitial(is_inherited))
+ value = CSSInitialValue::Create();
+ else if (resolved_declaration->IsInherit(is_inherited))
+ value = CSSInheritedValue::Create();
+ }
+
+ // Handle CSS-wide keywords (except 'revert', which should have been
+ // handled already).
+ DCHECK(!value->IsRevertValue());
+ if (value->IsInitialValue() || (value->IsUnsetValue() && !is_inherited)) {
+ value = Registration().Initial();
+ } else if (value->IsInheritedValue() ||
+ (value->IsUnsetValue() && is_inherited)) {
+ value = state.ParentStyle()->GetVariableValue(name, is_inherited);
+ if (!value) {
+ value = Registration().Initial();
+ }
+ conversion_checkers.push_back(
+ std::make_unique<InheritedCustomPropertyChecker>(
+ name, is_inherited, value, Registration().Initial()));
+ }
+
+ if (const auto* resolved_declaration =
+ DynamicTo<CSSCustomPropertyDeclaration>(value)) {
+ DCHECK(resolved_declaration->Value());
+ value = resolved_declaration->Value()->ParseForSyntax(
+ registration_->Syntax(), state.GetDocument().GetSecureContextMode());
+ if (!value)
+ return nullptr;
+ }
+
+ DCHECK(value);
+ return MaybeConvertValue(*value, &state, conversion_checkers);
+ }
+
if (!declaration.Value()) {
bool is_inherited_property = Registration().Inherits();
DCHECK(declaration.IsInitial(is_inherited_property) ||
@@ -232,20 +327,11 @@ InterpolationValue CSSInterpolationType::MaybeConvertCustomPropertyDeclaration(
scoped_refptr<CSSVariableData> resolved_tokens;
if (declaration.Value()->NeedsVariableResolution()) {
- if (RuntimeEnabledFeatures::CSSCascadeEnabled()) {
- const CSSValue* resolved =
- css_environment.Resolve(GetProperty(), &declaration);
- if (const auto* decl = DynamicTo<CSSCustomPropertyDeclaration>(resolved))
- resolved_tokens = decl->Value();
- } else {
- CSSVariableResolver& variable_resolver =
- css_environment.VariableResolver();
- bool cycle_detected = false;
- resolved_tokens =
- variable_resolver.ResolveCustomPropertyAnimationKeyframe(
- declaration, cycle_detected);
- DCHECK(!cycle_detected);
- }
+ CSSVariableResolver& variable_resolver = css_environment.VariableResolver();
+ bool cycle_detected = false;
+ resolved_tokens = variable_resolver.ResolveCustomPropertyAnimationKeyframe(
+ declaration, cycle_detected);
+ DCHECK(!cycle_detected);
conversion_checkers.push_back(
std::make_unique<ResolvedRegisteredCustomPropertyChecker>(
declaration, resolved_tokens));
diff --git a/chromium/third_party/blink/renderer/core/animation/css_interpolation_types_map.cc b/chromium/third_party/blink/renderer/core/animation/css_interpolation_types_map.cc
index 422d13f7ed3..ca730627644 100644
--- a/chromium/third_party/blink/renderer/core/animation/css_interpolation_types_map.cc
+++ b/chromium/third_party/blink/renderer/core/animation/css_interpolation_types_map.cc
@@ -59,7 +59,7 @@ CSSInterpolationTypesMap::CSSInterpolationTypesMap(
const Document& document)
: registry_(registry) {
allow_all_animations_ = document.IsFeatureEnabled(
- blink::mojom::blink::FeaturePolicyFeature::kLayoutAnimations);
+ blink::mojom::blink::DocumentPolicyFeature::kLayoutAnimations);
}
static const PropertyRegistration* GetRegistration(
@@ -368,10 +368,7 @@ const InterpolationTypes& CSSInterpolationTypesMap::Get(
}
size_t CSSInterpolationTypesMap::Version() const {
- // Property registrations are never removed so the number of registered
- // custom properties is equivalent to how many changes there have been to the
- // property registry.
- return registry_ ? registry_->RegistrationCount() : 0;
+ return registry_ ? registry_->Version() : 0;
}
static std::unique_ptr<CSSInterpolationType>
diff --git a/chromium/third_party/blink/renderer/core/animation/css_var_cycle_interpolation_type.cc b/chromium/third_party/blink/renderer/core/animation/css_var_cycle_interpolation_type.cc
index 6ae83a184c7..6aba5edbb2e 100644
--- a/chromium/third_party/blink/renderer/core/animation/css_var_cycle_interpolation_type.cc
+++ b/chromium/third_party/blink/renderer/core/animation/css_var_cycle_interpolation_type.cc
@@ -63,7 +63,9 @@ InterpolationValue CSSVarCycleInterpolationType::MaybeConvertSingle(
const auto& declaration = *To<CSSCustomPropertyDeclaration>(
To<CSSPropertySpecificKeyframe>(keyframe).Value());
DCHECK_EQ(GetProperty().CustomPropertyName(), declaration.GetName());
- if (!declaration.Value() || !declaration.Value()->NeedsVariableResolution()) {
+ if ((!declaration.Value() ||
+ !declaration.Value()->NeedsVariableResolution()) &&
+ !declaration.IsRevert()) {
return nullptr;
}
diff --git a/chromium/third_party/blink/renderer/core/animation/document_animations.cc b/chromium/third_party/blink/renderer/core/animation/document_animations.cc
index 104c0de08b5..b1df2494553 100644
--- a/chromium/third_party/blink/renderer/core/animation/document_animations.cc
+++ b/chromium/third_party/blink/renderer/core/animation/document_animations.cc
@@ -121,6 +121,11 @@ void DocumentAnimations::UpdateAnimations(
timeline->ScheduleNextService();
}
+void DocumentAnimations::MarkAnimationsCompositorPending() {
+ for (auto& timeline : timelines_)
+ timeline->MarkAnimationsCompositorPending();
+}
+
HeapVector<Member<Animation>> DocumentAnimations::getAnimations(
const TreeScope& tree_scope) {
// This method implements the Document::getAnimations method defined in the
diff --git a/chromium/third_party/blink/renderer/core/animation/document_animations.h b/chromium/third_party/blink/renderer/core/animation/document_animations.h
index 2627b129bfb..3bd3cd39073 100644
--- a/chromium/third_party/blink/renderer/core/animation/document_animations.h
+++ b/chromium/third_party/blink/renderer/core/animation/document_animations.h
@@ -47,6 +47,10 @@ class CORE_EXPORT DocumentAnimations final
DocumentAnimations(Document*);
~DocumentAnimations() = default;
+ uint64_t TransitionGeneration() const {
+ return current_transition_generation_;
+ }
+ void IncrementTrasitionGeneration() { current_transition_generation_++; }
void AddTimeline(AnimationTimeline&);
void UpdateAnimationTimingForAnimationFrame();
bool NeedsAnimationTimingUpdate();
@@ -61,7 +65,10 @@ class CORE_EXPORT DocumentAnimations final
DocumentLifecycle::LifecycleState required_lifecycle_state,
const PaintArtifactCompositor* paint_artifact_compositor);
+ void MarkAnimationsCompositorPending();
+
HeapVector<Member<Animation>> getAnimations(const TreeScope&);
+ uint64_t current_transition_generation_;
void Trace(Visitor*);
private:
diff --git a/chromium/third_party/blink/renderer/core/animation/document_animations_test.cc b/chromium/third_party/blink/renderer/core/animation/document_animations_test.cc
index f0ebf9c3dda..35c165f581c 100644
--- a/chromium/third_party/blink/renderer/core/animation/document_animations_test.cc
+++ b/chromium/third_party/blink/renderer/core/animation/document_animations_test.cc
@@ -23,6 +23,7 @@ class MockAnimationTimeline : public AnimationTimeline {
MockAnimationTimeline(Document* document) : AnimationTimeline(document) {}
MOCK_CONST_METHOD0(IsActive, bool());
+ MOCK_METHOD0(ZeroTimeInSeconds, double());
MOCK_METHOD0(InitialStartTimeForAnimations,
base::Optional<base::TimeDelta>());
MOCK_METHOD0(NeedsAnimationTimingUpdate, bool());
diff --git a/chromium/third_party/blink/renderer/core/animation/document_timeline.cc b/chromium/third_party/blink/renderer/core/animation/document_timeline.cc
index 63dd9e7451f..d3857a4a86c 100644
--- a/chromium/third_party/blink/renderer/core/animation/document_timeline.cc
+++ b/chromium/third_party/blink/renderer/core/animation/document_timeline.cc
@@ -34,6 +34,7 @@
#include "third_party/blink/renderer/core/animation/animation.h"
#include "third_party/blink/renderer/core/animation/animation_clock.h"
#include "third_party/blink/renderer/core/animation/animation_effect.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/loader/document_loader.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
@@ -66,7 +67,7 @@ const double DocumentTimeline::kMinimumDelay = 0.04;
DocumentTimeline* DocumentTimeline::Create(
ExecutionContext* execution_context,
const DocumentTimelineOptions* options) {
- Document* document = Document::From(execution_context);
+ Document* document = To<LocalDOMWindow>(execution_context)->document();
return MakeGarbageCollected<DocumentTimeline>(
document, base::TimeDelta::FromMillisecondsD(options->originTime()),
nullptr);
@@ -98,7 +99,7 @@ bool DocumentTimeline::IsActive() const {
// timeline current time.
base::Optional<base::TimeDelta>
DocumentTimeline::InitialStartTimeForAnimations() {
- base::Optional<double> current_time_ms = CurrentTime();
+ base::Optional<double> current_time_ms = currentTime();
if (current_time_ms.has_value()) {
return base::TimeDelta::FromMillisecondsD(current_time_ms.value());
}
@@ -204,13 +205,7 @@ void DocumentTimeline::SetPlaybackRate(double playback_rate) {
// Corresponding compositor animation may need to be restarted to pick up
// the new playback rate. Marking the effect changed forces this.
- SetAllCompositorPending(true);
-}
-
-void DocumentTimeline::SetAllCompositorPending(bool source_changed) {
- for (const auto& animation : animations_) {
- animation->SetCompositorPending(source_changed);
- }
+ MarkAnimationsCompositorPending(true);
}
double DocumentTimeline::PlaybackRate() const {
diff --git a/chromium/third_party/blink/renderer/core/animation/document_timeline.h b/chromium/third_party/blink/renderer/core/animation/document_timeline.h
index 2aa7eef4917..d98509a1e2e 100644
--- a/chromium/third_party/blink/renderer/core/animation/document_timeline.h
+++ b/chromium/third_party/blink/renderer/core/animation/document_timeline.h
@@ -79,10 +79,16 @@ class CORE_EXPORT DocumentTimeline : public AnimationTimeline {
return !animations_needing_update_.IsEmpty();
}
+ // The zero time of DocumentTimeline is computed by adding a separate
+ // |origin_time_| from DocumentTimelineOptions.
+ // https://drafts.csswg.org/web-animations/#origin-time
base::TimeTicks ZeroTime();
+ double ZeroTimeInSeconds() override {
+ return ZeroTime().since_origin().InSecondsF();
+ }
+
void PauseAnimationsForTesting(double);
- void SetAllCompositorPending(bool source_changed = false);
void InvalidateKeyframeEffects(const TreeScope&);
void SetPlaybackRate(double);
diff --git a/chromium/third_party/blink/renderer/core/animation/document_timeline_test.cc b/chromium/third_party/blink/renderer/core/animation/document_timeline_test.cc
index d759e6e921f..abeeb524817 100644
--- a/chromium/third_party/blink/renderer/core/animation/document_timeline_test.cc
+++ b/chromium/third_party/blink/renderer/core/animation/document_timeline_test.cc
@@ -161,11 +161,11 @@ TEST_F(AnimationDocumentTimelineTest, EmptyKeyframeAnimation) {
timeline->Play(keyframe_effect);
UpdateClockAndService(0);
- EXPECT_FLOAT_EQ(0, timeline->currentTime());
+ EXPECT_FLOAT_EQ(0, timeline->currentTime().value());
EXPECT_FALSE(keyframe_effect->IsInEffect());
UpdateClockAndService(1000);
- EXPECT_FLOAT_EQ(1000, timeline->currentTime());
+ EXPECT_FLOAT_EQ(1000, timeline->currentTime().value());
}
TEST_F(AnimationDocumentTimelineTest, EmptyForwardsKeyframeAnimation) {
@@ -182,7 +182,7 @@ TEST_F(AnimationDocumentTimelineTest, EmptyForwardsKeyframeAnimation) {
EXPECT_TRUE(keyframe_effect->IsInEffect());
UpdateClockAndService(1000);
- EXPECT_FLOAT_EQ(1000, timeline->currentTime());
+ EXPECT_FLOAT_EQ(1000, timeline->currentTime().value());
}
TEST_F(AnimationDocumentTimelineTest, ZeroTime) {
@@ -195,7 +195,7 @@ TEST_F(AnimationDocumentTimelineTest, ZeroTime) {
TEST_F(AnimationDocumentTimelineTest, CurrentTimeSeconds) {
GetAnimationClock().UpdateTime(TimeTicksFromMillisecondsD(2000));
- EXPECT_EQ(2, timeline->CurrentTimeSeconds().value());
+ EXPECT_EQ(2, timeline->CurrentTimeSeconds());
EXPECT_EQ(2000, timeline->currentTime());
auto* document_without_frame = MakeGarbageCollected<Document>();
@@ -203,10 +203,7 @@ TEST_F(AnimationDocumentTimelineTest, CurrentTimeSeconds) {
document_without_frame, base::TimeDelta(), platform_timing);
EXPECT_FALSE(inactive_timeline->CurrentTimeSeconds());
- EXPECT_NAN(inactive_timeline->currentTime());
- bool is_null = false;
- inactive_timeline->currentTime(is_null);
- EXPECT_TRUE(is_null);
+ EXPECT_FALSE(inactive_timeline->currentTime());
}
TEST_F(AnimationDocumentTimelineTest, PlaybackRateNormal) {
@@ -363,8 +360,8 @@ TEST_F(AnimationDocumentTimelineTest, PauseForTesting) {
Animation* animation2 = timeline->Play(anim2);
timeline->PauseAnimationsForTesting(seek_time);
- EXPECT_FLOAT_EQ(seek_time * 1000, animation1->currentTime());
- EXPECT_FLOAT_EQ(seek_time * 1000, animation2->currentTime());
+ EXPECT_FLOAT_EQ(seek_time * 1000, animation1->currentTime().value());
+ EXPECT_FLOAT_EQ(seek_time * 1000, animation2->currentTime().value());
}
TEST_F(AnimationDocumentTimelineTest, DelayBeforeAnimationStart) {
@@ -398,7 +395,7 @@ TEST_F(AnimationDocumentTimelineTest, UseAnimationAfterTimelineDeref) {
Animation* animation = timeline->Play(nullptr);
timeline.Clear();
// Test passes if this does not crash.
- animation->setStartTime(0, false);
+ animation->setStartTime(0);
}
TEST_F(AnimationDocumentTimelineTest, PlayAfterDocumentDeref) {
diff --git a/chromium/third_party/blink/renderer/core/animation/effect_stack.cc b/chromium/third_party/blink/renderer/core/animation/effect_stack.cc
index 38a142175c6..9a2a31fc1e7 100644
--- a/chromium/third_party/blink/renderer/core/animation/effect_stack.cc
+++ b/chromium/third_party/blink/renderer/core/animation/effect_stack.cc
@@ -124,6 +124,30 @@ bool EffectStack::AffectsProperties(PropertyHandleFilter filter) const {
return false;
}
+bool EffectStack::AffectsProperties(const CSSBitset& bitset,
+ KeyframeEffect::Priority priority) const {
+ for (const auto& sampled_effect : sampled_effects_) {
+ if (sampled_effect->GetPriority() != priority)
+ continue;
+ for (const auto& interpolation : sampled_effect->Interpolations()) {
+ const PropertyHandle& property = interpolation->GetProperty();
+ if (property.IsCSSCustomProperty() || !property.IsCSSProperty())
+ continue;
+ if (bitset.Has(property.GetCSSProperty().PropertyID()))
+ return true;
+ }
+ }
+ return false;
+}
+
+bool EffectStack::HasRevert() const {
+ for (const auto& sampled_effect : sampled_effects_) {
+ if (sampled_effect->Effect() && sampled_effect->Effect()->HasRevert())
+ return true;
+ }
+ return false;
+}
+
ActiveInterpolationsMap EffectStack::ActiveInterpolations(
EffectStack* effect_stack,
const HeapVector<Member<const InertEffect>>* new_animations,
diff --git a/chromium/third_party/blink/renderer/core/animation/effect_stack.h b/chromium/third_party/blink/renderer/core/animation/effect_stack.h
index 416ab8ad404..cf2b411b481 100644
--- a/chromium/third_party/blink/renderer/core/animation/effect_stack.h
+++ b/chromium/third_party/blink/renderer/core/animation/effect_stack.h
@@ -38,6 +38,7 @@
#include "third_party/blink/renderer/core/animation/property_handle.h"
#include "third_party/blink/renderer/core/animation/sampled_effect.h"
#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/core/css/properties/css_bitset.h"
#include "third_party/blink/renderer/platform/geometry/float_box.h"
#include "third_party/blink/renderer/platform/wtf/hash_set.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
@@ -64,6 +65,9 @@ class CORE_EXPORT EffectStack {
using PropertyHandleFilter = bool (*)(const PropertyHandle&);
bool AffectsProperties(PropertyHandleFilter) const;
+ bool AffectsProperties(const CSSBitset&,
+ KeyframeEffect::Priority priority) const;
+ bool HasRevert() const;
// Produces a map of properties to active effects.
// |effect_stack| contains the sequence of sample effects for an element.
diff --git a/chromium/third_party/blink/renderer/core/animation/effect_stack_test.cc b/chromium/third_party/blink/renderer/core/animation/effect_stack_test.cc
index 4f4a13bc386..9915dabfec0 100644
--- a/chromium/third_party/blink/renderer/core/animation/effect_stack_test.cc
+++ b/chromium/third_party/blink/renderer/core/animation/effect_stack_test.cc
@@ -15,6 +15,7 @@
#include "third_party/blink/renderer/core/animation/keyframe_effect_model.h"
#include "third_party/blink/renderer/core/animation/pending_animations.h"
#include "third_party/blink/renderer/core/animation/string_keyframe.h"
+#include "third_party/blink/renderer/core/html/html_element.h"
#include "third_party/blink/renderer/core/testing/page_test_base.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
@@ -31,7 +32,7 @@ class AnimationEffectStackTest : public PageTestBase {
Animation* Play(KeyframeEffect* effect, double start_time) {
Animation* animation = timeline->Play(effect);
- animation->setStartTime(start_time * 1000, false);
+ animation->setStartTime(start_time * 1000);
animation->Update(kTimingUpdateOnDemand);
return animation;
}
@@ -223,4 +224,60 @@ TEST_F(AnimationEffectStackTest, ForwardsFillDiscarding) {
EXPECT_EQ(1u, SampledEffectCount());
}
+TEST_F(AnimationEffectStackTest, AffectsPropertiesCSSBitsetDefaultPriority) {
+ Play(MakeKeyframeEffect(MakeEffectModel(CSSPropertyID::kColor, "red")), 10);
+ Play(MakeKeyframeEffect(MakeEffectModel(CSSPropertyID::kTop, "1px")), 10);
+ Play(MakeKeyframeEffect(MakeEffectModel(CSSPropertyID::kLeft, "1px")), 10);
+
+ ASSERT_TRUE(element->GetElementAnimations());
+ const EffectStack& effect_stack =
+ element->GetElementAnimations()->GetEffectStack();
+
+ EXPECT_FALSE(effect_stack.AffectsProperties(
+ CSSBitset({CSSPropertyID::kBackgroundColor}),
+ KeyframeEffect::kDefaultPriority));
+ EXPECT_FALSE(effect_stack.AffectsProperties(
+ CSSBitset({CSSPropertyID::kBackgroundColor, CSSPropertyID::kFontSize}),
+ KeyframeEffect::kDefaultPriority));
+ EXPECT_FALSE(effect_stack.AffectsProperties(
+ CSSBitset({CSSPropertyID::kColor}), KeyframeEffect::kTransitionPriority));
+
+ EXPECT_TRUE(effect_stack.AffectsProperties(CSSBitset({CSSPropertyID::kColor}),
+ KeyframeEffect::kDefaultPriority));
+ EXPECT_TRUE(effect_stack.AffectsProperties(CSSBitset({CSSPropertyID::kTop}),
+ KeyframeEffect::kDefaultPriority));
+ EXPECT_TRUE(effect_stack.AffectsProperties(CSSBitset({CSSPropertyID::kLeft}),
+ KeyframeEffect::kDefaultPriority));
+ EXPECT_TRUE(effect_stack.AffectsProperties(
+ CSSBitset({CSSPropertyID::kColor, CSSPropertyID::kRight}),
+ KeyframeEffect::kDefaultPriority));
+ EXPECT_TRUE(effect_stack.AffectsProperties(
+ CSSBitset({CSSPropertyID::kColor, CSSPropertyID::kTop}),
+ KeyframeEffect::kDefaultPriority));
+ EXPECT_FALSE(effect_stack.AffectsProperties(
+ CSSBitset({CSSPropertyID::kColor}), KeyframeEffect::kTransitionPriority));
+}
+
+TEST_F(AnimationEffectStackTest, AffectsPropertiesCSSBitsetTransitionPriority) {
+ Element* body = GetDocument().body();
+ body->SetInlineStyleProperty(CSSPropertyID::kTransition, "color 10s");
+ body->SetInlineStyleProperty(CSSPropertyID::kColor, "red");
+ UpdateAllLifecyclePhasesForTest();
+
+ body->SetInlineStyleProperty(CSSPropertyID::kColor, "blue");
+ UpdateAllLifecyclePhasesForTest();
+
+ ASSERT_TRUE(body->GetElementAnimations());
+ const EffectStack& effect_stack =
+ body->GetElementAnimations()->GetEffectStack();
+
+ EXPECT_FALSE(effect_stack.AffectsProperties(
+ CSSBitset({CSSPropertyID::kColor}), KeyframeEffect::kDefaultPriority));
+ EXPECT_TRUE(effect_stack.AffectsProperties(
+ CSSBitset({CSSPropertyID::kColor}), KeyframeEffect::kTransitionPriority));
+ EXPECT_FALSE(effect_stack.AffectsProperties(
+ CSSBitset({CSSPropertyID::kBackgroundColor}),
+ KeyframeEffect::kTransitionPriority));
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/animation/element_animations.cc b/chromium/third_party/blink/renderer/core/animation/element_animations.cc
index 57d14159850..b7968da8d3a 100644
--- a/chromium/third_party/blink/renderer/core/animation/element_animations.cc
+++ b/chromium/third_party/blink/renderer/core/animation/element_animations.cc
@@ -113,34 +113,30 @@ void ElementAnimations::Trace(Visitor* visitor) {
visitor->Trace(worklet_animations_);
}
-bool ElementAnimations::IsBaseComputedStyleUsable() const {
- if (has_important_overrides_)
- return false;
- if (has_font_affecting_animation_ && base_computed_style_ &&
- base_computed_style_->HasFontRelativeUnits()) {
- return false;
- }
- return true;
-}
-
const ComputedStyle* ElementAnimations::BaseComputedStyle() const {
- if (IsAnimationStyleChange() && IsBaseComputedStyleUsable())
+ if (IsAnimationStyleChange())
return base_computed_style_.get();
return nullptr;
}
+const CSSBitset* ElementAnimations::BaseImportantSet() const {
+ if (IsAnimationStyleChange())
+ return base_important_set_.get();
+ return nullptr;
+}
+
void ElementAnimations::UpdateBaseComputedStyle(
- const ComputedStyle* computed_style) {
+ const ComputedStyle* computed_style,
+ std::unique_ptr<CSSBitset> base_important_set) {
DCHECK(computed_style);
- if (!IsAnimationStyleChange() || !IsBaseComputedStyleUsable()) {
- base_computed_style_ = nullptr;
- return;
- }
+ DCHECK(IsAnimationStyleChange());
base_computed_style_ = ComputedStyle::Clone(*computed_style);
+ base_important_set_ = std::move(base_important_set);
}
void ElementAnimations::ClearBaseComputedStyle() {
base_computed_style_ = nullptr;
+ base_important_set_ = nullptr;
}
bool ElementAnimations::AnimationsPreserveAxisAlignment() const {
diff --git a/chromium/third_party/blink/renderer/core/animation/element_animations.h b/chromium/third_party/blink/renderer/core/animation/element_animations.h
index 9dded60358b..6d488127624 100644
--- a/chromium/third_party/blink/renderer/core/animation/element_animations.h
+++ b/chromium/third_party/blink/renderer/core/animation/element_animations.h
@@ -36,6 +36,7 @@
#include "third_party/blink/renderer/core/animation/css/css_animations.h"
#include "third_party/blink/renderer/core/animation/effect_stack.h"
#include "third_party/blink/renderer/core/animation/worklet_animation_base.h"
+#include "third_party/blink/renderer/core/css/properties/css_bitset.h"
#include "third_party/blink/renderer/platform/wtf/hash_counted_set.h"
#include "third_party/blink/renderer/platform/wtf/hash_map.h"
@@ -79,11 +80,12 @@ class CORE_EXPORT ElementAnimations final
void SetAnimationStyleChange(bool animation_style_change) {
animation_style_change_ = animation_style_change;
}
- void SetHasImportantOverrides() { has_important_overrides_ = true; }
- void SetHasFontAffectingAnimation() { has_font_affecting_animation_ = true; }
+ bool IsAnimationStyleChange() const { return animation_style_change_; }
const ComputedStyle* BaseComputedStyle() const;
- void UpdateBaseComputedStyle(const ComputedStyle*);
+ const CSSBitset* BaseImportantSet() const;
+ void UpdateBaseComputedStyle(const ComputedStyle*,
+ std::unique_ptr<CSSBitset> base_important_set);
void ClearBaseComputedStyle();
bool AnimationsPreserveAxisAlignment() const;
@@ -91,9 +93,6 @@ class CORE_EXPORT ElementAnimations final
void Trace(Visitor*);
private:
- bool IsAnimationStyleChange() const { return animation_style_change_; }
- bool IsBaseComputedStyleUsable() const;
-
EffectStack effect_stack_;
CSSAnimations css_animations_;
AnimationCountedSet animations_;
@@ -106,19 +105,22 @@ class CORE_EXPORT ElementAnimations final
// change from the running animations) and use that during style recalc,
// applying only the animation changes on top of it.
bool animation_style_change_;
- // This is true when there's an !important declaration that overrides an
- // animation effect. In this case, we can not use the base computed style
- // optimization, since we have no way of knowing the cascade origins used
- // to construct the various parts of the base style.
- bool has_important_overrides_ = false;
- // If a font-affecting property is undergoing an animation, we can't use
- // the base computed style optimization, because font-relative units
- // (such as 'em') present in the base should respond to the animation.
- bool has_font_affecting_animation_ = false;
scoped_refptr<ComputedStyle> base_computed_style_;
+ // Keeps track of the !important declarations used to build the base
+ // computed style. These declarations must not be overwritten by animation
+ // effects, hence we have to disable the base computed style optimization when
+ // !important declarations conflict with active animations.
+ //
+ // If there were no !important declarations in the base style, this field
+ // will be nullptr.
+ //
+ // TODO(andruud): We should be able to simply skip applying the animation
+ // for properties in this set instead of disabling the optimization.
+ // However, we currently need the cascade to handle the case where
+ // an !important declaration appears in a :visited selector.
+ // See https://crbug.com/1062217.
+ std::unique_ptr<CSSBitset> base_important_set_;
- // CSSAnimations checks if a style change is due to animation.
- friend class CSSAnimations;
DISALLOW_COPY_AND_ASSIGN(ElementAnimations);
FRIEND_TEST_ALL_PREFIXES(StyleEngineTest, PseudoElementBaseComputedStyle);
diff --git a/chromium/third_party/blink/renderer/core/animation/keyframe.cc b/chromium/third_party/blink/renderer/core/animation/keyframe.cc
index 22fba719cf0..26a398e8af5 100644
--- a/chromium/third_party/blink/renderer/core/animation/keyframe.cc
+++ b/chromium/third_party/blink/renderer/core/animation/keyframe.cc
@@ -30,8 +30,8 @@ Interpolation* Keyframe::PropertySpecificKeyframe::CreateInterpolation(
const_cast<PropertySpecificKeyframe*>(&end));
}
-void Keyframe::AddKeyframePropertiesToV8Object(
- V8ObjectBuilder& object_builder) const {
+void Keyframe::AddKeyframePropertiesToV8Object(V8ObjectBuilder& object_builder,
+ Element* element) const {
if (offset_) {
object_builder.Add("offset", offset_.value());
} else {
diff --git a/chromium/third_party/blink/renderer/core/animation/keyframe.h b/chromium/third_party/blink/renderer/core/animation/keyframe.h
index 9a084a56fe0..cb74faff5ae 100644
--- a/chromium/third_party/blink/renderer/core/animation/keyframe.h
+++ b/chromium/third_party/blink/renderer/core/animation/keyframe.h
@@ -78,7 +78,6 @@ class CORE_EXPORT Keyframe : public GarbageCollected<Keyframe> {
return composite_.value();
}
- // TODO(smcgruer): The keyframe timing function should be immutable.
void SetEasing(scoped_refptr<TimingFunction> easing) {
if (easing)
easing_ = std::move(easing);
@@ -86,6 +85,7 @@ class CORE_EXPORT Keyframe : public GarbageCollected<Keyframe> {
easing_ = LinearTimingFunction::Shared();
}
TimingFunction& Easing() const { return *easing_; }
+ void CopyEasing(const Keyframe& other) { SetEasing(other.easing_); }
// Returns a set of the properties represented in this keyframe.
virtual PropertyHandleSet Properties() const = 0;
@@ -108,7 +108,8 @@ class CORE_EXPORT Keyframe : public GarbageCollected<Keyframe> {
//
// Subclasses should override this to add the (property, value) pairs they
// store, and call into the base version to add the basic Keyframe properties.
- virtual void AddKeyframePropertiesToV8Object(V8ObjectBuilder&) const;
+ virtual void AddKeyframePropertiesToV8Object(V8ObjectBuilder&,
+ Element*) const;
virtual bool IsStringKeyframe() const { return false; }
virtual bool IsTransitionKeyframe() const { return false; }
@@ -131,6 +132,7 @@ class CORE_EXPORT Keyframe : public GarbageCollected<Keyframe> {
return composite_ == EffectModel::kCompositeReplace ? 0 : 1;
}
virtual bool IsNeutral() const = 0;
+ virtual bool IsRevert() const = 0;
virtual PropertySpecificKeyframe* CloneWithOffset(double offset) const = 0;
// FIXME: Remove this once CompositorAnimations no longer depends on
diff --git a/chromium/third_party/blink/renderer/core/animation/keyframe_effect.cc b/chromium/third_party/blink/renderer/core/animation/keyframe_effect.cc
index cb7772fe0db..e7155c1c063 100644
--- a/chromium/third_party/blink/renderer/core/animation/keyframe_effect.cc
+++ b/chromium/third_party/blink/renderer/core/animation/keyframe_effect.cc
@@ -32,11 +32,15 @@
#include "third_party/blink/renderer/bindings/core/v8/unrestricted_double_or_keyframe_effect_options.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_object_builder.h"
+#include "third_party/blink/renderer/core/animation/animation_input_helpers.h"
+#include "third_party/blink/renderer/core/animation/animation_utils.h"
#include "third_party/blink/renderer/core/animation/css/compositor_keyframe_transform.h"
#include "third_party/blink/renderer/core/animation/effect_input.h"
#include "third_party/blink/renderer/core/animation/element_animations.h"
#include "third_party/blink/renderer/core/animation/sampled_effect.h"
#include "third_party/blink/renderer/core/animation/timing_input.h"
+#include "third_party/blink/renderer/core/css/properties/css_property_ref.h"
+#include "third_party/blink/renderer/core/css/resolver/style_resolver.h"
#include "third_party/blink/renderer/core/dom/element.h"
#include "third_party/blink/renderer/core/dom/node_computed_style.h"
#include "third_party/blink/renderer/core/dom/pseudo_element.h"
@@ -242,14 +246,17 @@ HeapVector<ScriptValue> KeyframeEffect::getKeyframes(
// the given keyframe.
//
// https://w3c.github.io/web-animations/#dom-keyframeeffectreadonly-getkeyframes
- const KeyframeVector& keyframes = model_->GetFrames();
+ KeyframeVector keyframes = ignore_css_keyframes_
+ ? model_->GetFrames()
+ : model_->GetComputedKeyframes(EffectTarget());
+
Vector<double> computed_offsets =
KeyframeEffectModelBase::GetComputedOffsets(keyframes);
computed_keyframes.ReserveInitialCapacity(keyframes.size());
ScriptState::Scope scope(script_state);
for (wtf_size_t i = 0; i < keyframes.size(); i++) {
V8ObjectBuilder object_builder(script_state);
- keyframes[i]->AddKeyframePropertiesToV8Object(object_builder);
+ keyframes[i]->AddKeyframePropertiesToV8Object(object_builder, target());
object_builder.Add("computedOffset", computed_offsets[i]);
computed_keyframes.push_back(object_builder.GetScriptValue());
}
@@ -290,6 +297,10 @@ bool KeyframeEffect::Affects(const PropertyHandle& property) const {
return model_->Affects(property);
}
+bool KeyframeEffect::HasRevert() const {
+ return model_->HasRevert();
+}
+
void KeyframeEffect::NotifySampledEffectRemovedFromEffectStack() {
sampled_effect_ = nullptr;
}
diff --git a/chromium/third_party/blink/renderer/core/animation/keyframe_effect.h b/chromium/third_party/blink/renderer/core/animation/keyframe_effect.h
index b7a09035e07..1fb72a9e3ab 100644
--- a/chromium/third_party/blink/renderer/core/animation/keyframe_effect.h
+++ b/chromium/third_party/blink/renderer/core/animation/keyframe_effect.h
@@ -97,6 +97,7 @@ class CORE_EXPORT KeyframeEffect final : public AnimationEffect {
void SetKeyframes(StringKeyframeVector keyframes);
bool Affects(const PropertyHandle&) const;
+ bool HasRevert() const;
const KeyframeEffectModelBase* Model() const { return model_.Get(); }
KeyframeEffectModelBase* Model() { return model_.Get(); }
void SetModel(KeyframeEffectModelBase* model) {
diff --git a/chromium/third_party/blink/renderer/core/animation/keyframe_effect_model.cc b/chromium/third_party/blink/renderer/core/animation/keyframe_effect_model.cc
index ef9b74ee02d..fc823735f13 100644
--- a/chromium/third_party/blink/renderer/core/animation/keyframe_effect_model.cc
+++ b/chromium/third_party/blink/renderer/core/animation/keyframe_effect_model.cc
@@ -180,36 +180,23 @@ bool KeyframeEffectModelBase::SnapshotCompositableProperties(
// ensure that it can be animated.
const PropertyRegistry* property_registry =
element.GetDocument().GetPropertyRegistry();
- if (!property_registry) {
- // TODO(kevers): Change to DCHECK once CSSVariables2Enabled flag is removed.
+ if (!property_registry)
return updated;
- }
- if (auto* inherited_variables = computed_style.InheritedVariables()) {
- for (const auto& name : inherited_variables->GetCustomPropertyNames()) {
- if (property_registry->WasReferenced(name)) {
- // This variable has been referenced as a property value at least once
- // during style resolution in the document. Animating this property on
- // the compositor could introduce misalignment in frame synchronization.
- continue;
- }
- updated |= SnapshotCompositorKeyFrames(
- PropertyHandle(name), element, computed_style, parent_style,
- should_snapshot_property_callback, should_snapshot_keyframe_callback);
- }
- }
- if (auto* non_inherited_variables = computed_style.NonInheritedVariables()) {
- for (const auto& name : non_inherited_variables->GetCustomPropertyNames()) {
- // TODO(kevers): Check if referenced in computed style. References
- // elsewhere in the document should not prevent compositing.
- if (property_registry->WasReferenced(name)) {
- // Avoid potential side-effect of animating on compositor.
- continue;
- }
- updated |= SnapshotCompositorKeyFrames(
- PropertyHandle(name), element, computed_style, parent_style,
- should_snapshot_property_callback, should_snapshot_keyframe_callback);
+ for (const AtomicString& name : computed_style.GetVariableNames()) {
+ if (property_registry->WasReferenced(name)) {
+ // This variable has been referenced as a property value at least once
+ // during style resolution in the document. Animating this property on
+ // the compositor could introduce misalignment in frame synchronization.
+ //
+ // TODO(kevers): For non-inherited properites, check if referenced in
+ // computed style. References elsewhere in the document should not prevent
+ // compositing.
+ continue;
}
+ updated |= SnapshotCompositorKeyFrames(
+ PropertyHandle(name), element, computed_style, parent_style,
+ should_snapshot_property_callback, should_snapshot_keyframe_callback);
}
return updated;
}
@@ -335,8 +322,11 @@ void KeyframeEffectModelBase::EnsureKeyframeGroups() const {
group = group_iter->value.Get();
}
- group->AppendKeyframe(keyframe->CreatePropertySpecificKeyframe(
- property, composite_, computed_offset));
+ Keyframe::PropertySpecificKeyframe* property_specific_keyframe =
+ keyframe->CreatePropertySpecificKeyframe(property, composite_,
+ computed_offset);
+ has_revert_ |= property_specific_keyframe->IsRevert();
+ group->AppendKeyframe(property_specific_keyframe);
}
}
diff --git a/chromium/third_party/blink/renderer/core/animation/keyframe_effect_model.h b/chromium/third_party/blink/renderer/core/animation/keyframe_effect_model.h
index 7ad2414d2cf..498d7eb75e0 100644
--- a/chromium/third_party/blink/renderer/core/animation/keyframe_effect_model.h
+++ b/chromium/third_party/blink/renderer/core/animation/keyframe_effect_model.h
@@ -90,6 +90,10 @@ class CORE_EXPORT KeyframeEffectModelBase : public EffectModel {
template <class K>
void SetFrames(HeapVector<K>& keyframes);
+ // Keyframes for CSS animations require additional processing to lazy
+ // evaluate computed values.
+ virtual KeyframeVector GetComputedKeyframes(Element*) { return keyframes_; }
+
CompositeOperation Composite() const { return composite_; }
void SetComposite(CompositeOperation composite);
@@ -148,6 +152,11 @@ class CORE_EXPORT KeyframeEffectModelBase : public EffectModel {
return keyframe_groups_->Contains(property);
}
+ bool HasRevert() const {
+ EnsureKeyframeGroups();
+ return has_revert_;
+ }
+
bool IsTransformRelatedEffect() const override;
virtual KeyframeEffectModelBase* Clone() = 0;
@@ -164,7 +173,8 @@ class CORE_EXPORT KeyframeEffectModelBase : public EffectModel {
composite_(composite),
default_keyframe_easing_(std::move(default_keyframe_easing)),
has_synthetic_keyframes_(false),
- needs_compositor_keyframes_snapshot_(true) {}
+ needs_compositor_keyframes_snapshot_(true),
+ has_revert_(false) {}
// Lazily computes the groups of property-specific keyframes.
void EnsureKeyframeGroups() const;
@@ -207,13 +217,14 @@ class CORE_EXPORT KeyframeEffectModelBase : public EffectModel {
mutable bool has_synthetic_keyframes_;
mutable bool needs_compositor_keyframes_snapshot_;
+ mutable bool has_revert_;
friend class KeyframeEffectModelTest;
};
// Time independent representation of an Animation's keyframes.
template <class K>
-class KeyframeEffectModel final : public KeyframeEffectModelBase {
+class KeyframeEffectModel : public KeyframeEffectModelBase {
public:
using KeyframeVector = HeapVector<Member<K>>;
KeyframeEffectModel(
diff --git a/chromium/third_party/blink/renderer/core/animation/keyframe_effect_test.cc b/chromium/third_party/blink/renderer/core/animation/keyframe_effect_test.cc
index 6c17ea87b02..f1e6274e041 100644
--- a/chromium/third_party/blink/renderer/core/animation/keyframe_effect_test.cc
+++ b/chromium/third_party/blink/renderer/core/animation/keyframe_effect_test.cc
@@ -370,25 +370,25 @@ TEST_F(KeyframeEffectTest, TimeToEffectChange) {
keyframe_effect->TimeToReverseEffectChange());
// End of the before phase.
- animation->setCurrentTime(100000, false);
+ animation->setCurrentTime(100000);
EXPECT_EQ(AnimationTimeDelta::FromSecondsD(100),
keyframe_effect->TimeToForwardsEffectChange());
EXPECT_EQ(AnimationTimeDelta(), keyframe_effect->TimeToReverseEffectChange());
// Nearing the end of the active phase.
- animation->setCurrentTime(199000, false);
+ animation->setCurrentTime(199000);
EXPECT_EQ(AnimationTimeDelta::FromSecondsD(1),
keyframe_effect->TimeToForwardsEffectChange());
EXPECT_EQ(AnimationTimeDelta(), keyframe_effect->TimeToReverseEffectChange());
// End of the active phase.
- animation->setCurrentTime(200000, false);
+ animation->setCurrentTime(200000);
EXPECT_EQ(AnimationTimeDelta::FromSecondsD(100),
keyframe_effect->TimeToForwardsEffectChange());
EXPECT_EQ(AnimationTimeDelta(), keyframe_effect->TimeToReverseEffectChange());
// End of the animation.
- animation->setCurrentTime(300000, false);
+ animation->setCurrentTime(300000);
EXPECT_EQ(AnimationTimeDelta::Max(),
keyframe_effect->TimeToForwardsEffectChange());
EXPECT_EQ(AnimationTimeDelta::FromSecondsD(100),
diff --git a/chromium/third_party/blink/renderer/core/animation/pending_animations.cc b/chromium/third_party/blink/renderer/core/animation/pending_animations.cc
index bdc657ed8b6..0eb82a4c2b2 100644
--- a/chromium/third_party/blink/renderer/core/animation/pending_animations.cc
+++ b/chromium/third_party/blink/renderer/core/animation/pending_animations.cc
@@ -49,14 +49,9 @@ void PendingAnimations::Add(Animation* animation) {
document->View()->ScheduleAnimation();
bool visible = document->GetPage() && document->GetPage()->IsPageVisible();
- if (!visible && !timer_.IsActive() &&
- // TODO(crbug.com/916117): Firing a timer for animations linked to
- // inactive timelines creates an unnecessary cycle of unsuccessfully
- // starting such animations. Instead, let the animation frame call
- // PendingAnimations::Update when the timeline becomes active.
- // Revisit this condition and add a test as part of inactive timeline
- // implementation.
- animation->timeline() && animation->timeline()->IsActive()) {
+ if (!visible && !timer_.IsActive()) {
+ // Verify the timer is not activated in cycles.
+ CHECK(!inside_timer_fired_);
timer_.StartOneShot(base::TimeDelta(), FROM_HERE);
}
}
@@ -84,17 +79,14 @@ bool PendingAnimations::Update(
started_synchronized_on_compositor = true;
}
- // TODO(crbug.com/916117): Revisit this condition as part of handling
- // inactive timelines work.
- if (!animation->timeline() || !animation->timeline()->IsActive()) {
- DCHECK(!animation->timeline() ||
- !animation->timeline()->IsScrollTimeline());
+ if (!animation->timeline() || !animation->timeline()->IsActive())
continue;
- }
if (animation->Playing() && !animation->startTime()) {
waiting_for_start_time.push_back(animation.Get());
} else if (animation->PendingInternal()) {
+ DCHECK(animation->timeline()->IsActive() &&
+ animation->timeline()->CurrentTimeSeconds());
// A pending animation that is not waiting on a start time does not need
// to be synchronized with animations that are starting up. Nonetheless,
// it needs to notify the animation to resolve the ready promise and
@@ -117,20 +109,19 @@ bool PendingAnimations::Update(
} else {
for (auto& animation : waiting_for_start_time) {
DCHECK(!animation->startTime());
- // TODO(crbug.com/916117): Handle start time of scroll-linked animations.
+ DCHECK(animation->timeline()->IsActive() &&
+ animation->timeline()->CurrentTimeSeconds());
animation->NotifyReady(
animation->timeline()->CurrentTimeSeconds().value_or(0));
}
}
// FIXME: The postCommit should happen *after* the commit, not before.
- for (auto& animation : animations) {
- // TODO(crbug.com/916117): Handle NaN current time of scroll timeline.
- animation->PostCommit(
- animation->timeline()->CurrentTimeSeconds().value_or(0));
- }
+ for (auto& animation : animations)
+ animation->PostCommit();
DCHECK(pending_.IsEmpty());
+ DCHECK(start_on_compositor || deferred.IsEmpty());
for (auto& animation : deferred)
animation->SetCompositorPending();
DCHECK_EQ(pending_.size(), deferred.size());
@@ -174,12 +165,8 @@ void PendingAnimations::NotifyCompositorAnimationStarted(
waiting_for_compositor_animation_start_.push_back(animation);
continue;
}
- DCHECK(IsA<DocumentTimeline>(animation->timeline()));
animation->NotifyReady(monotonic_animation_start_time -
- To<DocumentTimeline>(animation->timeline())
- ->ZeroTime()
- .since_origin()
- .InSecondsF());
+ animation->timeline()->ZeroTimeInSeconds());
}
}
@@ -208,8 +195,8 @@ void PendingAnimations::FlushWaitingNonCompositedAnimations() {
if (animation->HasActiveAnimationsOnCompositor()) {
waiting_for_compositor_animation_start_.push_back(animation);
} else {
- // TODO(crbug.com/916117): Handle start time of scroll-linked
- // animations.
+ DCHECK(animation->timeline()->IsActive() &&
+ animation->timeline()->CurrentTimeSeconds());
animation->NotifyReady(
animation->timeline()->CurrentTimeSeconds().value_or(0));
}
@@ -221,4 +208,9 @@ void PendingAnimations::Trace(Visitor* visitor) {
visitor->Trace(waiting_for_compositor_animation_start_);
}
+void PendingAnimations::TimerFired(TimerBase*) {
+ base::AutoReset<bool> mark_inside(&inside_timer_fired_, true);
+ Update(nullptr, false);
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/animation/pending_animations.h b/chromium/third_party/blink/renderer/core/animation/pending_animations.h
index 010ccffb26f..619c7720435 100644
--- a/chromium/third_party/blink/renderer/core/animation/pending_animations.h
+++ b/chromium/third_party/blink/renderer/core/animation/pending_animations.h
@@ -65,7 +65,8 @@ class CORE_EXPORT PendingAnimations final
: timer_(document.GetTaskRunner(TaskType::kInternalDefault),
this,
&PendingAnimations::TimerFired),
- compositor_group_(1) {}
+ compositor_group_(1),
+ inside_timer_fired_(false) {}
void Add(Animation*);
@@ -96,7 +97,7 @@ class CORE_EXPORT PendingAnimations final
void Trace(Visitor*);
private:
- void TimerFired(TimerBase*) { Update(nullptr, false); }
+ void TimerFired(TimerBase*);
int NextCompositorGroup();
void FlushWaitingNonCompositedAnimations();
@@ -104,6 +105,7 @@ class CORE_EXPORT PendingAnimations final
HeapVector<Member<Animation>> waiting_for_compositor_animation_start_;
TaskRunnerTimer<PendingAnimations> timer_;
int compositor_group_;
+ bool inside_timer_fired_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/animation/scroll_timeline.cc b/chromium/third_party/blink/renderer/core/animation/scroll_timeline.cc
index 39d1891e984..526519ef69c 100644
--- a/chromium/third_party/blink/renderer/core/animation/scroll_timeline.cc
+++ b/chromium/third_party/blink/renderer/core/animation/scroll_timeline.cc
@@ -4,7 +4,9 @@
#include "third_party/blink/renderer/core/animation/scroll_timeline.h"
+#include "base/optional.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_scroll_timeline_options.h"
+#include "third_party/blink/renderer/core/animation/scroll_timeline_offset.h"
#include "third_party/blink/renderer/core/animation/scroll_timeline_util.h"
#include "third_party/blink/renderer/core/css/css_to_length_conversion_data.h"
#include "third_party/blink/renderer/core/css/parser/css_parser_context.h"
@@ -16,6 +18,7 @@
#include "third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.h"
#include "third_party/blink/renderer/core/paint/paint_layer.h"
#include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
+#include "third_party/blink/renderer/core/scroll/scroll_types.h"
#include "third_party/blink/renderer/platform/geometry/length_functions.h"
namespace blink {
@@ -57,19 +60,20 @@ bool StringToScrollDirection(String scroll_direction,
return false;
}
-bool StringToScrollOffset(String scroll_offset,
- const CSSParserContext& context,
- CSSPrimitiveValue** result) {
- CSSTokenizer tokenizer(scroll_offset);
- const auto tokens = tokenizer.TokenizeToEOF();
- CSSParserTokenRange range(tokens);
- CSSValue* value = css_parsing_utils::ConsumeScrollOffset(range, context);
- if (!value)
- return false;
-
- // We support 'auto', but for simplicity just store it as nullptr.
- *result = DynamicTo<CSSPrimitiveValue>(value);
- return true;
+ScrollOrientation ToPhysicalScrollOrientation(
+ ScrollTimeline::ScrollDirection direction,
+ const LayoutBox& source_box) {
+ bool is_horizontal = source_box.IsHorizontalWritingMode();
+ switch (direction) {
+ case ScrollTimeline::Block:
+ return is_horizontal ? kVerticalScroll : kHorizontalScroll;
+ case ScrollTimeline::Inline:
+ return is_horizontal ? kHorizontalScroll : kVerticalScroll;
+ case ScrollTimeline::Horizontal:
+ return kHorizontalScroll;
+ case ScrollTimeline::Vertical:
+ return kVerticalScroll;
+ }
}
// Note that the resolution process may trigger document lifecycle to clean
@@ -103,17 +107,17 @@ ScrollTimeline* ScrollTimeline::Create(Document& document,
return nullptr;
}
- CSSPrimitiveValue* start_scroll_offset = nullptr;
- if (!StringToScrollOffset(options->startScrollOffset(), *context,
- &start_scroll_offset)) {
- exception_state.ThrowTypeError("Invalid startScrollOffset");
+ ScrollTimelineOffset* start_scroll_offset =
+ ScrollTimelineOffset::Create(options->startScrollOffset(), *context);
+ if (!start_scroll_offset) {
+ exception_state.ThrowTypeError("Invalid start offset.");
return nullptr;
}
- CSSPrimitiveValue* end_scroll_offset = nullptr;
- if (!StringToScrollOffset(options->endScrollOffset(), *context,
- &end_scroll_offset)) {
- exception_state.ThrowTypeError("Invalid endScrollOffset");
+ ScrollTimelineOffset* end_scroll_offset =
+ ScrollTimelineOffset::Create(options->endScrollOffset(), *context);
+ if (!end_scroll_offset) {
+ exception_state.ThrowTypeError("Invalid end offset");
return nullptr;
}
@@ -133,8 +137,8 @@ ScrollTimeline* ScrollTimeline::Create(Document& document,
ScrollTimeline::ScrollTimeline(Document* document,
Element* scroll_source,
ScrollDirection orientation,
- CSSPrimitiveValue* start_scroll_offset,
- CSSPrimitiveValue* end_scroll_offset,
+ ScrollTimelineOffset* start_scroll_offset,
+ ScrollTimelineOffset* end_scroll_offset,
double time_range)
: AnimationTimeline(document),
scroll_source_(scroll_source),
@@ -156,7 +160,7 @@ ScrollTimeline::ScrollTimeline(Document* document,
}
bool ScrollTimeline::IsActive() const {
- return phase_and_time_snapshotted_.phase != TimelinePhase::kInactive;
+ return timeline_state_snapshotted_.phase != TimelinePhase::kInactive;
}
void ScrollTimeline::Invalidate() {
@@ -171,17 +175,37 @@ bool ScrollTimeline::ComputeIsActive() const {
layout_box->GetScrollableArea();
}
+void ScrollTimeline::ResolveScrollOffsets(double* start_offset,
+ double* end_offset) const {
+ DCHECK(ComputeIsActive());
+ LayoutBox* layout_box = resolved_scroll_source_->GetLayoutBox();
+ DCHECK(layout_box);
+
+ double current_offset;
+ double max_offset;
+ GetCurrentAndMaxOffset(layout_box, current_offset, max_offset);
+
+ DCHECK(start_scroll_offset_ && end_scroll_offset_);
+ auto orientation = ToPhysicalScrollOrientation(orientation_, *layout_box);
+ *start_offset = start_scroll_offset_->ResolveOffset(
+ resolved_scroll_source_, orientation, max_offset, 0);
+
+ *end_offset = end_scroll_offset_->ResolveOffset(
+ resolved_scroll_source_, orientation, max_offset, max_offset);
+}
+
AnimationTimeline::PhaseAndTime ScrollTimeline::CurrentPhaseAndTime() {
- return phase_and_time_snapshotted_;
+ return {timeline_state_snapshotted_.phase,
+ timeline_state_snapshotted_.current_time};
}
-AnimationTimeline::PhaseAndTime ScrollTimeline::ComputeCurrentPhaseAndTime()
- const {
+ScrollTimeline::TimelineState ScrollTimeline::ComputeTimelineState() const {
// 1. If scroll timeline is inactive, return an unresolved time value.
// https://github.com/WICG/scroll-animations/issues/31
// https://wicg.github.io/scroll-animations/#current-time-algorithm
if (!ComputeIsActive()) {
- return {TimelinePhase::kInactive, /*current_time*/ base::nullopt};
+ return {TimelinePhase::kInactive, /*current_time*/ base::nullopt,
+ base::nullopt, base::nullopt};
}
LayoutBox* layout_box = resolved_scroll_source_->GetLayoutBox();
// 2. Otherwise, let current scroll offset be the current scroll offset of
@@ -191,10 +215,9 @@ AnimationTimeline::PhaseAndTime ScrollTimeline::ComputeCurrentPhaseAndTime()
double max_offset;
GetCurrentAndMaxOffset(layout_box, current_offset, max_offset);
- double resolved_start_scroll_offset = 0;
- double resolved_end_scroll_offset = max_offset;
- ResolveScrollStartAndEnd(layout_box, max_offset, resolved_start_scroll_offset,
- resolved_end_scroll_offset);
+ double start_offset;
+ double end_offset;
+ ResolveScrollOffsets(&start_offset, &end_offset);
// TODO(crbug.com/1060384): Once the spec has been updated to state what the
// expected result is when startScrollOffset >= endScrollOffset, we might need
@@ -202,25 +225,31 @@ AnimationTimeline::PhaseAndTime ScrollTimeline::ComputeCurrentPhaseAndTime()
// https://github.com/WICG/scroll-animations/issues/20
// 3. If current scroll offset is less than startScrollOffset:
- if (current_offset < resolved_start_scroll_offset) {
- return {TimelinePhase::kBefore, base::TimeDelta()};
+ if (current_offset < start_offset) {
+ return {TimelinePhase::kBefore, base::TimeDelta(), start_offset,
+ end_offset};
}
// 4. If current scroll offset is greater than or equal to endScrollOffset:
- if (current_offset >= resolved_end_scroll_offset) {
- return {TimelinePhase::kAfter,
- base::TimeDelta::FromMillisecondsD(time_range_)};
+ if (current_offset >= end_offset) {
+ // If end_offset is greater than or equal to the maximum scroll offset of
+ // scrollSource in orientation then return active phase, otherwise return
+ // after phase.
+ TimelinePhase phase = end_offset >= max_offset ? TimelinePhase::kActive
+ : TimelinePhase::kAfter;
+ return {phase, base::TimeDelta::FromMillisecondsD(time_range_),
+ start_offset, end_offset};
}
// 5. Return the result of evaluating the following expression:
// ((current scroll offset - startScrollOffset) /
// (endScrollOffset - startScrollOffset)) * effective time range
base::Optional<base::TimeDelta> calculated_current_time =
- base::TimeDelta::FromMillisecondsD(
- ((current_offset - resolved_start_scroll_offset) /
- (resolved_end_scroll_offset - resolved_start_scroll_offset)) *
- time_range_);
- return {TimelinePhase::kActive, calculated_current_time};
+ base::TimeDelta::FromMillisecondsD((current_offset - start_offset) /
+ (end_offset - start_offset) *
+ time_range_);
+ return {TimelinePhase::kActive, calculated_current_time, start_offset,
+ end_offset};
}
// Scroll-linked animations are initialized with the start time of zero.
@@ -233,18 +262,29 @@ void ScrollTimeline::ServiceAnimations(TimingUpdateReason reason) {
// Snapshot timeline state once at top of animation frame.
if (reason == kTimingUpdateForAnimationFrame)
SnapshotState();
+ // When scroll timeline goes from inactive to active the animations may need
+ // to be started and possibly composited.
+ bool was_active =
+ last_current_phase_and_time_ &&
+ last_current_phase_and_time_.value().phase == TimelinePhase::kActive;
+ if (!was_active && IsActive())
+ MarkAnimationsCompositorPending();
+
AnimationTimeline::ServiceAnimations(reason);
}
void ScrollTimeline::ScheduleNextService() {
if (AnimationsNeedingUpdateCount() == 0)
return;
- if (ComputeCurrentPhaseAndTime() != last_current_phase_and_time_)
+
+ auto state = ComputeTimelineState();
+ PhaseAndTime current_phase_and_time{state.phase, state.current_time};
+ if (current_phase_and_time != last_current_phase_and_time_)
ScheduleServiceOnNextFrame();
}
void ScrollTimeline::SnapshotState() {
- phase_and_time_snapshotted_ = ComputeCurrentPhaseAndTime();
+ timeline_state_snapshotted_ = ComputeTimelineState();
}
Element* ScrollTimeline::scrollSource() {
@@ -267,12 +307,19 @@ String ScrollTimeline::orientation() {
}
}
-String ScrollTimeline::startScrollOffset() {
- return start_scroll_offset_ ? start_scroll_offset_->CssText() : "auto";
+void ScrollTimeline::startScrollOffset(
+ StringOrScrollTimelineElementBasedOffset& out) const {
+ if (!start_scroll_offset_)
+ return;
+ out = start_scroll_offset_->ToStringOrScrollTimelineElementBasedOffset();
}
-String ScrollTimeline::endScrollOffset() {
- return end_scroll_offset_ ? end_scroll_offset_->CssText() : "auto";
+void ScrollTimeline::endScrollOffset(
+ StringOrScrollTimelineElementBasedOffset& out) const {
+ if (!end_scroll_offset_)
+ return;
+
+ out = end_scroll_offset_->ToStringOrScrollTimelineElementBasedOffset();
}
void ScrollTimeline::timeRange(DoubleOrScrollTimelineAutoKeyword& result) {
@@ -302,22 +349,13 @@ void ScrollTimeline::GetCurrentAndMaxOffset(const LayoutBox* layout_box,
ScrollOffset scroll_dimensions = scrollable_area->MaximumScrollOffset() -
scrollable_area->MinimumScrollOffset();
- bool is_horizontal = layout_box->IsHorizontalWritingMode();
- if (orientation_ == Block) {
- current_offset =
- is_horizontal ? scroll_offset.Height() : scroll_offset.Width();
- max_offset =
- is_horizontal ? scroll_dimensions.Height() : scroll_dimensions.Width();
- } else if (orientation_ == Inline) {
- current_offset =
- is_horizontal ? scroll_offset.Width() : scroll_offset.Height();
- max_offset =
- is_horizontal ? scroll_dimensions.Width() : scroll_dimensions.Height();
- } else if (orientation_ == Horizontal) {
+ auto physical_orientation =
+ ToPhysicalScrollOrientation(orientation_, *layout_box);
+
+ if (physical_orientation == kHorizontalScroll) {
current_offset = scroll_offset.Width();
max_offset = scroll_dimensions.Width();
} else {
- DCHECK(orientation_ == Vertical);
current_offset = scroll_offset.Height();
max_offset = scroll_dimensions.Height();
}
@@ -328,30 +366,6 @@ void ScrollTimeline::GetCurrentAndMaxOffset(const LayoutBox* layout_box,
current_offset = std::abs(current_offset);
}
-void ScrollTimeline::ResolveScrollStartAndEnd(
- const LayoutBox* layout_box,
- double max_offset,
- double& resolved_start_scroll_offset,
- double& resolved_end_scroll_offset) const {
- DCHECK(layout_box);
- const ComputedStyle& computed_style = layout_box->StyleRef();
- Document& document = layout_box->GetDocument();
- const ComputedStyle* root_style =
- document.documentElement()
- ? document.documentElement()->GetComputedStyle()
- : document.GetComputedStyle();
- CSSToLengthConversionData conversion_data = CSSToLengthConversionData(
- &computed_style, root_style, document.GetLayoutView(),
- computed_style.EffectiveZoom());
- if (start_scroll_offset_) {
- resolved_start_scroll_offset = FloatValueForLength(
- start_scroll_offset_->ConvertToLength(conversion_data), max_offset);
- }
- if (end_scroll_offset_) {
- resolved_end_scroll_offset = FloatValueForLength(
- end_scroll_offset_->ConvertToLength(conversion_data), max_offset);
- }
-}
void ScrollTimeline::WorkletAnimationAttached() {
if (!resolved_scroll_source_)
diff --git a/chromium/third_party/blink/renderer/core/animation/scroll_timeline.h b/chromium/third_party/blink/renderer/core/animation/scroll_timeline.h
index d04aedd1146..6ddfaeb40ef 100644
--- a/chromium/third_party/blink/renderer/core/animation/scroll_timeline.h
+++ b/chromium/third_party/blink/renderer/core/animation/scroll_timeline.h
@@ -6,6 +6,7 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_SCROLL_TIMELINE_H_
#include "third_party/blink/renderer/core/animation/animation_timeline.h"
+#include "third_party/blink/renderer/core/animation/scroll_timeline_offset.h"
#include "third_party/blink/renderer/core/animation/timing.h"
#include "third_party/blink/renderer/core/css/css_primitive_value.h"
#include "third_party/blink/renderer/core/dom/element.h"
@@ -43,8 +44,8 @@ class CORE_EXPORT ScrollTimeline : public AnimationTimeline {
ScrollTimeline(Document*,
Element*,
ScrollDirection,
- CSSPrimitiveValue*,
- CSSPrimitiveValue*,
+ ScrollTimelineOffset*,
+ ScrollTimelineOffset*,
double);
// AnimationTimeline implementation.
@@ -54,6 +55,7 @@ class CORE_EXPORT ScrollTimeline : public AnimationTimeline {
// https://github.com/WICG/scroll-animations/issues/31
bool IsActive() const override;
base::Optional<base::TimeDelta> InitialStartTimeForAnimations() override;
+ double ZeroTimeInSeconds() override { return 0; }
void ServiceAnimations(TimingUpdateReason) override;
void ScheduleNextService() override;
@@ -61,25 +63,35 @@ class CORE_EXPORT ScrollTimeline : public AnimationTimeline {
// IDL API implementation.
Element* scrollSource();
String orientation();
- String startScrollOffset();
- String endScrollOffset();
+ void startScrollOffset(
+ StringOrScrollTimelineElementBasedOffset& result) const;
+ void endScrollOffset(StringOrScrollTimelineElementBasedOffset& result) const;
+
void timeRange(DoubleOrScrollTimelineAutoKeyword&);
// Returns the Node that should actually have the ScrollableArea (if one
// exists). This can differ from |scrollSource| when |scroll_source_| is the
- // Document's scrollingElement, and it may be null if the document was removed
- // before the ScrollTimeline was created.
+ // Document's scrollingElement, and it may be null if the document was
+ // removed before the ScrollTimeline was created.
Node* ResolvedScrollSource() const { return resolved_scroll_source_; }
+ // Return the latest resolved start scroll offset. This will be nullopt when
+ // timeline is inactive.
+ base::Optional<double> GetResolvedStartScrollOffset() const {
+ return timeline_state_snapshotted_.start_offset;
+ }
+
+ // Return the latest resolved end scroll offset. This will be nullopt when
+ // timeline is inactive.
+ base::Optional<double> GetResolvedEndScrollOffset() const {
+ return timeline_state_snapshotted_.end_offset;
+ }
+
ScrollDirection GetOrientation() const { return orientation_; }
void GetCurrentAndMaxOffset(const LayoutBox*,
double& current_offset,
double& max_offset) const;
- void ResolveScrollStartAndEnd(const LayoutBox*,
- double max_offset,
- double& resolved_start_scroll_offset,
- double& resolved_end_scroll_offset) const;
// Invalidates scroll timeline as a result of scroller properties change.
// This may lead the timeline to request a new animation frame.
virtual void Invalidate();
@@ -113,17 +125,45 @@ class CORE_EXPORT ScrollTimeline : public AnimationTimeline {
bool ComputeIsActive() const;
PhaseAndTime ComputeCurrentPhaseAndTime() const;
+ // Resolve scroll offsets The resolution process turns length-based values
+ // into concrete length values resolving percentages and zoom factor. For
+ // element-based values it computes the corresponding length value that maps
+ // to the particular element intersection. See
+ // |ScrollTimelineOffset::ResolveOffset()| for more details.
+ void ResolveScrollOffsets(double* start_offset, double* end_offset) const;
+
+ struct TimelineState {
+ TimelinePhase phase;
+ base::Optional<base::TimeDelta> current_time;
+ // The resolved version of start and end offset. These values are nullopts
+ // when timeline is inactive (e.g., when source does not overflow).
+ base::Optional<double> start_offset;
+ base::Optional<double> end_offset;
+
+ bool operator==(const TimelineState& other) const {
+ return phase == other.phase && current_time == other.current_time &&
+ start_offset == other.start_offset &&
+ end_offset == other.end_offset;
+ }
+ };
+
+ TimelineState ComputeTimelineState() const;
+
// Use |scroll_source_| only to implement the web-exposed API but use
// resolved_scroll_source_ to actually access the scroll related properties.
Member<Element> scroll_source_;
Member<Node> resolved_scroll_source_;
ScrollDirection orientation_;
- Member<CSSPrimitiveValue> start_scroll_offset_;
- Member<CSSPrimitiveValue> end_scroll_offset_;
+
+ // These define the total range of the scroller that the ScrollTimeline is
+ // active within.
+ Member<ScrollTimelineOffset> start_scroll_offset_;
+ Member<ScrollTimelineOffset> end_scroll_offset_;
+
double time_range_;
// Snapshotted value produced by the last SnapshotState call.
- PhaseAndTime phase_and_time_snapshotted_;
+ TimelineState timeline_state_snapshotted_;
};
template <>
diff --git a/chromium/third_party/blink/renderer/core/animation/scroll_timeline.idl b/chromium/third_party/blink/renderer/core/animation/scroll_timeline.idl
index 11650883814..881584a349e 100644
--- a/chromium/third_party/blink/renderer/core/animation/scroll_timeline.idl
+++ b/chromium/third_party/blink/renderer/core/animation/scroll_timeline.idl
@@ -3,7 +3,6 @@
// found in the LICENSE file.
// https://wicg.github.io/scroll-animations/#scrolltimeline-interface
-
[
RuntimeEnabled=ScrollTimeline,
Exposed=Window
@@ -11,7 +10,7 @@
[CallWith=Document, RaisesException, MeasureAs=ScrollTimelineConstructor] constructor(optional ScrollTimelineOptions options = {});
readonly attribute Element? scrollSource;
readonly attribute ScrollDirection orientation;
- readonly attribute DOMString startScrollOffset;
- readonly attribute DOMString endScrollOffset;
+ readonly attribute (DOMString or ScrollTimelineElementBasedOffset) startScrollOffset;
+ readonly attribute (DOMString or ScrollTimelineElementBasedOffset) endScrollOffset;
readonly attribute (double or ScrollTimelineAutoKeyword) timeRange;
};
diff --git a/chromium/third_party/blink/renderer/core/animation/scroll_timeline_element_based_offset.idl b/chromium/third_party/blink/renderer/core/animation/scroll_timeline_element_based_offset.idl
new file mode 100644
index 00000000000..189c0fc1e8f
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/animation/scroll_timeline_element_based_offset.idl
@@ -0,0 +1,16 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Experimental IDL of element-based offsets based on this proposal:
+// https://github.com/w3c/csswg-drafts/issues/4337
+
+enum Edge {"start", "end"};
+
+dictionary ScrollTimelineElementBasedOffset {
+ Element target;
+ double threshold = 0.0;
+ Edge edge = "start";
+ // TODO(majidvp): Add other values from proposal. http://crbug.com/1023375
+ // DOMString rootMargin;
+}; \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/core/animation/scroll_timeline_offset.cc b/chromium/third_party/blink/renderer/core/animation/scroll_timeline_offset.cc
new file mode 100644
index 00000000000..f839ede3f3e
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/animation/scroll_timeline_offset.cc
@@ -0,0 +1,208 @@
+// 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/core/animation/scroll_timeline_offset.h"
+
+#include "third_party/blink/renderer/bindings/core/v8/string_or_scroll_timeline_element_based_offset.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_scroll_timeline_element_based_offset.h"
+#include "third_party/blink/renderer/core/css/css_to_length_conversion_data.h"
+#include "third_party/blink/renderer/core/css/parser/css_parser_context.h"
+#include "third_party/blink/renderer/core/css/parser/css_tokenizer.h"
+#include "third_party/blink/renderer/core/dom/node_computed_style.h"
+#include "third_party/blink/renderer/core/layout/layout_box.h"
+#include "third_party/blink/renderer/core/layout/layout_view.h"
+#include "third_party/blink/renderer/platform/geometry/layout_unit.h"
+#include "third_party/blink/renderer/platform/geometry/length_functions.h"
+
+namespace blink {
+
+namespace {
+
+bool StringToScrollOffset(String scroll_offset,
+ const CSSParserContext& context,
+ CSSPrimitiveValue** result) {
+ CSSTokenizer tokenizer(scroll_offset);
+ const auto tokens = tokenizer.TokenizeToEOF();
+ CSSParserTokenRange range(tokens);
+ CSSValue* value = css_parsing_utils::ConsumeScrollOffset(range, context);
+ if (!value)
+ return false;
+
+ // We support 'auto', but for simplicity just store it as nullptr.
+ *result = DynamicTo<CSSPrimitiveValue>(value);
+ return true;
+}
+
+bool ValidateElementBasedOffset(ScrollTimelineElementBasedOffset* offset) {
+ if (!offset->hasTarget())
+ return false;
+
+ if (offset->hasThreshold()) {
+ if (offset->threshold() < 0 || offset->threshold() > 1)
+ return false;
+ }
+
+ return true;
+}
+
+} // namespace
+
+// static
+ScrollTimelineOffset* ScrollTimelineOffset::Create(
+ const StringOrScrollTimelineElementBasedOffset& input_offset,
+ const CSSParserContext& context) {
+ if (input_offset.IsString()) {
+ CSSPrimitiveValue* offset = nullptr;
+ if (!StringToScrollOffset(input_offset.GetAsString(), context, &offset)) {
+ return nullptr;
+ }
+
+ return MakeGarbageCollected<ScrollTimelineOffset>(offset);
+ } else if (input_offset.IsScrollTimelineElementBasedOffset()) {
+ auto* offset = input_offset.GetAsScrollTimelineElementBasedOffset();
+ if (!ValidateElementBasedOffset(offset))
+ return nullptr;
+
+ return MakeGarbageCollected<ScrollTimelineOffset>(offset);
+ } else {
+ // The default case is "auto" which we initialized with null
+ return MakeGarbageCollected<ScrollTimelineOffset>();
+ }
+}
+
+double ScrollTimelineOffset::ResolveOffset(Node* scroll_source,
+ ScrollOrientation orientation,
+ double max_offset,
+ double default_offset) {
+ const LayoutBox* root_box = scroll_source->GetLayoutBox();
+ DCHECK(root_box);
+ Document& document = root_box->GetDocument();
+
+ if (length_based_offset_) {
+ // Resolve scroll based offset.
+ const ComputedStyle& computed_style = root_box->StyleRef();
+ const ComputedStyle* root_style =
+ document.documentElement()
+ ? document.documentElement()->GetComputedStyle()
+ : document.GetComputedStyle();
+
+ CSSToLengthConversionData conversion_data = CSSToLengthConversionData(
+ &computed_style, root_style, document.GetLayoutView(),
+ computed_style.EffectiveZoom());
+ double resolved = FloatValueForLength(
+ length_based_offset_->ConvertToLength(conversion_data), max_offset);
+
+ return resolved;
+ } else if (element_based_offset_) {
+ // We assume that the root is the target's ancestor in layout tree. Under
+ // this assumption |target.LocalToAncestorRect()| returns the targets's
+ // position relative to the root's border box, while ignoring scroll offset.
+ //
+ // TODO(majidvp): We need to validate this assumption and deal with cases
+ // where it is not true. See the spec discussion here:
+ // https://github.com/w3c/csswg-drafts/issues/4337#issuecomment-610989843
+
+ DCHECK(element_based_offset_->hasTarget());
+ Element* target = element_based_offset_->target();
+ const LayoutBox* target_box = target->GetLayoutBox();
+
+ // It is possible for target to not have a layout box e.g., if it is an
+ // unattached element. In which case we return the default offset for now.
+ //
+ // TODO(majidvp): Need to consider this case in the spec. Most likely we
+ // should remain unresolved. See the spec discussion here:
+ // https://github.com/w3c/csswg-drafts/issues/4337#issuecomment-610997231
+ if (!target_box) {
+ return default_offset;
+ }
+
+ PhysicalRect target_rect = target_box->PhysicalBorderBoxRect();
+ target_rect = target_box->LocalToAncestorRect(
+ target_rect, root_box,
+ kTraverseDocumentBoundaries | kIgnoreScrollOffset);
+
+ PhysicalRect root_rect(root_box->PhysicalBorderBoxRect());
+
+ LayoutUnit root_edge;
+ LayoutUnit target_edge;
+
+ // Here is the simple diagram that shows the computation.
+ //
+ // +-----+
+ // | | +------+
+ // | | | |
+ // edge:start +----+-----+-------------------+-----+-------+
+ // | |xxxxxx| |xxxxx| |
+ // | +------+ |xxxxx| |
+ // | +-----+ |
+ // | |
+ // threshold: | A) 0 B) 0.5 C) 1 |
+ // | |
+ // | +-----+ |
+ // | +------+ |xxxxx| |
+ // | |xxxxxx| |xxxxx| |
+ // edge: end +----+-----+-------------------+-----+-------+
+ // | | | |
+ // | | +------+
+ // +-----+
+ //
+ // We always take the target top edge and compute the distance to the
+ // root's selected edge. This give us (C) in start edge case and (A) in
+ // end edge case.
+ //
+ // To take threshold into account we simply add (1-threshold) or threshold
+ // in start and end edge cases respectively.
+ bool is_start = element_based_offset_->edge() == "start";
+ float threshold_adjustment = is_start
+ ? (1 - element_based_offset_->threshold())
+ : element_based_offset_->threshold();
+
+ if (orientation == kVerticalScroll) {
+ root_edge = is_start ? root_rect.Y() : root_rect.Bottom();
+ target_edge = target_rect.Y();
+ // Note that threshold is considered as a portion of target and not as a
+ // portion of root. IntersectionObserver has option to allow both.
+ target_edge += (threshold_adjustment * target_rect.Height());
+ } else { // kHorizontalScroll
+ root_edge = is_start ? root_rect.X() : root_rect.Right();
+ target_edge = target_rect.X();
+ target_edge += (threshold_adjustment * target_rect.Width());
+ }
+
+ LayoutUnit offset = target_edge - root_edge;
+ return std::min(std::max(offset.ToDouble(), 0.0), max_offset);
+ } else {
+ // Resolve the default case (i.e., 'auto' value)
+ return default_offset;
+ }
+}
+
+StringOrScrollTimelineElementBasedOffset
+ScrollTimelineOffset::ToStringOrScrollTimelineElementBasedOffset() const {
+ StringOrScrollTimelineElementBasedOffset result;
+ if (length_based_offset_) {
+ result.SetString(length_based_offset_->CssText());
+ } else if (element_based_offset_) {
+ result.SetScrollTimelineElementBasedOffset(element_based_offset_);
+ } else {
+ // This is the default value (i.e., 'auto' value)
+ result.SetString("auto");
+ }
+
+ return result;
+}
+
+ScrollTimelineOffset::ScrollTimelineOffset(CSSPrimitiveValue* offset)
+ : length_based_offset_(offset), element_based_offset_(nullptr) {}
+
+ScrollTimelineOffset::ScrollTimelineOffset(
+ ScrollTimelineElementBasedOffset* offset)
+ : length_based_offset_(nullptr), element_based_offset_(offset) {}
+
+void ScrollTimelineOffset::Trace(blink::Visitor* visitor) {
+ visitor->Trace(length_based_offset_);
+ visitor->Trace(element_based_offset_);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/animation/scroll_timeline_offset.h b/chromium/third_party/blink/renderer/core/animation/scroll_timeline_offset.h
new file mode 100644
index 00000000000..de2d55baff9
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/animation/scroll_timeline_offset.h
@@ -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.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_SCROLL_TIMELINE_OFFSET_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_SCROLL_TIMELINE_OFFSET_H_
+
+#include "third_party/blink/renderer/bindings/core/v8/v8_scroll_timeline_element_based_offset.h"
+#include "third_party/blink/renderer/core/css/properties/css_parsing_utils.h"
+#include "third_party/blink/renderer/core/scroll/scroll_types.h"
+
+namespace blink {
+
+class StringOrScrollTimelineElementBasedOffset;
+
+// Represent a scroll timeline start/end offset which can be an
+// scroll offset or an element based offset
+class CORE_EXPORT ScrollTimelineOffset final
+ : public GarbageCollected<ScrollTimelineOffset> {
+ public:
+ static ScrollTimelineOffset* Create(
+ const StringOrScrollTimelineElementBasedOffset& offset,
+ const CSSParserContext& context);
+
+ // Create a default offset representing 'auto'.
+ ScrollTimelineOffset() = default;
+ // Create a scroll based offset.
+ explicit ScrollTimelineOffset(CSSPrimitiveValue*);
+ // Create an element based offset.
+ explicit ScrollTimelineOffset(ScrollTimelineElementBasedOffset*);
+
+ void Trace(blink::Visitor*);
+
+ // Resolves this offset against the scroll source and in the given orientation
+ // returning eqiuvalent concrete scroll offset.
+ //
+ // - Length-based values are converted into concrete length values resolving
+ // percentages and zoom factor.
+ // - Element-based values are resolved to the equivalent scroll offset that
+ // satisfy the requirement.
+ // - Auto value simply returns the |detfault_offset|.
+ //
+ // max offset is expected to be the maximum scroll offset in the scroll
+ // orientation.
+ double ResolveOffset(Node* scroll_source,
+ ScrollOrientation,
+ double max_offset,
+ double default_offset);
+
+ StringOrScrollTimelineElementBasedOffset
+ ToStringOrScrollTimelineElementBasedOffset() const;
+
+ private:
+ // We either have an scroll or element based offset so at any time one of
+ // these is null. If both are null, it represents the default value of
+ // 'auto'.
+ Member<CSSPrimitiveValue> length_based_offset_;
+ Member<ScrollTimelineElementBasedOffset> element_based_offset_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_SCROLL_TIMELINE_OFFSET_H_
diff --git a/chromium/third_party/blink/renderer/core/animation/scroll_timeline_options.idl b/chromium/third_party/blink/renderer/core/animation/scroll_timeline_options.idl
index 74e907227c7..a42d4bebf46 100644
--- a/chromium/third_party/blink/renderer/core/animation/scroll_timeline_options.idl
+++ b/chromium/third_party/blink/renderer/core/animation/scroll_timeline_options.idl
@@ -16,7 +16,8 @@ enum ScrollTimelineAutoKeyword { "auto" };
dictionary ScrollTimelineOptions {
Element? scrollSource = null;
ScrollDirection orientation = "block";
- DOMString startScrollOffset = "auto";
- DOMString endScrollOffset = "auto";
+ (DOMString or ScrollTimelineElementBasedOffset) startScrollOffset = "auto";
+ (DOMString or ScrollTimelineElementBasedOffset) endScrollOffset = "auto";
+
(double or ScrollTimelineAutoKeyword) timeRange = "auto";
};
diff --git a/chromium/third_party/blink/renderer/core/animation/scroll_timeline_test.cc b/chromium/third_party/blink/renderer/core/animation/scroll_timeline_test.cc
index d7047bde6f5..5c65bfe990b 100644
--- a/chromium/third_party/blink/renderer/core/animation/scroll_timeline_test.cc
+++ b/chromium/third_party/blink/renderer/core/animation/scroll_timeline_test.cc
@@ -9,6 +9,7 @@
#include "third_party/blink/renderer/core/animation/keyframe_effect.h"
#include "third_party/blink/renderer/core/animation/keyframe_effect_model.h"
#include "third_party/blink/renderer/core/css/css_numeric_literal_value.h"
+#include "third_party/blink/renderer/core/dom/events/native_event_listener.h"
#include "third_party/blink/renderer/core/paint/paint_layer.h"
#include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
#include "third_party/blink/renderer/core/testing/core_unit_test_helper.h"
@@ -17,6 +18,16 @@
namespace blink {
+namespace {
+
+StringOrScrollTimelineElementBasedOffset OffsetFromString(const String& value) {
+ StringOrScrollTimelineElementBasedOffset result;
+ result.SetString(value);
+ return result;
+}
+
+} // namespace
+
class ScrollTimelineTest : public RenderingTest {
void SetUp() override {
EnableCompositing();
@@ -34,15 +45,19 @@ class ScrollTimelineTest : public RenderingTest {
class TestScrollTimeline : public ScrollTimeline {
public:
- TestScrollTimeline(
- Document* document,
- Element* scroll_source,
- CSSPrimitiveValue* start_scroll_offset =
- CSSNumericLiteralValue::Create(10.0,
- CSSPrimitiveValue::UnitType::kPixels),
- CSSPrimitiveValue* end_scroll_offset =
- CSSNumericLiteralValue::Create(90.0,
- CSSPrimitiveValue::UnitType::kPixels))
+ TestScrollTimeline(Document* document,
+ Element* scroll_source,
+ ScrollTimelineOffset* start_scroll_offset =
+ MakeGarbageCollected<ScrollTimelineOffset>(
+ CSSNumericLiteralValue::Create(
+ 10.0,
+ CSSPrimitiveValue::UnitType::kPixels)),
+
+ ScrollTimelineOffset* end_scroll_offset =
+ MakeGarbageCollected<ScrollTimelineOffset>(
+ CSSNumericLiteralValue::Create(
+ 90.0,
+ CSSPrimitiveValue::UnitType::kPixels)))
: ScrollTimeline(document,
scroll_source,
ScrollTimeline::Vertical,
@@ -81,9 +96,7 @@ TEST_F(ScrollTimelineTest, CurrentTimeIsNullIfScrollSourceIsNotScrollable) {
ScrollTimeline* scroll_timeline =
ScrollTimeline::Create(GetDocument(), options, ASSERT_NO_EXCEPTION);
- bool current_time_is_null = false;
- scroll_timeline->currentTime(current_time_is_null);
- EXPECT_TRUE(current_time_is_null);
+ EXPECT_FALSE(scroll_timeline->currentTime().has_value());
EXPECT_FALSE(scroll_timeline->IsActive());
}
@@ -110,8 +123,8 @@ TEST_F(ScrollTimelineTest,
DoubleOrScrollTimelineAutoKeyword::FromDouble(100);
options->setTimeRange(time_range);
options->setScrollSource(GetElementById("scroller"));
- options->setStartScrollOffset("10px");
- options->setEndScrollOffset("90px");
+ options->setStartScrollOffset(OffsetFromString("10px"));
+ options->setEndScrollOffset(OffsetFromString("90px"));
ScrollTimeline* scroll_timeline =
ScrollTimeline::Create(GetDocument(), options, ASSERT_NO_EXCEPTION);
@@ -121,45 +134,35 @@ TEST_F(ScrollTimelineTest,
// Simulate a new animation frame which allows the timeline to compute new
// current time.
SimulateFrame();
- double current_time = scroll_timeline->currentTime(current_time_is_null);
- EXPECT_FALSE(current_time_is_null);
- EXPECT_EQ(current_time, 0);
+ EXPECT_EQ(scroll_timeline->currentTime(), 0);
EXPECT_EQ("before", scroll_timeline->phase());
current_time_is_null = true;
scrollable_area->SetScrollOffset(ScrollOffset(0, 10),
mojom::blink::ScrollType::kProgrammatic);
SimulateFrame();
- current_time = scroll_timeline->currentTime(current_time_is_null);
- EXPECT_FALSE(current_time_is_null);
- EXPECT_EQ(current_time, 0);
+ EXPECT_EQ(scroll_timeline->currentTime(), 0);
EXPECT_EQ("active", scroll_timeline->phase());
current_time_is_null = true;
scrollable_area->SetScrollOffset(ScrollOffset(0, 50),
mojom::blink::ScrollType::kProgrammatic);
SimulateFrame();
- current_time = scroll_timeline->currentTime(current_time_is_null);
- EXPECT_FALSE(current_time_is_null);
- EXPECT_EQ(current_time, 50);
+ EXPECT_EQ(scroll_timeline->currentTime(), 50);
EXPECT_EQ("active", scroll_timeline->phase());
current_time_is_null = true;
scrollable_area->SetScrollOffset(ScrollOffset(0, 90),
mojom::blink::ScrollType::kProgrammatic);
SimulateFrame();
- current_time = scroll_timeline->currentTime(current_time_is_null);
- EXPECT_FALSE(current_time_is_null);
- EXPECT_EQ(current_time, time_range.GetAsDouble());
+ EXPECT_EQ(scroll_timeline->currentTime(), time_range.GetAsDouble());
EXPECT_EQ("after", scroll_timeline->phase());
current_time_is_null = true;
scrollable_area->SetScrollOffset(ScrollOffset(0, 100),
mojom::blink::ScrollType::kProgrammatic);
SimulateFrame();
- scroll_timeline->currentTime(current_time_is_null);
- EXPECT_FALSE(current_time_is_null);
- EXPECT_EQ(current_time, time_range.GetAsDouble());
+ EXPECT_EQ(scroll_timeline->currentTime(), time_range.GetAsDouble());
EXPECT_EQ("after", scroll_timeline->phase());
EXPECT_TRUE(scroll_timeline->IsActive());
}
@@ -187,8 +190,8 @@ TEST_F(ScrollTimelineTest,
DoubleOrScrollTimelineAutoKeyword::FromDouble(100);
options->setTimeRange(time_range);
options->setScrollSource(GetElementById("scroller"));
- options->setStartScrollOffset("80px");
- options->setEndScrollOffset("40px");
+ options->setStartScrollOffset(OffsetFromString("80px"));
+ options->setEndScrollOffset(OffsetFromString("40px"));
ScrollTimeline* scroll_timeline =
ScrollTimeline::Create(GetDocument(), options, ASSERT_NO_EXCEPTION);
@@ -198,27 +201,21 @@ TEST_F(ScrollTimelineTest,
// Simulate a new animation frame which allows the timeline to compute new
// current time.
SimulateFrame();
- double current_time = scroll_timeline->currentTime(current_time_is_null);
- EXPECT_FALSE(current_time_is_null);
- EXPECT_EQ(0, current_time);
+ EXPECT_EQ(0, scroll_timeline->currentTime());
EXPECT_EQ("before", scroll_timeline->phase());
current_time_is_null = true;
scrollable_area->SetScrollOffset(ScrollOffset(0, 60),
mojom::blink::ScrollType::kProgrammatic);
SimulateFrame();
- current_time = scroll_timeline->currentTime(current_time_is_null);
- EXPECT_FALSE(current_time_is_null);
- EXPECT_EQ(0, current_time);
+ EXPECT_EQ(0, scroll_timeline->currentTime());
EXPECT_EQ("before", scroll_timeline->phase());
current_time_is_null = true;
scrollable_area->SetScrollOffset(ScrollOffset(0, 100),
mojom::blink::ScrollType::kProgrammatic);
SimulateFrame();
- current_time = scroll_timeline->currentTime(current_time_is_null);
- EXPECT_FALSE(current_time_is_null);
- EXPECT_EQ(time_range.GetAsDouble(), current_time);
+ EXPECT_EQ(time_range.GetAsDouble(), scroll_timeline->currentTime());
EXPECT_EQ("after", scroll_timeline->phase());
EXPECT_TRUE(scroll_timeline->IsActive());
}
@@ -245,8 +242,8 @@ TEST_F(ScrollTimelineTest, PhasesAreCorrectWhenUsingOffsets) {
DoubleOrScrollTimelineAutoKeyword::FromDouble(100);
options->setTimeRange(time_range);
options->setScrollSource(GetElementById("scroller"));
- options->setStartScrollOffset("10px");
- options->setEndScrollOffset("90px");
+ options->setStartScrollOffset(OffsetFromString("10px"));
+ options->setEndScrollOffset(OffsetFromString("90px"));
ScrollTimeline* scroll_timeline =
ScrollTimeline::Create(GetDocument(), options, ASSERT_NO_EXCEPTION);
@@ -340,8 +337,8 @@ TEST_F(ScrollTimelineTest, AttachOrDetachAnimationWithNullScrollSource) {
// scrollSource. The alternative approach would require us to remove the
// documentElement from the document.
Element* scroll_source = nullptr;
- CSSPrimitiveValue* start_scroll_offset = nullptr;
- CSSPrimitiveValue* end_scroll_offset = nullptr;
+ ScrollTimelineOffset* start_scroll_offset = nullptr;
+ ScrollTimelineOffset* end_scroll_offset = nullptr;
Persistent<ScrollTimeline> scroll_timeline =
MakeGarbageCollected<ScrollTimeline>(
&GetDocument(), scroll_source, ScrollTimeline::Block,
@@ -437,9 +434,13 @@ TEST_F(ScrollTimelineTest, ScheduleFrameWhenScrollerLayoutChanges) {
scrollable_area->SetScrollOffset(ScrollOffset(0, 20),
mojom::blink::ScrollType::kProgrammatic);
Element* scroller_element = GetElementById("scroller");
+
+ // Use empty offsets as 'auto'.
TestScrollTimeline* scroll_timeline =
- MakeGarbageCollected<TestScrollTimeline>(&GetDocument(), scroller_element,
- nullptr, nullptr);
+ MakeGarbageCollected<TestScrollTimeline>(
+ &GetDocument(), scroller_element,
+ MakeGarbageCollected<ScrollTimelineOffset>(),
+ MakeGarbageCollected<ScrollTimelineOffset>());
NonThrowableExceptionState exception_state;
Timing timing;
timing.iteration_duration = AnimationTimeDelta::FromSecondsD(30);
@@ -452,7 +453,9 @@ TEST_F(ScrollTimelineTest, ScheduleFrameWhenScrollerLayoutChanges) {
scroll_timeline, exception_state);
scroll_animation->play();
UpdateAllLifecyclePhasesForTest();
- // Validate that frame is scheduled when scroller layout changes.
+ // Validate that frame is scheduled when scroller layout changes that causes
+ // current time to change. Here we change the scroller max offset which
+ // affects current time because endScrollOffset is 'auto'.
Element* spacer_element = GetElementById("spacer");
spacer_element->setAttribute(html_names::kStyleAttr, "height:1000px;");
scroll_timeline->ResetNextServiceScheduled();
@@ -491,24 +494,184 @@ TEST_F(ScrollTimelineTest, CurrentTimeUpdateAfterNewAnimationFrame) {
ScrollTimeline* scroll_timeline =
ScrollTimeline::Create(GetDocument(), options, ASSERT_NO_EXCEPTION);
- bool current_time_is_null = false;
- double time_before = scroll_timeline->currentTime(current_time_is_null);
- ASSERT_FALSE(current_time_is_null);
+ double time_before = scroll_timeline->currentTime().value();
scrollable_area->SetScrollOffset(ScrollOffset(0, 10),
mojom::blink::ScrollType::kProgrammatic);
// Verify that the current time didn't change before there is a new animation
// frame.
- EXPECT_EQ(time_before, scroll_timeline->currentTime(current_time_is_null));
- ASSERT_FALSE(current_time_is_null);
+ EXPECT_EQ(time_before, scroll_timeline->currentTime().value());
// Simulate a new animation frame which allows the timeline to compute a new
// current time.
SimulateFrame();
// Verify that current time did change in the new animation frame.
- EXPECT_NE(time_before, scroll_timeline->currentTime(current_time_is_null));
- ASSERT_FALSE(current_time_is_null);
+ EXPECT_NE(time_before, scroll_timeline->currentTime().value());
+}
+
+TEST_F(ScrollTimelineTest, FinishedAnimationPlaysOnReversedScrolling) {
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ #scroller { overflow: scroll; width: 100px; height: 100px; }
+ #spacer { width: 200px; height: 200px; }
+ </style>
+ <div id='scroller'>
+ <div id ='spacer'></div>
+ </div>
+ )HTML");
+ Element* scroller_element = GetElementById("scroller");
+ LayoutBoxModelObject* scroller =
+ ToLayoutBoxModelObject(GetLayoutObjectByElementId("scroller"));
+ PaintLayerScrollableArea* scrollable_area = scroller->GetScrollableArea();
+ TestScrollTimeline* scroll_timeline =
+ MakeGarbageCollected<TestScrollTimeline>(&GetDocument(),
+ scroller_element);
+ NonThrowableExceptionState exception_state;
+ Timing timing;
+ timing.iteration_duration = AnimationTimeDelta::FromSecondsD(0.1);
+ Animation* scroll_animation =
+ Animation::Create(MakeGarbageCollected<KeyframeEffect>(
+ nullptr,
+ MakeGarbageCollected<StringKeyframeEffectModel>(
+ StringKeyframeVector()),
+ timing),
+ scroll_timeline, exception_state);
+ scroll_animation->play();
+ UpdateAllLifecyclePhasesForTest();
+ // Scroll to finished state.
+ scrollable_area->SetScrollOffset(ScrollOffset(0, 91),
+ mojom::blink::ScrollType::kProgrammatic);
+ // Simulate a new animation frame which allows the timeline to compute a new
+ // current time.
+ SimulateFrame();
+ ASSERT_EQ("finished", scroll_animation->playState());
+ // Verify that the animation was not removed from animations needing update
+ // list.
+ EXPECT_EQ(1u, scroll_timeline->AnimationsNeedingUpdateCount());
+
+ // Scroll back.
+ scrollable_area->SetScrollOffset(ScrollOffset(0, 80),
+ mojom::blink::ScrollType::kProgrammatic);
+ SimulateFrame();
+ // Verify that the animation as back to running.
+ EXPECT_EQ("running", scroll_animation->playState());
+}
+
+TEST_F(ScrollTimelineTest, CancelledAnimationDetachedFromTimeline) {
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ #scroller { overflow: scroll; width: 100px; height: 100px; }
+ #spacer { width: 200px; height: 200px; }
+ </style>
+ <div id='scroller'>
+ <div id ='spacer'></div>
+ </div>
+ )HTML");
+ TestScrollTimeline* scroll_timeline =
+ MakeGarbageCollected<TestScrollTimeline>(&GetDocument(),
+ GetElementById("scroller"));
+ NonThrowableExceptionState exception_state;
+ Timing timing;
+ timing.iteration_duration = AnimationTimeDelta::FromSecondsD(0.1);
+ Animation* scroll_animation =
+ Animation::Create(MakeGarbageCollected<KeyframeEffect>(
+ nullptr,
+ MakeGarbageCollected<StringKeyframeEffectModel>(
+ StringKeyframeVector()),
+ timing),
+ scroll_timeline, exception_state);
+ scroll_animation->play();
+ UpdateAllLifecyclePhasesForTest();
+ ASSERT_EQ(1u, scroll_timeline->AnimationsNeedingUpdateCount());
+
+ scroll_animation->cancel();
+ // Simulate a new animation frame which allows the timeline to compute a new
+ // current time.
+ SimulateFrame();
+ ASSERT_EQ("idle", scroll_animation->playState());
+ // Verify that the animation is removed from animations needing update
+ // list.
+ EXPECT_EQ(0u, scroll_timeline->AnimationsNeedingUpdateCount());
+}
+
+class AnimationEventListener final : public NativeEventListener {
+ public:
+ void Invoke(ExecutionContext*, Event* event) override {
+ event_received_ = true;
+ }
+ bool EventReceived() const { return event_received_; }
+ void ResetEventReceived() { event_received_ = false; }
+
+ private:
+ bool event_received_ = false;
+};
+
+TEST_F(ScrollTimelineTest,
+ FiringAnimationEventsByFinishedAnimationOnReversedScrolling) {
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ #scroller { overflow: scroll; width: 100px; height: 100px; }
+ #spacer { width: 200px; height: 200px; }
+ </style>
+ <div id='scroller'>
+ <div id ='spacer'></div>
+ </div>
+ )HTML");
+ LayoutBoxModelObject* scroller =
+ ToLayoutBoxModelObject(GetLayoutObjectByElementId("scroller"));
+ PaintLayerScrollableArea* scrollable_area = scroller->GetScrollableArea();
+ TestScrollTimeline* scroll_timeline =
+ MakeGarbageCollected<TestScrollTimeline>(&GetDocument(),
+ GetElementById("scroller"));
+ NonThrowableExceptionState exception_state;
+ Timing timing;
+ timing.iteration_duration = AnimationTimeDelta::FromSecondsD(0.1);
+ Animation* scroll_animation =
+ Animation::Create(MakeGarbageCollected<KeyframeEffect>(
+ nullptr,
+ MakeGarbageCollected<StringKeyframeEffectModel>(
+ StringKeyframeVector()),
+ timing),
+ scroll_timeline, exception_state);
+ auto* event_listener = MakeGarbageCollected<AnimationEventListener>();
+ scroll_animation->addEventListener(event_type_names::kFinish, event_listener);
+
+ scroll_animation->play();
+ UpdateAllLifecyclePhasesForTest();
+ // Scroll to finished state.
+ scrollable_area->SetScrollOffset(ScrollOffset(0, 91),
+ mojom::blink::ScrollType::kProgrammatic);
+ // Simulate a new animation frame which allows the timeline to compute a new
+ // current time.
+ SimulateFrame();
+ ASSERT_TRUE(event_listener->EventReceived());
+ event_listener->ResetEventReceived();
+
+ // Verify finished event does not re-fire.
+ SimulateFrame();
+ EXPECT_FALSE(event_listener->EventReceived());
+
+ // Scroll back.
+ scrollable_area->SetScrollOffset(ScrollOffset(0, 80),
+ mojom::blink::ScrollType::kProgrammatic);
+ SimulateFrame();
+ // Verify finished event is not fired on reverse scroll from finished state.
+ EXPECT_FALSE(event_listener->EventReceived());
+
+ // Scroll forward to finished state.
+ scrollable_area->SetScrollOffset(ScrollOffset(0, 91),
+ mojom::blink::ScrollType::kProgrammatic);
+ SimulateFrame();
+ // Verify animation finished event is fired.
+ EXPECT_TRUE(event_listener->EventReceived());
+ event_listener->ResetEventReceived();
+
+ scrollable_area->SetScrollOffset(ScrollOffset(0, 95),
+ mojom::blink::ScrollType::kProgrammatic);
+ SimulateFrame();
+ // Verify animation finished event is fired only once in finished state.
+ EXPECT_FALSE(event_listener->EventReceived());
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/animation/scroll_timeline_util.cc b/chromium/third_party/blink/renderer/core/animation/scroll_timeline_util.cc
index 5a4600b419b..394daa26d11 100644
--- a/chromium/third_party/blink/renderer/core/animation/scroll_timeline_util.cc
+++ b/chromium/third_party/blink/renderer/core/animation/scroll_timeline_util.cc
@@ -36,21 +36,8 @@ scoped_refptr<CompositorScrollTimeline> ToCompositorScrollTimeline(
CompositorScrollTimeline::ScrollDirection orientation = ConvertOrientation(
scroll_timeline->GetOrientation(), box ? box->Style() : nullptr);
- base::Optional<double> start_scroll_offset;
- base::Optional<double> end_scroll_offset;
- if (box) {
- double current_offset;
- double max_offset;
- scroll_timeline->GetCurrentAndMaxOffset(box, current_offset, max_offset);
-
- double resolved_start_scroll_offset = 0;
- double resolved_end_scroll_offset = max_offset;
- scroll_timeline->ResolveScrollStartAndEnd(box, max_offset,
- resolved_start_scroll_offset,
- resolved_end_scroll_offset);
- start_scroll_offset = resolved_start_scroll_offset;
- end_scroll_offset = resolved_end_scroll_offset;
- }
+ auto start_scroll_offset = scroll_timeline->GetResolvedStartScrollOffset();
+ auto end_scroll_offset = scroll_timeline->GetResolvedEndScrollOffset();
return CompositorScrollTimeline::Create(
element_id, orientation, start_scroll_offset, end_scroll_offset,
diff --git a/chromium/third_party/blink/renderer/core/animation/scroll_timeline_util_test.cc b/chromium/third_party/blink/renderer/core/animation/scroll_timeline_util_test.cc
index 58aa61f101b..9d146d046bd 100644
--- a/chromium/third_party/blink/renderer/core/animation/scroll_timeline_util_test.cc
+++ b/chromium/third_party/blink/renderer/core/animation/scroll_timeline_util_test.cc
@@ -13,6 +13,16 @@
namespace blink {
+namespace {
+
+StringOrScrollTimelineElementBasedOffset OffsetFromString(const String& value) {
+ StringOrScrollTimelineElementBasedOffset result;
+ result.SetString(value);
+ return result;
+}
+
+} // namespace
+
namespace scroll_timeline_util {
using ScrollTimelineUtilTest = PageTestBase;
@@ -47,8 +57,8 @@ TEST_F(ScrollTimelineUtilTest, ToCompositorScrollTimeline) {
options->setTimeRange(
DoubleOrScrollTimelineAutoKeyword::FromDouble(time_range));
options->setOrientation("block");
- options->setStartScrollOffset("50px");
- options->setEndScrollOffset("auto");
+ options->setStartScrollOffset(OffsetFromString("50px"));
+ options->setEndScrollOffset(OffsetFromString("auto"));
ScrollTimeline* timeline =
ScrollTimeline::Create(GetDocument(), options, ASSERT_NO_EXCEPTION);
@@ -80,8 +90,10 @@ TEST_F(ScrollTimelineUtilTest, ToCompositorScrollTimelineNullScrollSource) {
// scrollSource. The alternative approach would require us to remove the
// documentElement from the document.
Element* scroll_source = nullptr;
- CSSPrimitiveValue* start_scroll_offset = nullptr;
- CSSPrimitiveValue* end_scroll_offset = nullptr;
+ ScrollTimelineOffset* start_scroll_offset =
+ MakeGarbageCollected<ScrollTimelineOffset>();
+ ScrollTimelineOffset* end_scroll_offset =
+ MakeGarbageCollected<ScrollTimelineOffset>();
ScrollTimeline* timeline = MakeGarbageCollected<ScrollTimeline>(
&GetDocument(), scroll_source, ScrollTimeline::Block, start_scroll_offset,
end_scroll_offset, 100);
diff --git a/chromium/third_party/blink/renderer/core/animation/string_keyframe.cc b/chromium/third_party/blink/renderer/core/animation/string_keyframe.cc
index 7d3be39bde9..e966397c81d 100644
--- a/chromium/third_party/blink/renderer/core/animation/string_keyframe.cc
+++ b/chromium/third_party/blink/renderer/core/animation/string_keyframe.cc
@@ -178,8 +178,9 @@ bool StringKeyframe::HasCssProperty() const {
}
void StringKeyframe::AddKeyframePropertiesToV8Object(
- V8ObjectBuilder& object_builder) const {
- Keyframe::AddKeyframePropertiesToV8Object(object_builder);
+ V8ObjectBuilder& object_builder,
+ Element* element) const {
+ Keyframe::AddKeyframePropertiesToV8Object(object_builder, element);
for (const auto& entry : input_properties_) {
const PropertyHandle& property_handle = entry.key;
const CSSValue* property_value = entry.value;
@@ -259,6 +260,10 @@ bool StringKeyframe::CSSPropertySpecificKeyframe::
return true;
}
+bool StringKeyframe::CSSPropertySpecificKeyframe::IsRevert() const {
+ return value_ && value_->IsRevertValue();
+}
+
Keyframe::PropertySpecificKeyframe*
StringKeyframe::CSSPropertySpecificKeyframe::NeutralKeyframe(
double offset,
diff --git a/chromium/third_party/blink/renderer/core/animation/string_keyframe.h b/chromium/third_party/blink/renderer/core/animation/string_keyframe.h
index 31cdb962583..da68ab5f49f 100644
--- a/chromium/third_party/blink/renderer/core/animation/string_keyframe.h
+++ b/chromium/third_party/blink/renderer/core/animation/string_keyframe.h
@@ -81,7 +81,10 @@ class CORE_EXPORT StringKeyframe : public Keyframe {
bool HasCssProperty() const;
- void AddKeyframePropertiesToV8Object(V8ObjectBuilder&) const override;
+ void AddKeyframePropertiesToV8Object(V8ObjectBuilder&,
+ Element*) const override;
+
+ Keyframe* Clone() const override;
void Trace(Visitor*) override;
@@ -109,6 +112,7 @@ class CORE_EXPORT StringKeyframe : public Keyframe {
}
bool IsNeutral() const final { return !value_; }
+ bool IsRevert() const final;
Keyframe::PropertySpecificKeyframe* NeutralKeyframe(
double offset,
scoped_refptr<TimingFunction> easing) const final;
@@ -145,6 +149,7 @@ class CORE_EXPORT StringKeyframe : public Keyframe {
}
bool IsNeutral() const final { return value_.IsNull(); }
+ bool IsRevert() const final { return false; }
PropertySpecificKeyframe* NeutralKeyframe(
double offset,
scoped_refptr<TimingFunction> easing) const final;
@@ -156,7 +161,6 @@ class CORE_EXPORT StringKeyframe : public Keyframe {
};
private:
- Keyframe* Clone() const override;
Keyframe::PropertySpecificKeyframe* CreatePropertySpecificKeyframe(
const PropertyHandle&,
EffectModel::CompositeOperation effect_composite,
diff --git a/chromium/third_party/blink/renderer/core/animation/timing_calculations.h b/chromium/third_party/blink/renderer/core/animation/timing_calculations.h
index 370e9a3f8fa..c33ac8cf3ba 100644
--- a/chromium/third_party/blink/renderer/core/animation/timing_calculations.h
+++ b/chromium/third_party/blink/renderer/core/animation/timing_calculations.h
@@ -37,23 +37,29 @@
namespace blink {
namespace {
-inline bool IsWithinEpsilon(double a, double b) {
- // Permit 2-bits of quantization error. Threshold based on experimentation
- // with accuracy of fmod.
- return std::abs(a - b) <= 2.0 * std::numeric_limits<double>::epsilon();
-}
-
-inline bool LessThanOrEqualToWithinEpsilon(double a, double b) {
- return a <= b || IsWithinEpsilon(a, b);
-}
inline bool EndsOnIterationBoundary(double iteration_count,
double iteration_start) {
DCHECK(std::isfinite(iteration_count));
return !fmod(iteration_count + iteration_start, 1);
}
+
} // namespace
+static inline double TimingCalculationEpsilon() {
+ // Permit 2-bits of quantization error. Threshold based on experimentation
+ // with accuracy of fmod.
+ return 2.0 * std::numeric_limits<double>::epsilon();
+}
+
+static inline bool IsWithinAnimationTimeEpsilon(double a, double b) {
+ return std::abs(a - b) <= TimingCalculationEpsilon();
+}
+
+inline bool LessThanOrEqualToWithinEpsilon(double a, double b) {
+ return a <= b + TimingCalculationEpsilon();
+}
+
static inline double MultiplyZeroAlwaysGivesZero(double x, double y) {
DCHECK(!Timing::IsNull(x));
DCHECK(!Timing::IsNull(y));
@@ -148,7 +154,7 @@ static inline base::Optional<double> CalculateOverallProgress(
// 2. Calculate an initial value for overall progress.
double overall_progress = 0;
- if (IsWithinEpsilon(iteration_duration, 0)) {
+ if (IsWithinAnimationTimeEpsilon(iteration_duration, 0)) {
if (phase != Timing::kPhaseBefore)
overall_progress = iteration_count;
} else {
@@ -192,10 +198,11 @@ static inline base::Optional<double> CalculateSimpleIterationProgress(
// * the active time is equal to the active duration, and
// * the iteration count is not equal to zero.
// let the simple iteration progress be 1.0.
- if (IsWithinEpsilon(simple_iteration_progress, 0.0) &&
+ if (IsWithinAnimationTimeEpsilon(simple_iteration_progress, 0.0) &&
(phase == Timing::kPhaseActive || phase == Timing::kPhaseAfter) &&
- IsWithinEpsilon(active_time->InSecondsF(), active_duration) &&
- !IsWithinEpsilon(iteration_count, 0.0)) {
+ IsWithinAnimationTimeEpsilon(active_time->InSecondsF(),
+ active_duration) &&
+ !IsWithinAnimationTimeEpsilon(iteration_count, 0.0)) {
simple_iteration_progress = 1.0;
}
@@ -242,11 +249,11 @@ static inline bool IsCurrentDirectionForwards(
base::Optional<double> current_iteration,
Timing::PlaybackDirection direction) {
const bool current_iteration_is_even =
- !current_iteration
- ? false
- : (std::isinf(current_iteration.value())
- ? true
- : IsWithinEpsilon(fmod(current_iteration.value(), 2), 0));
+ !current_iteration ? false
+ : (std::isinf(current_iteration.value())
+ ? true
+ : IsWithinAnimationTimeEpsilon(
+ fmod(current_iteration.value(), 2), 0));
switch (direction) {
case Timing::PlaybackDirection::NORMAL:
@@ -304,10 +311,10 @@ static inline base::Optional<double> CalculateTransformedProgress(
// (crbug.com/949373)
if (phase == Timing::kPhaseAfter) {
if (is_current_direction_forward &&
- IsWithinEpsilon(directed_progress.value(), 1)) {
+ IsWithinAnimationTimeEpsilon(directed_progress.value(), 1)) {
directed_progress = 1;
} else if (!is_current_direction_forward &&
- IsWithinEpsilon(directed_progress.value(), 0)) {
+ IsWithinAnimationTimeEpsilon(directed_progress.value(), 0)) {
directed_progress = 0;
}
}
diff --git a/chromium/third_party/blink/renderer/core/animation/timing_input_test.cc b/chromium/third_party/blink/renderer/core/animation/timing_input_test.cc
index 3ab294441d0..6585577cd28 100644
--- a/chromium/third_party/blink/renderer/core/animation/timing_input_test.cc
+++ b/chromium/third_party/blink/renderer/core/animation/timing_input_test.cc
@@ -46,26 +46,39 @@ Timing AnimationTimingInputTest::ApplyTimingInputNumber(
v8::Local<v8::Object> timing_input = v8::Object::New(isolate);
SetV8ObjectPropertyAsNumber(isolate, timing_input, timing_property,
timing_property_value);
- DummyExceptionStateForTesting exception_state;
+
Timing result;
+ timing_conversion_success = false;
+ DummyExceptionStateForTesting exception_state;
if (is_keyframeeffectoptions) {
KeyframeEffectOptions* timing_input_dictionary =
NativeValueTraits<KeyframeEffectOptions>::NativeValue(
isolate, timing_input, exception_state);
+ if (exception_state.HadException()) {
+ return Timing();
+ }
+
UnrestrictedDoubleOrKeyframeEffectOptions timing_input =
UnrestrictedDoubleOrKeyframeEffectOptions::FromKeyframeEffectOptions(
timing_input_dictionary);
result = TimingInput::Convert(timing_input, GetDocument(), exception_state);
+ if (exception_state.HadException())
+ return Timing();
} else {
KeyframeAnimationOptions* timing_input_dictionary =
NativeValueTraits<KeyframeAnimationOptions>::NativeValue(
isolate, timing_input, exception_state);
+ if (exception_state.HadException())
+ return Timing();
+
UnrestrictedDoubleOrKeyframeAnimationOptions timing_input =
UnrestrictedDoubleOrKeyframeAnimationOptions::
FromKeyframeAnimationOptions(timing_input_dictionary);
result = TimingInput::Convert(timing_input, GetDocument(), exception_state);
+ if (exception_state.HadException())
+ return Timing();
}
- timing_conversion_success = !exception_state.HadException();
+ timing_conversion_success = true;
return result;
}
@@ -79,56 +92,75 @@ Timing AnimationTimingInputTest::ApplyTimingInputString(
SetV8ObjectPropertyAsString(isolate, timing_input, timing_property,
timing_property_value);
- DummyExceptionStateForTesting exception_state;
Timing result;
+ timing_conversion_success = false;
+ DummyExceptionStateForTesting exception_state;
if (is_keyframeeffectoptions) {
KeyframeEffectOptions* timing_input_dictionary =
NativeValueTraits<KeyframeEffectOptions>::NativeValue(
isolate, timing_input, exception_state);
+ if (exception_state.HadException())
+ return Timing();
+
UnrestrictedDoubleOrKeyframeEffectOptions timing_input =
UnrestrictedDoubleOrKeyframeEffectOptions::FromKeyframeEffectOptions(
timing_input_dictionary);
result = TimingInput::Convert(timing_input, GetDocument(), exception_state);
+ if (exception_state.HadException())
+ return Timing();
} else {
KeyframeAnimationOptions* timing_input_dictionary =
NativeValueTraits<KeyframeAnimationOptions>::NativeValue(
isolate, timing_input, exception_state);
+ if (exception_state.HadException())
+ return Timing();
+
UnrestrictedDoubleOrKeyframeAnimationOptions timing_input =
UnrestrictedDoubleOrKeyframeAnimationOptions::
FromKeyframeAnimationOptions(timing_input_dictionary);
result = TimingInput::Convert(timing_input, GetDocument(), exception_state);
+ if (exception_state.HadException())
+ return Timing();
}
- timing_conversion_success = !exception_state.HadException();
+ timing_conversion_success = true;
return result;
}
TEST_F(AnimationTimingInputTest, TimingInputStartDelay) {
V8TestingScope scope;
- bool ignored_success;
+ bool did_success;
EXPECT_EQ(1.1, ApplyTimingInputNumber(scope.GetIsolate(), "delay", 1100,
- ignored_success)
+ did_success)
.start_delay);
+ EXPECT_TRUE(did_success);
EXPECT_EQ(-1, ApplyTimingInputNumber(scope.GetIsolate(), "delay", -1000,
- ignored_success)
+ did_success)
.start_delay);
+ EXPECT_TRUE(did_success);
EXPECT_EQ(1, ApplyTimingInputString(scope.GetIsolate(), "delay", "1000",
- ignored_success)
- .start_delay);
- EXPECT_EQ(0, ApplyTimingInputString(scope.GetIsolate(), "delay", "1s",
- ignored_success)
+ did_success)
.start_delay);
+ EXPECT_TRUE(did_success);
+ EXPECT_EQ(
+ 0, ApplyTimingInputString(scope.GetIsolate(), "delay", "1s", did_success)
+ .start_delay);
+ EXPECT_FALSE(did_success);
EXPECT_EQ(0, ApplyTimingInputString(scope.GetIsolate(), "delay", "Infinity",
- ignored_success)
+ did_success)
.start_delay);
+ EXPECT_FALSE(did_success);
EXPECT_EQ(0, ApplyTimingInputString(scope.GetIsolate(), "delay", "-Infinity",
- ignored_success)
- .start_delay);
- EXPECT_EQ(0, ApplyTimingInputString(scope.GetIsolate(), "delay", "NaN",
- ignored_success)
+ did_success)
.start_delay);
+ EXPECT_FALSE(did_success);
+ EXPECT_EQ(
+ 0, ApplyTimingInputString(scope.GetIsolate(), "delay", "NaN", did_success)
+ .start_delay);
+ EXPECT_FALSE(did_success);
EXPECT_EQ(0, ApplyTimingInputString(scope.GetIsolate(), "delay", "rubbish",
- ignored_success)
+ did_success)
.start_delay);
+ EXPECT_FALSE(did_success);
}
TEST_F(AnimationTimingInputTest,
diff --git a/chromium/third_party/blink/renderer/core/animation/transition_keyframe.cc b/chromium/third_party/blink/renderer/core/animation/transition_keyframe.cc
index a26bc65b634..7a42136093b 100644
--- a/chromium/third_party/blink/renderer/core/animation/transition_keyframe.cc
+++ b/chromium/third_party/blink/renderer/core/animation/transition_keyframe.cc
@@ -5,10 +5,18 @@
#include "third_party/blink/renderer/core/animation/transition_keyframe.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_object_builder.h"
+#include "third_party/blink/renderer/core/animation/animation_input_helpers.h"
+#include "third_party/blink/renderer/core/animation/animation_utils.h"
#include "third_party/blink/renderer/core/animation/compositor_animations.h"
+#include "third_party/blink/renderer/core/animation/css_interpolation_environment.h"
+#include "third_party/blink/renderer/core/animation/css_interpolation_types_map.h"
#include "third_party/blink/renderer/core/animation/interpolation_type.h"
#include "third_party/blink/renderer/core/animation/pairwise_interpolation_value.h"
#include "third_party/blink/renderer/core/animation/transition_interpolation.h"
+#include "third_party/blink/renderer/core/css/properties/css_property_ref.h"
+#include "third_party/blink/renderer/core/css/resolver/style_resolver.h"
+#include "third_party/blink/renderer/core/dom/document.h"
+#include "third_party/blink/renderer/core/style/computed_style.h"
namespace blink {
@@ -26,9 +34,32 @@ PropertyHandleSet TransitionKeyframe::Properties() const {
}
void TransitionKeyframe::AddKeyframePropertiesToV8Object(
- V8ObjectBuilder& object_builder) const {
- Keyframe::AddKeyframePropertiesToV8Object(object_builder);
- // TODO(crbug.com/777971): Add in the property/value for TransitionKeyframe.
+ V8ObjectBuilder& object_builder,
+ Element* element) const {
+ Keyframe::AddKeyframePropertiesToV8Object(object_builder, element);
+
+ // TODO(crbug.com/933761): Fix resolution of the style in the case where the
+ // target element has been removed.
+ if (!element)
+ return;
+
+ Document& document = element->GetDocument();
+ StyleResolverState state(document, *element);
+ state.SetStyle(ComputedStyle::Create());
+ CSSInterpolationTypesMap map(document.GetPropertyRegistry(), document);
+ CSSInterpolationEnvironment environment(map, state, nullptr);
+ value_->GetType().Apply(value_->GetInterpolableValue(),
+ value_->GetNonInterpolableValue(), environment);
+
+ const ComputedStyle* style = state.Style();
+ String property_value =
+ AnimationUtils::KeyframeValueFromComputedStyle(
+ property_, *style, document, element->GetLayoutObject())
+ ->CssText();
+
+ String property_name =
+ AnimationInputHelpers::PropertyHandleToKeyframeAttribute(property_);
+ object_builder.Add(property_name, property_value);
}
void TransitionKeyframe::Trace(Visitor* visitor) {
diff --git a/chromium/third_party/blink/renderer/core/animation/transition_keyframe.h b/chromium/third_party/blink/renderer/core/animation/transition_keyframe.h
index 9a21096c312..cbaa0db934c 100644
--- a/chromium/third_party/blink/renderer/core/animation/transition_keyframe.h
+++ b/chromium/third_party/blink/renderer/core/animation/transition_keyframe.h
@@ -42,7 +42,8 @@ class CORE_EXPORT TransitionKeyframe : public Keyframe {
void SetCompositorValue(CompositorKeyframeValue*);
PropertyHandleSet Properties() const final;
- void AddKeyframePropertiesToV8Object(V8ObjectBuilder&) const override;
+ void AddKeyframePropertiesToV8Object(V8ObjectBuilder&,
+ Element*) const override;
void Trace(Visitor*) override;
@@ -64,6 +65,7 @@ class CORE_EXPORT TransitionKeyframe : public Keyframe {
}
bool IsNeutral() const final { return false; }
+ bool IsRevert() const final { return false; }
Keyframe::PropertySpecificKeyframe* NeutralKeyframe(
double offset,
scoped_refptr<TimingFunction> easing) const final {
diff --git a/chromium/third_party/blink/renderer/core/animation_frame/worker_animation_frame_provider.cc b/chromium/third_party/blink/renderer/core/animation_frame/worker_animation_frame_provider.cc
index 36fd6aaae50..3d314f5d756 100644
--- a/chromium/third_party/blink/renderer/core/animation_frame/worker_animation_frame_provider.cc
+++ b/chromium/third_party/blink/renderer/core/animation_frame/worker_animation_frame_provider.cc
@@ -15,8 +15,9 @@ WorkerAnimationFrameProvider::WorkerAnimationFrameProvider(
ExecutionContext* context,
const BeginFrameProviderParams& begin_frame_provider_params)
: begin_frame_provider_(
- std::make_unique<BeginFrameProvider>(begin_frame_provider_params,
- this)),
+ MakeGarbageCollected<BeginFrameProvider>(begin_frame_provider_params,
+ this,
+ context)),
callback_collection_(context),
context_(context) {}
@@ -71,21 +72,21 @@ void WorkerAnimationFrameProvider::BeginFrame(const viz::BeginFrameArgs& args) {
void WorkerAnimationFrameProvider::RegisterOffscreenCanvas(
OffscreenCanvas* context) {
- DCHECK(offscreen_canvases_.Find(context) == kNotFound);
- offscreen_canvases_.push_back(context);
+ auto result = offscreen_canvases_.insert(context);
+ DCHECK(result.is_new_entry);
}
void WorkerAnimationFrameProvider::DeregisterOffscreenCanvas(
OffscreenCanvas* offscreen_canvas) {
- wtf_size_t pos = offscreen_canvases_.Find(offscreen_canvas);
- if (pos != kNotFound) {
- offscreen_canvases_.EraseAt(pos);
- }
+ offscreen_canvases_.erase(offscreen_canvas);
}
void WorkerAnimationFrameProvider::Trace(Visitor* visitor) {
+ visitor->Trace(begin_frame_provider_);
visitor->Trace(callback_collection_);
+ visitor->Trace(offscreen_canvases_);
visitor->Trace(context_);
+ BeginFrameProviderClient::Trace(visitor);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/animation_frame/worker_animation_frame_provider.h b/chromium/third_party/blink/renderer/core/animation_frame/worker_animation_frame_provider.h
index 939883ce2df..d06b7d02dd3 100644
--- a/chromium/third_party/blink/renderer/core/animation_frame/worker_animation_frame_provider.h
+++ b/chromium/third_party/blink/renderer/core/animation_frame/worker_animation_frame_provider.h
@@ -9,6 +9,7 @@
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/dom/frame_request_callback_collection.h"
#include "third_party/blink/renderer/platform/graphics/begin_frame_provider.h"
+#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
namespace blink {
@@ -28,6 +29,8 @@ class OffscreenCanvas;
class CORE_EXPORT WorkerAnimationFrameProvider
: public GarbageCollected<WorkerAnimationFrameProvider>,
public BeginFrameProviderClient {
+ USING_GARBAGE_COLLECTED_MIXIN(WorkerAnimationFrameProvider);
+
public:
WorkerAnimationFrameProvider(
ExecutionContext* context,
@@ -36,7 +39,7 @@ class CORE_EXPORT WorkerAnimationFrameProvider
int RegisterCallback(FrameRequestCallbackCollection::FrameCallback* callback);
void CancelCallback(int id);
- void Trace(Visitor* visitor);
+ void Trace(Visitor* visitor) override;
// BeginFrameProviderClient
void BeginFrame(const viz::BeginFrameArgs&) override;
@@ -47,13 +50,11 @@ class CORE_EXPORT WorkerAnimationFrameProvider
static const int kInvalidCallbackId = -1;
private:
- const std::unique_ptr<BeginFrameProvider> begin_frame_provider_;
+ const Member<BeginFrameProvider> begin_frame_provider_;
DISALLOW_COPY_AND_ASSIGN(WorkerAnimationFrameProvider);
FrameRequestCallbackCollection callback_collection_;
- // To avoid leaking OffscreenCanvas objects, the following vector must
- // not hold strong references.
- Vector<UntracedMember<OffscreenCanvas>> offscreen_canvases_;
+ HeapLinkedHashSet<WeakMember<OffscreenCanvas>> offscreen_canvases_;
Member<ExecutionContext> context_;
diff --git a/chromium/third_party/blink/renderer/core/aom/accessible_node.cc b/chromium/third_party/blink/renderer/core/aom/accessible_node.cc
index 2e1cb679398..198fabffe62 100644
--- a/chromium/third_party/blink/renderer/core/aom/accessible_node.cc
+++ b/chromium/third_party/blink/renderer/core/aom/accessible_node.cc
@@ -65,10 +65,8 @@ QualifiedName GetCorrespondingARIAAttribute(AOMRelationProperty property) {
switch (property) {
case AOMRelationProperty::kActiveDescendant:
return html_names::kAriaActivedescendantAttr;
- break;
case AOMRelationProperty::kErrorMessage:
return html_names::kAriaErrormessageAttr;
- break;
}
NOTREACHED();
@@ -79,24 +77,18 @@ QualifiedName GetCorrespondingARIAAttribute(AOMRelationListProperty property) {
switch (property) {
case AOMRelationListProperty::kDescribedBy:
return html_names::kAriaDescribedbyAttr;
- break;
case AOMRelationListProperty::kDetails:
return html_names::kAriaDetailsAttr;
- break;
case AOMRelationListProperty::kControls:
return html_names::kAriaControlsAttr;
- break;
case AOMRelationListProperty::kFlowTo:
return html_names::kAriaFlowtoAttr;
- break;
case AOMRelationListProperty::kLabeledBy:
// Note that there are two allowed spellings of this attribute.
// Callers should check both.
return html_names::kAriaLabelledbyAttr;
- break;
case AOMRelationListProperty::kOwns:
return html_names::kAriaOwnsAttr;
- break;
}
NOTREACHED();
@@ -107,37 +99,26 @@ QualifiedName GetCorrespondingARIAAttribute(AOMBooleanProperty property) {
switch (property) {
case AOMBooleanProperty::kAtomic:
return html_names::kAriaAtomicAttr;
- break;
case AOMBooleanProperty::kBusy:
return html_names::kAriaBusyAttr;
- break;
case AOMBooleanProperty::kDisabled:
return html_names::kAriaDisabledAttr;
- break;
case AOMBooleanProperty::kExpanded:
return html_names::kAriaExpandedAttr;
- break;
case AOMBooleanProperty::kHidden:
return html_names::kAriaHiddenAttr;
- break;
case AOMBooleanProperty::kModal:
return html_names::kAriaModalAttr;
- break;
case AOMBooleanProperty::kMultiline:
return html_names::kAriaMultilineAttr;
- break;
case AOMBooleanProperty::kMultiselectable:
return html_names::kAriaMultiselectableAttr;
- break;
case AOMBooleanProperty::kReadOnly:
return html_names::kAriaReadonlyAttr;
- break;
case AOMBooleanProperty::kRequired:
return html_names::kAriaRequiredAttr;
- break;
case AOMBooleanProperty::kSelected:
return html_names::kAriaSelectedAttr;
- break;
}
NOTREACHED();
@@ -149,13 +130,10 @@ QualifiedName GetCorrespondingARIAAttribute(AOMFloatProperty property) {
switch (property) {
case AOMFloatProperty::kValueMax:
return html_names::kAriaValuemaxAttr;
- break;
case AOMFloatProperty::kValueMin:
return html_names::kAriaValueminAttr;
- break;
case AOMFloatProperty::kValueNow:
return html_names::kAriaValuenowAttr;
- break;
}
NOTREACHED();
@@ -166,22 +144,16 @@ QualifiedName GetCorrespondingARIAAttribute(AOMUIntProperty property) {
switch (property) {
case AOMUIntProperty::kColIndex:
return html_names::kAriaColindexAttr;
- break;
case AOMUIntProperty::kColSpan:
return html_names::kAriaColspanAttr;
- break;
case AOMUIntProperty::kLevel:
return html_names::kAriaLevelAttr;
- break;
case AOMUIntProperty::kPosInSet:
return html_names::kAriaPosinsetAttr;
- break;
case AOMUIntProperty::kRowIndex:
return html_names::kAriaRowindexAttr;
- break;
case AOMUIntProperty::kRowSpan:
return html_names::kAriaRowspanAttr;
- break;
}
NOTREACHED();
@@ -192,13 +164,10 @@ QualifiedName GetCorrespondingARIAAttribute(AOMIntProperty property) {
switch (property) {
case AOMIntProperty::kColCount:
return html_names::kAriaColcountAttr;
- break;
case AOMIntProperty::kRowCount:
return html_names::kAriaRowcountAttr;
- break;
case AOMIntProperty::kSetSize:
return html_names::kAriaSetsizeAttr;
- break;
}
NOTREACHED();
@@ -307,21 +276,6 @@ static base::Optional<T> FindPropertyValue(
return base::nullopt;
}
-template <typename P, typename T>
-static T FindPropertyValue(P property,
- bool& is_null,
- const Vector<std::pair<P, T>>& properties,
- T default_value) {
- for (const auto& item : properties) {
- if (item.first == property) {
- is_null = false;
- return item.second;
- }
- }
-
- return default_value;
-}
-
base::Optional<bool> AccessibleNode::GetProperty(
AOMBooleanProperty property) const {
return FindPropertyValue(property, boolean_properties_);
@@ -354,57 +308,6 @@ base::Optional<float> AccessibleNode::GetProperty(Element* element,
property, element->ExistingAccessibleNode()->float_properties_);
}
-bool AccessibleNode::GetProperty(AOMBooleanProperty property,
- bool& is_null) const {
- is_null = true;
- return FindPropertyValue(property, is_null, boolean_properties_, false);
-}
-
-// static
-float AccessibleNode::GetProperty(Element* element,
- AOMFloatProperty property,
- bool& is_null) {
- is_null = true;
-
- float default_value = 0.0;
- if (!element || !element->ExistingAccessibleNode())
- return default_value;
-
- return FindPropertyValue(property, is_null,
- element->ExistingAccessibleNode()->float_properties_,
- default_value);
-}
-
-// static
-int32_t AccessibleNode::GetProperty(Element* element,
- AOMIntProperty property,
- bool& is_null) {
- is_null = true;
-
- int32_t default_value = 0;
- if (!element || !element->ExistingAccessibleNode())
- return default_value;
-
- return FindPropertyValue(property, is_null,
- element->ExistingAccessibleNode()->int_properties_,
- default_value);
-}
-
-// static
-uint32_t AccessibleNode::GetProperty(Element* element,
- AOMUIntProperty property,
- bool& is_null) {
- is_null = true;
-
- uint32_t default_value = 0;
- if (!element || !element->ExistingAccessibleNode())
- return default_value;
-
- return FindPropertyValue(property, is_null,
- element->ExistingAccessibleNode()->uint_properties_,
- default_value);
-}
-
bool AccessibleNode::IsUndefinedAttrValue(const AtomicString& value) {
return value.IsEmpty() || EqualIgnoringASCIICase(value, "undefined");
}
@@ -608,15 +511,6 @@ void AccessibleNode::setAtomic(base::Optional<bool> value) {
NotifyAttributeChanged(html_names::kAriaAtomicAttr);
}
-bool AccessibleNode::atomic(bool& is_null) const {
- return GetProperty(AOMBooleanProperty::kAtomic, is_null);
-}
-
-void AccessibleNode::setAtomic(bool atomic, bool is_null) {
- SetBooleanProperty(AOMBooleanProperty::kAtomic, atomic, is_null);
- NotifyAttributeChanged(html_names::kAriaAtomicAttr);
-}
-
AtomicString AccessibleNode::autocomplete() const {
return GetProperty(AOMStringProperty::kAutocomplete);
}
@@ -635,15 +529,6 @@ void AccessibleNode::setBusy(base::Optional<bool> value) {
NotifyAttributeChanged(html_names::kAriaBusyAttr);
}
-bool AccessibleNode::busy(bool& is_null) const {
- return GetProperty(AOMBooleanProperty::kBusy, is_null);
-}
-
-void AccessibleNode::setBusy(bool busy, bool is_null) {
- SetBooleanProperty(AOMBooleanProperty::kBusy, busy, is_null);
- NotifyAttributeChanged(html_names::kAriaBusyAttr);
-}
-
AtomicString AccessibleNode::checked() const {
return GetProperty(AOMStringProperty::kChecked);
}
@@ -662,15 +547,6 @@ void AccessibleNode::setColCount(base::Optional<int32_t> value) {
NotifyAttributeChanged(html_names::kAriaColcountAttr);
}
-int32_t AccessibleNode::colCount(bool& is_null) const {
- return GetProperty(element_, AOMIntProperty::kColCount, is_null);
-}
-
-void AccessibleNode::setColCount(int32_t col_count, bool is_null) {
- SetIntProperty(AOMIntProperty::kColCount, col_count, is_null);
- NotifyAttributeChanged(html_names::kAriaColcountAttr);
-}
-
base::Optional<uint32_t> AccessibleNode::colIndex() const {
return GetProperty(element_, AOMUIntProperty::kColIndex);
}
@@ -680,15 +556,6 @@ void AccessibleNode::setColIndex(base::Optional<uint32_t> value) {
NotifyAttributeChanged(html_names::kAriaColindexAttr);
}
-uint32_t AccessibleNode::colIndex(bool& is_null) const {
- return GetProperty(element_, AOMUIntProperty::kColIndex, is_null);
-}
-
-void AccessibleNode::setColIndex(uint32_t col_index, bool is_null) {
- SetUIntProperty(AOMUIntProperty::kColIndex, col_index, is_null);
- NotifyAttributeChanged(html_names::kAriaColindexAttr);
-}
-
base::Optional<uint32_t> AccessibleNode::colSpan() const {
return GetProperty(element_, AOMUIntProperty::kColSpan);
}
@@ -698,15 +565,6 @@ void AccessibleNode::setColSpan(base::Optional<uint32_t> value) {
NotifyAttributeChanged(html_names::kAriaColspanAttr);
}
-uint32_t AccessibleNode::colSpan(bool& is_null) const {
- return GetProperty(element_, AOMUIntProperty::kColSpan, is_null);
-}
-
-void AccessibleNode::setColSpan(uint32_t col_span, bool is_null) {
- SetUIntProperty(AOMUIntProperty::kColSpan, col_span, is_null);
- NotifyAttributeChanged(html_names::kAriaColspanAttr);
-}
-
AccessibleNodeList* AccessibleNode::controls() const {
return GetProperty(element_, AOMRelationListProperty::kControls);
}
@@ -761,15 +619,6 @@ void AccessibleNode::setDisabled(base::Optional<bool> value) {
NotifyAttributeChanged(html_names::kAriaDisabledAttr);
}
-bool AccessibleNode::disabled(bool& is_null) const {
- return GetProperty(AOMBooleanProperty::kDisabled, is_null);
-}
-
-void AccessibleNode::setDisabled(bool disabled, bool is_null) {
- SetBooleanProperty(AOMBooleanProperty::kDisabled, disabled, is_null);
- NotifyAttributeChanged(html_names::kAriaDisabledAttr);
-}
-
AccessibleNode* AccessibleNode::errorMessage() const {
return GetProperty(element_, AOMRelationProperty::kErrorMessage);
}
@@ -788,15 +637,6 @@ void AccessibleNode::setExpanded(base::Optional<bool> value) {
NotifyAttributeChanged(html_names::kAriaExpandedAttr);
}
-bool AccessibleNode::expanded(bool& is_null) const {
- return GetProperty(AOMBooleanProperty::kExpanded, is_null);
-}
-
-void AccessibleNode::setExpanded(bool expanded, bool is_null) {
- SetBooleanProperty(AOMBooleanProperty::kExpanded, expanded, is_null);
- NotifyAttributeChanged(html_names::kAriaExpandedAttr);
-}
-
AccessibleNodeList* AccessibleNode::flowTo() const {
return GetProperty(element_, AOMRelationListProperty::kFlowTo);
}
@@ -824,15 +664,6 @@ void AccessibleNode::setHidden(base::Optional<bool> value) {
NotifyAttributeChanged(html_names::kAriaHiddenAttr);
}
-bool AccessibleNode::hidden(bool& is_null) const {
- return GetProperty(AOMBooleanProperty::kHidden, is_null);
-}
-
-void AccessibleNode::setHidden(bool hidden, bool is_null) {
- SetBooleanProperty(AOMBooleanProperty::kHidden, hidden, is_null);
- NotifyAttributeChanged(html_names::kAriaHiddenAttr);
-}
-
AtomicString AccessibleNode::invalid() const {
return GetProperty(AOMStringProperty::kInvalid);
}
@@ -878,15 +709,6 @@ void AccessibleNode::setLevel(base::Optional<uint32_t> value) {
NotifyAttributeChanged(html_names::kAriaLevelAttr);
}
-uint32_t AccessibleNode::level(bool& is_null) const {
- return GetProperty(element_, AOMUIntProperty::kLevel, is_null);
-}
-
-void AccessibleNode::setLevel(uint32_t level, bool is_null) {
- SetUIntProperty(AOMUIntProperty::kLevel, level, is_null);
- NotifyAttributeChanged(html_names::kAriaLevelAttr);
-}
-
AtomicString AccessibleNode::live() const {
return GetProperty(AOMStringProperty::kLive);
}
@@ -905,15 +727,6 @@ void AccessibleNode::setModal(base::Optional<bool> value) {
NotifyAttributeChanged(html_names::kAriaModalAttr);
}
-bool AccessibleNode::modal(bool& is_null) const {
- return GetProperty(AOMBooleanProperty::kModal, is_null);
-}
-
-void AccessibleNode::setModal(bool modal, bool is_null) {
- SetBooleanProperty(AOMBooleanProperty::kModal, modal, is_null);
- NotifyAttributeChanged(html_names::kAriaModalAttr);
-}
-
base::Optional<bool> AccessibleNode::multiline() const {
return GetProperty(AOMBooleanProperty::kMultiline);
}
@@ -923,15 +736,6 @@ void AccessibleNode::setMultiline(base::Optional<bool> value) {
NotifyAttributeChanged(html_names::kAriaMultilineAttr);
}
-bool AccessibleNode::multiline(bool& is_null) const {
- return GetProperty(AOMBooleanProperty::kMultiline, is_null);
-}
-
-void AccessibleNode::setMultiline(bool multiline, bool is_null) {
- SetBooleanProperty(AOMBooleanProperty::kMultiline, multiline, is_null);
- NotifyAttributeChanged(html_names::kAriaMultilineAttr);
-}
-
base::Optional<bool> AccessibleNode::multiselectable() const {
return GetProperty(AOMBooleanProperty::kMultiselectable);
}
@@ -941,16 +745,6 @@ void AccessibleNode::setMultiselectable(base::Optional<bool> value) {
NotifyAttributeChanged(html_names::kAriaMultiselectableAttr);
}
-bool AccessibleNode::multiselectable(bool& is_null) const {
- return GetProperty(AOMBooleanProperty::kMultiselectable, is_null);
-}
-
-void AccessibleNode::setMultiselectable(bool multiselectable, bool is_null) {
- SetBooleanProperty(AOMBooleanProperty::kMultiselectable, multiselectable,
- is_null);
- NotifyAttributeChanged(html_names::kAriaMultiselectableAttr);
-}
-
AtomicString AccessibleNode::orientation() const {
return GetProperty(AOMStringProperty::kOrientation);
}
@@ -987,15 +781,6 @@ void AccessibleNode::setPosInSet(base::Optional<uint32_t> value) {
NotifyAttributeChanged(html_names::kAriaPosinsetAttr);
}
-uint32_t AccessibleNode::posInSet(bool& is_null) const {
- return GetProperty(element_, AOMUIntProperty::kPosInSet, is_null);
-}
-
-void AccessibleNode::setPosInSet(uint32_t pos_in_set, bool is_null) {
- SetUIntProperty(AOMUIntProperty::kPosInSet, pos_in_set, is_null);
- NotifyAttributeChanged(html_names::kAriaPosinsetAttr);
-}
-
AtomicString AccessibleNode::pressed() const {
return GetProperty(AOMStringProperty::kPressed);
}
@@ -1014,15 +799,6 @@ void AccessibleNode::setReadOnly(base::Optional<bool> value) {
NotifyAttributeChanged(html_names::kAriaReadonlyAttr);
}
-bool AccessibleNode::readOnly(bool& is_null) const {
- return GetProperty(AOMBooleanProperty::kReadOnly, is_null);
-}
-
-void AccessibleNode::setReadOnly(bool read_only, bool is_null) {
- SetBooleanProperty(AOMBooleanProperty::kReadOnly, read_only, is_null);
- NotifyAttributeChanged(html_names::kAriaReadonlyAttr);
-}
-
AtomicString AccessibleNode::relevant() const {
return GetProperty(AOMStringProperty::kRelevant);
}
@@ -1041,15 +817,6 @@ void AccessibleNode::setRequired(base::Optional<bool> value) {
NotifyAttributeChanged(html_names::kAriaRequiredAttr);
}
-bool AccessibleNode::required(bool& is_null) const {
- return GetProperty(AOMBooleanProperty::kRequired, is_null);
-}
-
-void AccessibleNode::setRequired(bool required, bool is_null) {
- SetBooleanProperty(AOMBooleanProperty::kRequired, required, is_null);
- NotifyAttributeChanged(html_names::kAriaRequiredAttr);
-}
-
AtomicString AccessibleNode::role() const {
return GetProperty(AOMStringProperty::kRole);
}
@@ -1077,15 +844,6 @@ void AccessibleNode::setRowCount(base::Optional<int32_t> value) {
NotifyAttributeChanged(html_names::kAriaRowcountAttr);
}
-int32_t AccessibleNode::rowCount(bool& is_null) const {
- return GetProperty(element_, AOMIntProperty::kRowCount, is_null);
-}
-
-void AccessibleNode::setRowCount(int32_t row_count, bool is_null) {
- SetIntProperty(AOMIntProperty::kRowCount, row_count, is_null);
- NotifyAttributeChanged(html_names::kAriaRowcountAttr);
-}
-
base::Optional<uint32_t> AccessibleNode::rowIndex() const {
return GetProperty(element_, AOMUIntProperty::kRowIndex);
}
@@ -1095,15 +853,6 @@ void AccessibleNode::setRowIndex(base::Optional<uint32_t> value) {
NotifyAttributeChanged(html_names::kAriaRowindexAttr);
}
-uint32_t AccessibleNode::rowIndex(bool& is_null) const {
- return GetProperty(element_, AOMUIntProperty::kRowIndex, is_null);
-}
-
-void AccessibleNode::setRowIndex(uint32_t row_index, bool is_null) {
- SetUIntProperty(AOMUIntProperty::kRowIndex, row_index, is_null);
- NotifyAttributeChanged(html_names::kAriaRowindexAttr);
-}
-
base::Optional<uint32_t> AccessibleNode::rowSpan() const {
return GetProperty(element_, AOMUIntProperty::kRowSpan);
}
@@ -1113,15 +862,6 @@ void AccessibleNode::setRowSpan(base::Optional<uint32_t> value) {
NotifyAttributeChanged(html_names::kAriaRowspanAttr);
}
-uint32_t AccessibleNode::rowSpan(bool& is_null) const {
- return GetProperty(element_, AOMUIntProperty::kRowSpan, is_null);
-}
-
-void AccessibleNode::setRowSpan(uint32_t row_span, bool is_null) {
- SetUIntProperty(AOMUIntProperty::kRowSpan, row_span, is_null);
- NotifyAttributeChanged(html_names::kAriaRowspanAttr);
-}
-
base::Optional<bool> AccessibleNode::selected() const {
return GetProperty(AOMBooleanProperty::kSelected);
}
@@ -1131,15 +871,6 @@ void AccessibleNode::setSelected(base::Optional<bool> value) {
NotifyAttributeChanged(html_names::kAriaSelectedAttr);
}
-bool AccessibleNode::selected(bool& is_null) const {
- return GetProperty(AOMBooleanProperty::kSelected, is_null);
-}
-
-void AccessibleNode::setSelected(bool selected, bool is_null) {
- SetBooleanProperty(AOMBooleanProperty::kSelected, selected, is_null);
- NotifyAttributeChanged(html_names::kAriaSelectedAttr);
-}
-
base::Optional<int32_t> AccessibleNode::setSize() const {
return GetProperty(element_, AOMIntProperty::kSetSize);
}
@@ -1149,15 +880,6 @@ void AccessibleNode::setSetSize(base::Optional<int32_t> value) {
NotifyAttributeChanged(html_names::kAriaSetsizeAttr);
}
-int32_t AccessibleNode::setSize(bool& is_null) const {
- return GetProperty(element_, AOMIntProperty::kSetSize, is_null);
-}
-
-void AccessibleNode::setSetSize(int32_t set_size, bool is_null) {
- SetIntProperty(AOMIntProperty::kSetSize, set_size, is_null);
- NotifyAttributeChanged(html_names::kAriaSetsizeAttr);
-}
-
AtomicString AccessibleNode::sort() const {
return GetProperty(AOMStringProperty::kSort);
}
@@ -1176,15 +898,6 @@ void AccessibleNode::setValueMax(base::Optional<float> value) {
NotifyAttributeChanged(html_names::kAriaValuemaxAttr);
}
-float AccessibleNode::valueMax(bool& is_null) const {
- return GetProperty(element_, AOMFloatProperty::kValueMax, is_null);
-}
-
-void AccessibleNode::setValueMax(float value_max, bool is_null) {
- SetFloatProperty(AOMFloatProperty::kValueMax, value_max, is_null);
- NotifyAttributeChanged(html_names::kAriaValuemaxAttr);
-}
-
base::Optional<float> AccessibleNode::valueMin() const {
return GetProperty(element_, AOMFloatProperty::kValueMin);
}
@@ -1194,15 +907,6 @@ void AccessibleNode::setValueMin(base::Optional<float> value) {
NotifyAttributeChanged(html_names::kAriaValueminAttr);
}
-float AccessibleNode::valueMin(bool& is_null) const {
- return GetProperty(element_, AOMFloatProperty::kValueMin, is_null);
-}
-
-void AccessibleNode::setValueMin(float value_min, bool is_null) {
- SetFloatProperty(AOMFloatProperty::kValueMin, value_min, is_null);
- NotifyAttributeChanged(html_names::kAriaValueminAttr);
-}
-
base::Optional<float> AccessibleNode::valueNow() const {
return GetProperty(element_, AOMFloatProperty::kValueNow);
}
@@ -1212,15 +916,6 @@ void AccessibleNode::setValueNow(base::Optional<float> value) {
NotifyAttributeChanged(html_names::kAriaValuenowAttr);
}
-float AccessibleNode::valueNow(bool& is_null) const {
- return GetProperty(element_, AOMFloatProperty::kValueNow, is_null);
-}
-
-void AccessibleNode::setValueNow(float value_now, bool is_null) {
- SetFloatProperty(AOMFloatProperty::kValueNow, value_now, is_null);
- NotifyAttributeChanged(html_names::kAriaValuenowAttr);
-}
-
AtomicString AccessibleNode::valueText() const {
return GetProperty(AOMStringProperty::kValueText);
}
@@ -1409,49 +1104,6 @@ void AccessibleNode::SetFloatProperty(AOMFloatProperty property,
SetProperty(property, value, float_properties_);
}
-template <typename P, typename T>
-static void SetProperty(P property,
- T value,
- bool is_null,
- Vector<std::pair<P, T>>& properties) {
- for (wtf_size_t i = 0; i < properties.size(); i++) {
- auto& item = properties[i];
- if (item.first == property) {
- if (is_null)
- properties.EraseAt(i);
- else
- item.second = value;
- return;
- }
- }
-
- properties.push_back(std::make_pair(property, value));
-}
-
-void AccessibleNode::SetBooleanProperty(AOMBooleanProperty property,
- bool value,
- bool is_null) {
- SetProperty(property, value, is_null, boolean_properties_);
-}
-
-void AccessibleNode::SetIntProperty(AOMIntProperty property,
- int32_t value,
- bool is_null) {
- SetProperty(property, value, is_null, int_properties_);
-}
-
-void AccessibleNode::SetUIntProperty(AOMUIntProperty property,
- uint32_t value,
- bool is_null) {
- SetProperty(property, value, is_null, uint_properties_);
-}
-
-void AccessibleNode::SetFloatProperty(AOMFloatProperty property,
- float value,
- bool is_null) {
- SetProperty(property, value, is_null, float_properties_);
-}
-
void AccessibleNode::OnRelationListChanged(AOMRelationListProperty property) {
NotifyAttributeChanged(GetCorrespondingARIAAttribute(property));
}
diff --git a/chromium/third_party/blink/renderer/core/aom/accessible_node.h b/chromium/third_party/blink/renderer/core/aom/accessible_node.h
index 840b41f90b3..0ceaa645a36 100644
--- a/chromium/third_party/blink/renderer/core/aom/accessible_node.h
+++ b/chromium/third_party/blink/renderer/core/aom/accessible_node.h
@@ -142,8 +142,6 @@ class CORE_EXPORT AccessibleNode : public EventTargetWithInlineData {
// Returns the given boolean property.
base::Optional<bool> GetProperty(AOMBooleanProperty) const;
- // TODO(crbug.com/1060971): Remove |is_null| version.
- bool GetProperty(AOMBooleanProperty, bool& is_null) const; // DEPRECATED
// Returns the value of the given property if the
// Element has an AccessibleNode. Sets |isNull| if the property and
@@ -151,10 +149,6 @@ class CORE_EXPORT AccessibleNode : public EventTargetWithInlineData {
static base::Optional<int32_t> GetProperty(Element*, AOMIntProperty);
static base::Optional<uint32_t> GetProperty(Element*, AOMUIntProperty);
static base::Optional<float> GetProperty(Element*, AOMFloatProperty);
- // TODO(crbug.com/1060971): Remove |is_null| version.
- static float GetProperty(Element*, AOMFloatProperty, bool& is_null);
- static int32_t GetProperty(Element*, AOMIntProperty, bool& is_null);
- static uint32_t GetProperty(Element*, AOMUIntProperty, bool& is_null);
// Does the attribute value match one of the ARIA undefined patterns for
// boolean and token properties?
@@ -209,39 +203,24 @@ class CORE_EXPORT AccessibleNode : public EventTargetWithInlineData {
base::Optional<bool> atomic() const;
void setAtomic(base::Optional<bool>);
- // TODO(crbug.com/1060971): Remove |is_null| version.
- bool atomic(bool& is_null) const; // DEPRECATED
- void setAtomic(bool, bool is_null); // DEPRECATED
AtomicString autocomplete() const;
void setAutocomplete(const AtomicString&);
base::Optional<bool> busy() const;
void setBusy(base::Optional<bool>);
- // TODO(crbug.com/1060971): Remove |is_null| version.
- bool busy(bool& is_null) const; // DEPRECATED
- void setBusy(bool, bool is_null); // DEPRECATED
AtomicString checked() const;
void setChecked(const AtomicString&);
base::Optional<int32_t> colCount() const;
void setColCount(base::Optional<int32_t>);
- // TODO(crbug.com/1060971): Remove |is_null| version.
- int32_t colCount(bool& is_null) const; // DEPRECATED
- void setColCount(int32_t, bool is_null); // DEPRECATED
base::Optional<uint32_t> colIndex() const;
void setColIndex(base::Optional<uint32_t>);
- // TODO(crbug.com/1060971): Remove |is_null| version.
- uint32_t colIndex(bool& is_null) const; // DEPRECATED
- void setColIndex(uint32_t, bool is_null); // DEPRECATED
base::Optional<uint32_t> colSpan() const;
void setColSpan(base::Optional<uint32_t>);
- // TODO(crbug.com/1060971): Remove |is_null| version.
- uint32_t colSpan(bool& is_null) const; // DEPRECATED
- void setColSpan(uint32_t, bool is_null); // DEPRECATED
AccessibleNodeList* controls() const;
void setControls(AccessibleNodeList*);
@@ -260,18 +239,12 @@ class CORE_EXPORT AccessibleNode : public EventTargetWithInlineData {
base::Optional<bool> disabled() const;
void setDisabled(base::Optional<bool>);
- // TODO(crbug.com/1060971): Remove |is_null| version.
- bool disabled(bool& is_null) const; // DEPRECATED
- void setDisabled(bool, bool is_null); // DEPRECATED
AccessibleNode* errorMessage() const;
void setErrorMessage(AccessibleNode*);
base::Optional<bool> expanded() const;
void setExpanded(base::Optional<bool>);
- // TODO(crbug.com/1060971): Remove |is_null| version.
- bool expanded(bool& is_null) const; // DEPRECATED
- void setExpanded(bool, bool is_null); // DEPRECATED
AccessibleNodeList* flowTo() const;
void setFlowTo(AccessibleNodeList*);
@@ -281,9 +254,6 @@ class CORE_EXPORT AccessibleNode : public EventTargetWithInlineData {
base::Optional<bool> hidden() const;
void setHidden(base::Optional<bool>);
- // TODO(crbug.com/1060971): Remove |is_null| version.
- bool hidden(bool& is_null) const; // DEPRECATED
- void setHidden(bool, bool is_null); // DEPRECATED
AtomicString invalid() const;
void setInvalid(const AtomicString&);
@@ -299,30 +269,18 @@ class CORE_EXPORT AccessibleNode : public EventTargetWithInlineData {
base::Optional<uint32_t> level() const;
void setLevel(base::Optional<uint32_t>);
- // TODO(crbug.com/1060971): Remove |is_null| version.
- uint32_t level(bool& is_null) const; // DEPRECATED
- void setLevel(uint32_t, bool is_null); // DEPRECATED
AtomicString live() const;
void setLive(const AtomicString&);
base::Optional<bool> modal() const;
void setModal(base::Optional<bool>);
- // TODO(crbug.com/1060971): Remove |is_null| version.
- bool modal(bool& is_null) const; // DEPRECATED
- void setModal(bool, bool is_null); // DEPRECATED
base::Optional<bool> multiline() const;
void setMultiline(base::Optional<bool>);
- // TODO(crbug.com/1060971): Remove |is_null| version.
- bool multiline(bool& is_null) const; // DEPRECATED
- void setMultiline(bool, bool is_null); // DEPRECATED
base::Optional<bool> multiselectable() const;
void setMultiselectable(base::Optional<bool>);
- // TODO(crbug.com/1060971): Remove |is_null| version.
- bool multiselectable(bool& is_null) const; // DEPRECATED
- void setMultiselectable(bool, bool is_null); // DEPRECATED
AtomicString orientation() const;
void setOrientation(const AtomicString&);
@@ -335,27 +293,18 @@ class CORE_EXPORT AccessibleNode : public EventTargetWithInlineData {
base::Optional<uint32_t> posInSet() const;
void setPosInSet(base::Optional<uint32_t>);
- // TODO(crbug.com/1060971): Remove |is_null| version.
- uint32_t posInSet(bool& is_null) const; // DEPRECATED
- void setPosInSet(uint32_t, bool is_null); // DEPRECATED
AtomicString pressed() const;
void setPressed(const AtomicString&);
base::Optional<bool> readOnly() const;
void setReadOnly(base::Optional<bool>);
- // TODO(crbug.com/1060971): Remove |is_null| version.
- bool readOnly(bool& is_null) const; // DEPRECATED
- void setReadOnly(bool, bool is_null); // DEPRECATED
AtomicString relevant() const;
void setRelevant(const AtomicString&);
base::Optional<bool> required() const;
void setRequired(base::Optional<bool>);
- // TODO(crbug.com/1060971): Remove |is_null| version.
- bool required(bool& is_null) const; // DEPRECATED
- void setRequired(bool, bool is_null); // DEPRECATED
AtomicString role() const;
void setRole(const AtomicString&);
@@ -365,54 +314,30 @@ class CORE_EXPORT AccessibleNode : public EventTargetWithInlineData {
base::Optional<int32_t> rowCount() const;
void setRowCount(base::Optional<int32_t>);
- // TODO(crbug.com/1060971): Remove |is_null| version.
- int32_t rowCount(bool& is_null) const; // DEPRECATED
- void setRowCount(int32_t, bool is_null); // DEPRECATED
base::Optional<uint32_t> rowIndex() const;
void setRowIndex(base::Optional<uint32_t>);
- // TODO(crbug.com/1060971): Remove |is_null| version.
- uint32_t rowIndex(bool& is_null) const; // DEPRECATED
- void setRowIndex(uint32_t, bool is_null); // DEPRECATED
base::Optional<uint32_t> rowSpan() const;
void setRowSpan(base::Optional<uint32_t>);
- // TODO(crbug.com/1060971): Remove |is_null| version.
- uint32_t rowSpan(bool& is_null) const; // DEPRECATED
- void setRowSpan(uint32_t, bool is_null); // DEPRECATED
base::Optional<bool> selected() const;
void setSelected(base::Optional<bool>);
- // TODO(crbug.com/1060971): Remove |is_null| version.
- bool selected(bool& is_null) const; // DEPRECATED
- void setSelected(bool, bool is_null); // DEPRECATED
base::Optional<int32_t> setSize() const;
void setSetSize(base::Optional<int32_t>);
- // TODO(crbug.com/1060971): Remove |is_null| version.
- int32_t setSize(bool& is_null) const; // DEPRECATED
- void setSetSize(int32_t, bool is_null); // DEPRECATED
AtomicString sort() const;
void setSort(const AtomicString&);
base::Optional<float> valueMax() const;
void setValueMax(base::Optional<float>);
- // TODO(crbug.com/1060971): Remove |is_null| version.
- float valueMax(bool& is_null) const; // DEPRECATED
- void setValueMax(float, bool is_null); // DEPRECATED
base::Optional<float> valueMin() const;
void setValueMin(base::Optional<float>);
- // TODO(crbug.com/1060971): Remove |is_null| version.
- float valueMin(bool& is_null) const; // DEPRECATED
- void setValueMin(float, bool is_null); // DEPRECATED
base::Optional<float> valueNow() const;
void setValueNow(base::Optional<float>);
- // TODO(crbug.com/1060971): Remove |is_null| version.
- float valueNow(bool& is_null) const; // DEPRECATED
- void setValueNow(float, bool is_null); // DEPRECATED
AtomicString valueText() const;
void setValueText(const AtomicString&);
@@ -453,19 +378,6 @@ class CORE_EXPORT AccessibleNode : public EventTargetWithInlineData {
void SetIntProperty(AOMIntProperty, base::Optional<int32_t> value);
void SetUIntProperty(AOMUIntProperty, base::Optional<uint32_t> value);
void SetFloatProperty(AOMFloatProperty, base::Optional<float> value);
- // TODO(crbug.com/1060971): Remove |is_null| version.
- void SetBooleanProperty(AOMBooleanProperty,
- bool value,
- bool is_null); // DEPRECATED
- void SetFloatProperty(AOMFloatProperty,
- float value,
- bool is_null); // DEPRECATED
- void SetUIntProperty(AOMUIntProperty,
- uint32_t value,
- bool is_null); // DEPRECATED
- void SetIntProperty(AOMIntProperty,
- int32_t value,
- bool is_null); // DEPRECATED
void NotifyAttributeChanged(const blink::QualifiedName&);
AXObjectCache* GetAXObjectCache();
diff --git a/chromium/third_party/blink/renderer/core/aom/accessible_node.idl b/chromium/third_party/blink/renderer/core/aom/accessible_node.idl
index b8e78529c4b..c9a9c5bc288 100644
--- a/chromium/third_party/blink/renderer/core/aom/accessible_node.idl
+++ b/chromium/third_party/blink/renderer/core/aom/accessible_node.idl
@@ -6,6 +6,7 @@
// Explainer: https://github.com/WICG/aom/blob/master/explainer.md
// Spec: https://wicg.github.io/aom/spec/
[
+ Exposed=Window,
RuntimeEnabled=AccessibilityObjectModel
] interface AccessibleNode : EventTarget {
[CallWith=Document] constructor();
diff --git a/chromium/third_party/blink/renderer/core/aom/accessible_node_list.idl b/chromium/third_party/blink/renderer/core/aom/accessible_node_list.idl
index 68573677e95..718ded68e9f 100644
--- a/chromium/third_party/blink/renderer/core/aom/accessible_node_list.idl
+++ b/chromium/third_party/blink/renderer/core/aom/accessible_node_list.idl
@@ -6,6 +6,7 @@
// Explainer: https://github.com/WICG/aom/blob/master/explainer.md
// Spec: https://wicg.github.io/aom/spec/
[
+ Exposed=Window,
RuntimeEnabled=AccessibilityObjectModel
] interface AccessibleNodeList {
constructor(optional sequence<AccessibleNode> nodes = []);
diff --git a/chromium/third_party/blink/renderer/core/aom/computed_accessible_node.cc b/chromium/third_party/blink/renderer/core/aom/computed_accessible_node.cc
index e6ea86dd66e..e62cbe358ba 100644
--- a/chromium/third_party/blink/renderer/core/aom/computed_accessible_node.cc
+++ b/chromium/third_party/blink/renderer/core/aom/computed_accessible_node.cc
@@ -202,10 +202,6 @@ base::Optional<float> ComputedAccessibleNode::valueNow() const {
return GetFloatAttribute(WebAOMFloatAttribute::AOM_ATTR_VALUE_NOW);
}
-bool ComputedAccessibleNode::atomic(bool& is_null) const {
- return GetBoolAttribute(WebAOMBoolAttribute::AOM_ATTR_ATOMIC, is_null);
-}
-
ScriptPromise ComputedAccessibleNode::ensureUpToDate(
ScriptState* script_state) {
AXObjectCache* cache = document_->ExistingAXObjectCache();
@@ -218,46 +214,6 @@ ScriptPromise ComputedAccessibleNode::ensureUpToDate(
return promise;
}
-bool ComputedAccessibleNode::busy(bool& is_null) const {
- return GetBoolAttribute(WebAOMBoolAttribute::AOM_ATTR_BUSY, is_null);
-}
-
-bool ComputedAccessibleNode::disabled(bool& is_null) const {
- return GetBoolAttribute(WebAOMBoolAttribute::AOM_ATTR_DISABLED, is_null);
-}
-
-bool ComputedAccessibleNode::expanded(bool& is_null) const {
- return GetBoolAttribute(WebAOMBoolAttribute::AOM_ATTR_EXPANDED, is_null);
-}
-
-bool ComputedAccessibleNode::modal(bool& is_null) const {
- return GetBoolAttribute(WebAOMBoolAttribute::AOM_ATTR_MODAL, is_null);
-}
-
-bool ComputedAccessibleNode::readOnly(bool& is_null) const {
- return GetBoolAttribute(WebAOMBoolAttribute::AOM_ATTR_READONLY, is_null);
-}
-
-bool ComputedAccessibleNode::multiline(bool& is_null) const {
- return GetBoolAttribute(blink::WebAOMBoolAttribute::AOM_ATTR_MULTILINE,
- is_null);
-}
-
-bool ComputedAccessibleNode::multiselectable(bool& is_null) const {
- return GetBoolAttribute(blink::WebAOMBoolAttribute::AOM_ATTR_MULTISELECTABLE,
- is_null);
-}
-
-bool ComputedAccessibleNode::required(bool& is_null) const {
- return GetBoolAttribute(blink::WebAOMBoolAttribute::AOM_ATTR_REQUIRED,
- is_null);
-}
-
-bool ComputedAccessibleNode::selected(bool& is_null) const {
- return GetBoolAttribute(blink::WebAOMBoolAttribute::AOM_ATTR_SELECTED,
- is_null);
-}
-
const String ComputedAccessibleNode::autocomplete() const {
return GetStringAttribute(WebAOMStringAttribute::AOM_ATTR_AUTOCOMPLETE);
}
@@ -296,55 +252,6 @@ const String ComputedAccessibleNode::valueText() const {
return GetStringAttribute(WebAOMStringAttribute::AOM_ATTR_VALUE_TEXT);
}
-int32_t ComputedAccessibleNode::colCount(bool& is_null) const {
- return GetIntAttribute(WebAOMIntAttribute::AOM_ATTR_COLUMN_COUNT, is_null);
-}
-
-int32_t ComputedAccessibleNode::colIndex(bool& is_null) const {
- return GetIntAttribute(WebAOMIntAttribute::AOM_ATTR_COLUMN_INDEX, is_null);
-}
-
-int32_t ComputedAccessibleNode::colSpan(bool& is_null) const {
- return GetIntAttribute(WebAOMIntAttribute::AOM_ATTR_COLUMN_SPAN, is_null);
-}
-
-int32_t ComputedAccessibleNode::level(bool& is_null) const {
- return GetIntAttribute(WebAOMIntAttribute::AOM_ATTR_HIERARCHICAL_LEVEL,
- is_null);
-}
-
-int32_t ComputedAccessibleNode::posInSet(bool& is_null) const {
- return GetIntAttribute(WebAOMIntAttribute::AOM_ATTR_POS_IN_SET, is_null);
-}
-
-int32_t ComputedAccessibleNode::rowCount(bool& is_null) const {
- return GetIntAttribute(WebAOMIntAttribute::AOM_ATTR_ROW_COUNT, is_null);
-}
-
-int32_t ComputedAccessibleNode::rowIndex(bool& is_null) const {
- return GetIntAttribute(WebAOMIntAttribute::AOM_ATTR_ROW_INDEX, is_null);
-}
-
-int32_t ComputedAccessibleNode::rowSpan(bool& is_null) const {
- return GetIntAttribute(WebAOMIntAttribute::AOM_ATTR_ROW_SPAN, is_null);
-}
-
-int32_t ComputedAccessibleNode::setSize(bool& is_null) const {
- return GetIntAttribute(WebAOMIntAttribute::AOM_ATTR_SET_SIZE, is_null);
-}
-
-float ComputedAccessibleNode::valueMax(bool& is_null) const {
- return GetFloatAttribute(WebAOMFloatAttribute::AOM_ATTR_VALUE_MAX, is_null);
-}
-
-float ComputedAccessibleNode::valueMin(bool& is_null) const {
- return GetFloatAttribute(WebAOMFloatAttribute::AOM_ATTR_VALUE_MIN, is_null);
-}
-
-float ComputedAccessibleNode::valueNow(bool& is_null) const {
- return GetFloatAttribute(WebAOMFloatAttribute::AOM_ATTR_VALUE_NOW, is_null);
-}
-
ComputedAccessibleNode* ComputedAccessibleNode::parent() const {
int32_t parent_ax_id;
if (!tree_->GetParentIdForAXNode(ax_id_, &parent_ax_id)) {
@@ -409,36 +316,6 @@ base::Optional<float> ComputedAccessibleNode::GetFloatAttribute(
return base::nullopt;
}
-bool ComputedAccessibleNode::GetBoolAttribute(WebAOMBoolAttribute attr,
- bool& is_null) const {
- bool out;
- is_null = true;
- if (tree_->GetBoolAttributeForAXNode(ax_id_, attr, &out)) {
- is_null = false;
- }
- return out;
-}
-
-float ComputedAccessibleNode::GetFloatAttribute(WebAOMFloatAttribute attr,
- bool& is_null) const {
- float out;
- is_null = true;
- if (tree_->GetFloatAttributeForAXNode(ax_id_, attr, &out)) {
- is_null = false;
- }
- return out;
-}
-
-int32_t ComputedAccessibleNode::GetIntAttribute(WebAOMIntAttribute attr,
- bool& is_null) const {
- int32_t out = 0;
- is_null = true;
- if (tree_->GetIntAttributeForAXNode(ax_id_, attr, &out)) {
- is_null = false;
- }
- return out;
-}
-
const String ComputedAccessibleNode::GetStringAttribute(
WebAOMStringAttribute attr) const {
WebString out;
diff --git a/chromium/third_party/blink/renderer/core/aom/computed_accessible_node.h b/chromium/third_party/blink/renderer/core/aom/computed_accessible_node.h
index 027d68e72ff..35b87ee82e2 100644
--- a/chromium/third_party/blink/renderer/core/aom/computed_accessible_node.h
+++ b/chromium/third_party/blink/renderer/core/aom/computed_accessible_node.h
@@ -78,32 +78,6 @@ class ComputedAccessibleNode : public ScriptWrappable {
base::Optional<float> valueMin() const;
base::Optional<float> valueNow() const;
- // TODO(crbug.com/1060971): Remove |is_null| version.
- bool atomic(bool& is_null) const; // DEPRECATED
- bool busy(bool& is_null) const; // DEPRECATED
- bool disabled(bool& is_null) const; // DEPRECATED
- bool readOnly(bool& is_null) const; // DEPRECATED
- bool expanded(bool& is_null) const; // DEPRECATED
- bool modal(bool& is_null) const; // DEPRECATED
- bool multiline(bool& is_null) const; // DEPRECATED
- bool multiselectable(bool& is_null) const; // DEPRECATED
- bool required(bool& is_null) const; // DEPRECATED
- bool selected(bool& is_null) const; // DEPRECATED
-
- int32_t colCount(bool& is_null) const; // DEPRECATED
- int32_t colIndex(bool& is_null) const; // DEPRECATED
- int32_t colSpan(bool& is_null) const; // DEPRECATED
- int32_t level(bool& is_null) const; // DEPRECATED
- int32_t posInSet(bool& is_null) const; // DEPRECATED
- int32_t rowCount(bool& is_null) const; // DEPRECATED
- int32_t rowIndex(bool& is_null) const; // DEPRECATED
- int32_t rowSpan(bool& is_null) const; // DEPRECATED
- int32_t setSize(bool& is_null) const; // DEPRECATED
-
- float valueMax(bool& is_null) const; // DEPRECATED
- float valueMin(bool& is_null) const; // DEPRECATED
- float valueNow(bool& is_null) const; // DEPRECATED
-
const String autocomplete() const;
const String checked() const;
const String keyShortcuts() const;
@@ -125,10 +99,6 @@ class ComputedAccessibleNode : public ScriptWrappable {
base::Optional<bool> GetBoolAttribute(WebAOMBoolAttribute) const;
base::Optional<int32_t> GetIntAttribute(WebAOMIntAttribute) const;
base::Optional<float> GetFloatAttribute(WebAOMFloatAttribute) const;
- // TODO(crbug.com/1060971): Remove |is_null| version.
- bool GetBoolAttribute(WebAOMBoolAttribute, bool& is_null) const;
- int32_t GetIntAttribute(WebAOMIntAttribute, bool& is_null) const;
- float GetFloatAttribute(WebAOMFloatAttribute, bool& is_null) const;
const String GetStringAttribute(WebAOMStringAttribute) const;
AXID ax_id_;
diff --git a/chromium/third_party/blink/renderer/core/aom/computed_accessible_node.idl b/chromium/third_party/blink/renderer/core/aom/computed_accessible_node.idl
index 803e1c54b83..0765e606954 100644
--- a/chromium/third_party/blink/renderer/core/aom/computed_accessible_node.idl
+++ b/chromium/third_party/blink/renderer/core/aom/computed_accessible_node.idl
@@ -6,6 +6,7 @@
// Explainer: https://github.com/WICG/aom/blob/master/explainer.md
// Spec: https://wicg.github.io/aom/spec/
[
+ Exposed=Window,
RuntimeEnabled=AccessibilityObjectModel
] interface ComputedAccessibleNode {
diff --git a/chromium/third_party/blink/renderer/core/clipboard/raw_system_clipboard.cc b/chromium/third_party/blink/renderer/core/clipboard/raw_system_clipboard.cc
index 0e1d95a0252..4f08821b9d0 100644
--- a/chromium/third_party/blink/renderer/core/clipboard/raw_system_clipboard.cc
+++ b/chromium/third_party/blink/renderer/core/clipboard/raw_system_clipboard.cc
@@ -4,14 +4,30 @@
#include "third_party/blink/renderer/core/clipboard/raw_system_clipboard.h"
+#include "mojo/public/cpp/base/big_buffer.h"
#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
+#include "third_party/blink/public/mojom/clipboard/raw_clipboard.mojom-blink.h"
namespace blink {
-RawSystemClipboard::RawSystemClipboard(LocalFrame* frame) {
+RawSystemClipboard::RawSystemClipboard(LocalFrame* frame)
+ : clipboard_(frame->DomWindow()) {
frame->GetBrowserInterfaceBroker().GetInterface(
- clipboard_.BindNewPipeAndPassReceiver());
+ clipboard_.BindNewPipeAndPassReceiver(
+ frame->GetTaskRunner(TaskType::kUserInteraction)));
+}
+
+void RawSystemClipboard::ReadAvailableFormatNames(
+ mojom::blink::RawClipboardHost::ReadAvailableFormatNamesCallback callback) {
+ clipboard_->ReadAvailableFormatNames(std::move(callback));
+}
+
+void RawSystemClipboard::Read(
+ const String& type,
+ mojom::blink::RawClipboardHost::ReadCallback callback) {
+ clipboard_->Read(type, std::move(callback));
}
void RawSystemClipboard::Write(const String& type, mojo_base::BigBuffer data) {
@@ -22,4 +38,8 @@ void RawSystemClipboard::CommitWrite() {
clipboard_->CommitWrite();
}
+void RawSystemClipboard::Trace(Visitor* visitor) {
+ visitor->Trace(clipboard_);
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/clipboard/raw_system_clipboard.h b/chromium/third_party/blink/renderer/core/clipboard/raw_system_clipboard.h
index eba190f4673..d65c89f3c43 100644
--- a/chromium/third_party/blink/renderer/core/clipboard/raw_system_clipboard.h
+++ b/chromium/third_party/blink/renderer/core/clipboard/raw_system_clipboard.h
@@ -5,10 +5,11 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CLIPBOARD_RAW_SYSTEM_CLIPBOARD_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_CLIPBOARD_RAW_SYSTEM_CLIPBOARD_H_
-#include "mojo/public/cpp/bindings/remote.h" // For mojo::Remote<T>
#include "third_party/blink/public/mojom/clipboard/raw_clipboard.mojom-blink.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
+#include "third_party/blink/renderer/platform/mojo/heap_mojo_remote.h"
+#include "third_party/blink/renderer/platform/mojo/heap_mojo_wrapper_mode.h"
// RawSystemClipboard:
// - is a singleton.
@@ -28,12 +29,22 @@ class CORE_EXPORT RawSystemClipboard final
RawSystemClipboard(const RawSystemClipboard&) = delete;
RawSystemClipboard& operator=(const RawSystemClipboard&) = delete;
+ void ReadAvailableFormatNames(
+ mojom::blink::RawClipboardHost::ReadAvailableFormatNamesCallback
+ callback);
+
+ void Read(const String& type,
+ mojom::blink::RawClipboardHost::ReadCallback callback);
+
void Write(const String& type, mojo_base::BigBuffer data);
+
void CommitWrite();
- void Trace(Visitor*) {}
+ void Trace(Visitor*);
private:
- mojo::Remote<mojom::blink::RawClipboardHost> clipboard_;
+ HeapMojoRemote<mojom::blink::RawClipboardHost,
+ HeapMojoWrapperMode::kWithoutContextObserver>
+ clipboard_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/clipboard/system_clipboard.cc b/chromium/third_party/blink/renderer/core/clipboard/system_clipboard.cc
index 905739a4b40..cecf0515695 100644
--- a/chromium/third_party/blink/renderer/core/clipboard/system_clipboard.cc
+++ b/chromium/third_party/blink/renderer/core/clipboard/system_clipboard.cc
@@ -15,6 +15,7 @@
#include "third_party/blink/renderer/core/clipboard/clipboard_mime_types.h"
#include "third_party/blink/renderer/core/clipboard/clipboard_utilities.h"
#include "third_party/blink/renderer/core/clipboard/data_object.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/platform/graphics/image.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
@@ -31,9 +32,11 @@ String NonNullString(const String& string) {
} // namespace
-SystemClipboard::SystemClipboard(LocalFrame* frame) {
+SystemClipboard::SystemClipboard(LocalFrame* frame)
+ : clipboard_(frame->DomWindow()) {
frame->GetBrowserInterfaceBroker().GetInterface(
- clipboard_.BindNewPipeAndPassReceiver());
+ clipboard_.BindNewPipeAndPassReceiver(
+ frame->GetTaskRunner(TaskType::kUserInteraction)));
}
bool SystemClipboard::IsSelectionMode() const {
@@ -75,8 +78,7 @@ Vector<String> SystemClipboard::ReadAvailableTypes() {
if (!IsValidBufferType(buffer_))
return {};
Vector<String> types;
- bool contains_filenames; // Unused argument.
- clipboard_->ReadAvailableTypes(buffer_, &types, &contains_filenames);
+ clipboard_->ReadAvailableTypes(buffer_, &types);
return types;
}
@@ -93,7 +95,7 @@ String SystemClipboard::ReadPlainText(mojom::ClipboardBuffer buffer) {
}
void SystemClipboard::WritePlainText(const String& plain_text,
- SmartReplaceOption) {
+ SmartReplaceOption) {
// TODO(https://crbug.com/106449): add support for smart replace, which is
// currently under-specified.
String text = plain_text;
@@ -159,8 +161,8 @@ String SystemClipboard::ReadImageAsImageMarkup(
}
void SystemClipboard::WriteImageWithTag(Image* image,
- const KURL& url,
- const String& title) {
+ const KURL& url,
+ const String& title) {
DCHECK(image);
PaintImage paint_image = image->PaintImageForCurrentFrame();
@@ -233,6 +235,10 @@ void SystemClipboard::CommitWrite() {
clipboard_->CommitWrite();
}
+void SystemClipboard::Trace(Visitor* visitor) {
+ visitor->Trace(clipboard_);
+}
+
bool SystemClipboard::IsValidBufferType(mojom::ClipboardBuffer buffer) {
switch (buffer) {
case mojom::ClipboardBuffer::kStandard:
diff --git a/chromium/third_party/blink/renderer/core/clipboard/system_clipboard.h b/chromium/third_party/blink/renderer/core/clipboard/system_clipboard.h
index 71a11cb6ffa..dfea6b765f6 100644
--- a/chromium/third_party/blink/renderer/core/clipboard/system_clipboard.h
+++ b/chromium/third_party/blink/renderer/core/clipboard/system_clipboard.h
@@ -5,10 +5,11 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CLIPBOARD_SYSTEM_CLIPBOARD_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_CLIPBOARD_SYSTEM_CLIPBOARD_H_
-#include "mojo/public/cpp/bindings/remote.h"
#include "third_party/blink/public/mojom/clipboard/clipboard.mojom-blink.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
+#include "third_party/blink/renderer/platform/mojo/heap_mojo_remote.h"
+#include "third_party/blink/renderer/platform/mojo/heap_mojo_wrapper_mode.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/text/wtf_string.h"
@@ -72,12 +73,14 @@ class CORE_EXPORT SystemClipboard final
// the OS clipboard.
void CommitWrite();
- void Trace(Visitor*) {}
+ void Trace(Visitor*);
private:
bool IsValidBufferType(mojom::ClipboardBuffer);
- mojo::Remote<mojom::blink::ClipboardHost> clipboard_;
+ HeapMojoRemote<mojom::blink::ClipboardHost,
+ HeapMojoWrapperMode::kWithoutContextObserver>
+ clipboard_;
// In X11, |buffer_| may equal ClipboardBuffer::kStandard or kSelection.
// Outside X11, |buffer_| always equals ClipboardBuffer::kStandard.
mojom::ClipboardBuffer buffer_ = mojom::ClipboardBuffer::kStandard;
diff --git a/chromium/third_party/blink/renderer/core/content_capture/content_capture_task.cc b/chromium/third_party/blink/renderer/core/content_capture/content_capture_task.cc
index 0d9b43bf30d..d637d2edade 100644
--- a/chromium/third_party/blink/renderer/core/content_capture/content_capture_task.cc
+++ b/chromium/third_party/blink/renderer/core/content_capture/content_capture_task.cc
@@ -187,7 +187,6 @@ bool ContentCaptureTask::RunInternal() {
break;
case TaskState::kProcessCurrentSession:
return ProcessSession();
- break;
default:
return true;
}
diff --git a/chromium/third_party/blink/renderer/core/content_capture/content_capture_test.cc b/chromium/third_party/blink/renderer/core/content_capture/content_capture_test.cc
index e0577afd83f..31ad8cd0501 100644
--- a/chromium/third_party/blink/renderer/core/content_capture/content_capture_test.cc
+++ b/chromium/third_party/blink/renderer/core/content_capture/content_capture_test.cc
@@ -438,7 +438,7 @@ TEST_F(ContentCaptureTest, TaskHistogramReporter) {
// This performs gc for all DocumentSession, flushes the existing
// SentContentCount and give a clean baseline for histograms.
// We are not sure if it always work, maybe still be the source of flaky.
- V8GCController::CollectAllGarbageForTesting(v8::Isolate::GetCurrent());
+ ThreadState::Current()->CollectAllGarbageForTesting();
base::HistogramTester histograms;
// The task stops before captures content.
@@ -515,7 +515,7 @@ TEST_F(ContentCaptureTest, TaskHistogramReporter) {
ContentCaptureTaskHistogramReporter::kSentContentCount, 0u);
GetContentCaptureTask()->ClearDocumentSessionsForTesting();
- V8GCController::CollectAllGarbageForTesting(v8::Isolate::GetCurrent());
+ ThreadState::Current()->CollectAllGarbageForTesting();
histograms.ExpectTotalCount(
ContentCaptureTaskHistogramReporter::kCaptureContentTime, 2u);
histograms.ExpectTotalCount(
diff --git a/chromium/third_party/blink/renderer/core/core_idl_files.gni b/chromium/third_party/blink/renderer/core/core_idl_files.gni
index 31ae21cfbd2..be73ad34204 100644
--- a/chromium/third_party/blink/renderer/core/core_idl_files.gni
+++ b/chromium/third_party/blink/renderer/core/core_idl_files.gni
@@ -65,7 +65,6 @@ core_idl_files =
"css/css_style_sheet.idl",
"css/css_supports_rule.idl",
"css/css_property_rule.idl",
- "css/css_viewport_rule.idl",
"css/font_face.idl",
"css/font_face_set.idl",
"css/font_face_set_load_event.idl",
@@ -174,7 +173,6 @@ core_idl_files =
"events/ui_event.idl",
"events/wheel_event.idl",
"feature_policy/feature_policy.idl",
- "fetch/body.idl",
"fetch/headers.idl",
"fetch/request.idl",
"fetch/response.idl",
@@ -192,6 +190,7 @@ core_idl_files =
"frame/fragment_directive.idl",
"frame/history.idl",
"frame/intervention_report_body.idl",
+ "frame/is_input_pending_options.idl",
"frame/location.idl",
"frame/navigator_ua_data.idl",
"frame/report.idl",
@@ -312,7 +311,6 @@ core_idl_files =
"inspector/inspector_overlay_host.idl",
"intersection_observer/intersection_observer.idl",
"intersection_observer/intersection_observer_entry.idl",
- "invisible_dom/activate_invisible_event.idl",
"layout/ng/custom/intrinsic_sizes.idl",
"layout/ng/custom/layout_constraints.idl",
"layout/ng/custom/layout_edges.idl",
@@ -443,8 +441,10 @@ core_idl_files =
"svg/svg_unit_types.idl",
"svg/svg_use_element.idl",
"svg/svg_view_element.idl",
+ "timing/event_counts.idl",
"timing/largest_contentful_paint.idl",
"timing/layout_shift.idl",
+ "timing/layout_shift_attribution.idl",
"timing/memory_info.idl",
"timing/performance.idl",
"timing/performance_element_timing.idl",
@@ -532,10 +532,10 @@ core_dependency_idl_files =
get_path_info([
"animation/animatable.idl",
"animation/document_animation.idl",
- "css/font_face_source.idl",
- "css/property_registration.idl",
"css/cssom/css_unit_values.idl",
"css/cssom/element_computed_style_map.idl",
+ "css/font_face_source.idl",
+ "css/property_registration.idl",
"dom/accessibility_role.idl",
"dom/aria_attributes.idl",
"dom/aria_relationship_attributes.idl",
@@ -547,6 +547,7 @@ core_dependency_idl_files =
"dom/non_element_parent_node.idl",
"dom/parent_node.idl",
"events/navigator_events.idl",
+ "fetch/body.idl",
"fetch/window_fetch.idl",
"fetch/worker_fetch.idl",
"fileapi/url_file_api.idl",
@@ -612,6 +613,7 @@ core_dictionary_idl_files =
"animation/keyframe_animation_options.idl",
"animation/keyframe_effect_options.idl",
"animation/optional_effect_timing.idl",
+ "animation/scroll_timeline_element_based_offset.idl",
"animation/scroll_timeline_options.idl",
"css/css_style_sheet_init.idl",
"css/font_face_descriptors.idl",
@@ -623,6 +625,7 @@ core_dictionary_idl_files =
"dom/element_creation_options.idl",
"dom/element_definition_options.idl",
"dom/element_registration_options.idl",
+ "dom/get_inner_html_options.idl",
"dom/get_root_node_options.idl",
"dom/idle_request_options.idl",
"dom/mutation_observer_init.idl",
@@ -665,6 +668,7 @@ core_dictionary_idl_files =
"fetch/trust_token.idl",
"fileapi/blob_property_bag.idl",
"fileapi/file_property_bag.idl",
+ "frame/is_input_pending_options_init.idl",
"frame/navigator_ua_brand_version.idl",
"frame/reporting_observer_options.idl",
"frame/scroll_into_view_options.idl",
diff --git a/chromium/third_party/blink/renderer/core/core_initializer.cc b/chromium/third_party/blink/renderer/core/core_initializer.cc
index cb5ad15a22e..04c64c223ab 100644
--- a/chromium/third_party/blink/renderer/core/core_initializer.cc
+++ b/chromium/third_party/blink/renderer/core/core_initializer.cc
@@ -31,6 +31,7 @@
#include "third_party/blink/renderer/core/core_initializer.h"
#include "third_party/blink/public/platform/platform.h"
+#include "third_party/blink/public/web/blink.h"
#include "third_party/blink/renderer/bindings/core/v8/binding_security.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_throw_dom_exception.h"
#include "third_party/blink/renderer/core/css/media_feature_names.h"
@@ -67,6 +68,11 @@ namespace blink {
CoreInitializer* CoreInitializer::instance_ = nullptr;
+// Function defined in third_party/blink/public/web/blink.h.
+void ForceNextWebGLContextCreationToFailForTest() {
+ CoreInitializer::GetInstance().ForceNextWebGLContextCreationToFail();
+}
+
void CoreInitializer::RegisterEventFactory() {
static bool is_registered = false;
if (is_registered)
diff --git a/chromium/third_party/blink/renderer/core/core_initializer.h b/chromium/third_party/blink/renderer/core/core_initializer.h
index 3f6d8de0389..7c4975a9e7e 100644
--- a/chromium/third_party/blink/renderer/core/core_initializer.h
+++ b/chromium/third_party/blink/renderer/core/core_initializer.h
@@ -61,7 +61,6 @@ class WebMediaPlayerClient;
class WebMediaPlayerSource;
class WebRemotePlaybackClient;
class WebViewClient;
-class WorkerGlobalScope;
class CORE_EXPORT CoreInitializer {
USING_FAST_MALLOC(CoreInitializer);
@@ -88,7 +87,6 @@ class CORE_EXPORT CoreInitializer {
virtual void InitLocalFrame(LocalFrame&) const = 0;
// Supplements installed on a frame using ChromeClient
virtual void InstallSupplements(LocalFrame&) const = 0;
- virtual void ProvideLocalFileSystemToWorker(WorkerGlobalScope&) const = 0;
virtual MediaControls* CreateMediaControls(HTMLMediaElement&,
ShadowRoot&) const = 0;
virtual PictureInPictureController* CreatePictureInPictureController(
@@ -125,8 +123,8 @@ class CORE_EXPORT CoreInitializer {
Page* clone_from_page,
const SessionStorageNamespaceId& clone_to_namespace) = 0;
- virtual void DidCommitLoad(LocalFrame&) = 0;
virtual void DidChangeManifest(LocalFrame&) = 0;
+ virtual void NotifyOrientationChanged(LocalFrame&) = 0;
protected:
// CoreInitializer is only instantiated by subclass ModulesInitializer.
diff --git a/chromium/third_party/blink/renderer/core/css/BUILD.gn b/chromium/third_party/blink/renderer/core/css/BUILD.gn
index 183fd3f3789..e65b9bcc1e6 100644
--- a/chromium/third_party/blink/renderer/core/css/BUILD.gn
+++ b/chromium/third_party/blink/renderer/core/css/BUILD.gn
@@ -103,8 +103,8 @@ blink_core_sources("css") {
"css_keyframes_rule.h",
"css_layout_function_value.cc",
"css_layout_function_value.h",
- "css_light_dark_color_pair.cc",
- "css_light_dark_color_pair.h",
+ "css_light_dark_value_pair.cc",
+ "css_light_dark_value_pair.h",
"css_markup.cc",
"css_markup.h",
"css_math_expression_node.cc",
@@ -155,6 +155,8 @@ blink_core_sources("css") {
"css_reflection_direction.h",
"css_resolution_units.h",
"css_resource_fetch_restriction.h",
+ "css_revert_value.cc",
+ "css_revert_value.h",
"css_rule.cc",
"css_rule.h",
"css_rule_list.h",
@@ -206,8 +208,6 @@ blink_core_sources("css") {
"css_variable_data.h",
"css_variable_reference_value.cc",
"css_variable_reference_value.h",
- "css_viewport_rule.cc",
- "css_viewport_rule.h",
"cssom/computed_style_property_map.cc",
"cssom/computed_style_property_map.h",
"cssom/cross_thread_color_value.cc",
@@ -438,6 +438,7 @@ blink_core_sources("css") {
"part_names.h",
"properties/computed_style_utils.cc",
"properties/computed_style_utils.h",
+ "properties/css_bitset.h",
"properties/css_direction_aware_resolver.cc",
"properties/css_direction_aware_resolver.h",
"properties/css_exposure.h",
@@ -597,11 +598,12 @@ blink_core_tests("unit_tests") {
sources = [
"active_style_sheets_test.cc",
"affected_by_pseudo_test.cc",
+ "computed_style_css_value_mapping_test.cc",
"css_computed_style_declaration_test.cc",
"css_font_face_source_test.cc",
"css_gradient_value_test.cc",
"css_invalid_variable_value_test.cc",
- "css_light_dark_color_pair_test.cc",
+ "css_light_dark_value_pair_test.cc",
"css_math_expression_node_test.cc",
"css_page_rule_test.cc",
"css_paint_value_test.cc",
@@ -626,8 +628,10 @@ blink_core_tests("unit_tests") {
"cssom/inline_style_property_map_test.cc",
"cssom/paint_worklet_style_property_map_test.cc",
"cssom/prepopulated_computed_style_property_map_test.cc",
+ "cssom/style_property_map_test.cc",
"drag_update_test.cc",
"font_face_cache_test.cc",
+ "font_update_invalidation_test.cc",
"invalidation/invalidation_set_test.cc",
"invalidation/pending_invalidations_test.cc",
"invalidation/style_invalidator_test.cc",
@@ -643,6 +647,7 @@ blink_core_tests("unit_tests") {
"parser/css_parser_local_context_test.cc",
"parser/css_parser_token_stream_test.cc",
"parser/css_parser_token_test.cc",
+ "parser/css_property_parser_helpers_test.cc",
"parser/css_property_parser_test.cc",
"parser/css_selector_parser_test.cc",
"parser/css_supports_parser_test.cc",
@@ -650,11 +655,14 @@ blink_core_tests("unit_tests") {
"parser/media_condition_test.cc",
"parser/sizes_attribute_parser_test.cc",
"parser/sizes_math_function_parser_test.cc",
+ "properties/computed_style_utils_test.cc",
+ "properties/css_bitset_test.cc",
"properties/css_exposure_test.cc",
"properties/css_parsing_utils_test.cc",
"properties/css_property_ref_test.cc",
"properties/css_property_test.cc",
"properties/longhands/custom_property_test.cc",
+ "property_registry_test.cc",
"resolver/cascade_expansion_test.cc",
"resolver/cascade_filter_test.cc",
"resolver/cascade_interpolations_test.cc",
@@ -665,8 +673,10 @@ blink_core_tests("unit_tests") {
"resolver/font_builder_test.cc",
"resolver/font_style_resolver_test.cc",
"resolver/match_result_test.cc",
+ "resolver/matched_properties_cache_test.cc",
"resolver/selector_filter_parent_scope_test.cc",
"resolver/style_adjuster_test.cc",
+ "resolver/style_builder_test.cc",
"resolver/style_cascade_test.cc",
"resolver/style_resolver_test.cc",
"rule_feature_set_test.cc",
diff --git a/chromium/third_party/blink/renderer/core/css/active_style_sheets_test.cc b/chromium/third_party/blink/renderer/core/css/active_style_sheets_test.cc
index 4f38ad0a53a..9e5fa7c52ac 100644
--- a/chromium/third_party/blink/renderer/core/css/active_style_sheets_test.cc
+++ b/chromium/third_party/blink/renderer/core/css/active_style_sheets_test.cc
@@ -470,8 +470,12 @@ TEST_F(ApplyRulesetsTest, AddFontFaceRuleToDocument) {
GetStyleEngine().ApplyRuleSetChanges(GetDocument(), ActiveStyleSheetVector(),
new_style_sheets);
- EXPECT_EQ(kSubtreeStyleChange,
- GetDocument().documentElement()->GetStyleChangeType());
+ StyleChangeType expected =
+ RuntimeEnabledFeatures::CSSReducedFontLoadingInvalidationsEnabled()
+ ? kNoStyleChange
+ : kSubtreeStyleChange;
+
+ EXPECT_EQ(expected, GetDocument().documentElement()->GetStyleChangeType());
}
TEST_F(ApplyRulesetsTest, AddFontFaceRuleToShadowTree) {
diff --git a/chromium/third_party/blink/renderer/core/css/computed_style_css_value_mapping.cc b/chromium/third_party/blink/renderer/core/css/computed_style_css_value_mapping.cc
index c18d609e682..73691c9e784 100644
--- a/chromium/third_party/blink/renderer/core/css/computed_style_css_value_mapping.cc
+++ b/chromium/third_party/blink/renderer/core/css/computed_style_css_value_mapping.cc
@@ -47,42 +47,11 @@ ComputedStyleCSSValueMapping::GetVariables(const ComputedStyle& style,
const PropertyRegistry* registry) {
HeapHashMap<AtomicString, Member<const CSSValue>> variables;
- StyleInheritedVariables* inherited = style.InheritedVariables();
-
- if (inherited) {
- for (const auto& name : inherited->GetCustomPropertyNames()) {
- const CSSValue* value =
- ComputedStyleCSSValueMapping::Get(name, style, registry);
- if (value)
- variables.Set(name, value);
- }
- }
-
- StyleNonInheritedVariables* non_inherited = style.NonInheritedVariables();
-
- if (non_inherited) {
- for (const auto& name : non_inherited->GetCustomPropertyNames()) {
- const CSSValue* value =
- ComputedStyleCSSValueMapping::Get(name, style, registry);
- if (value)
- variables.Set(name, value);
- }
- }
-
- // Registered properties with initial values are not stored explicitly on
- // each computed style. Their initialness is instead indicated by the
- // absence of that property on the computed style. This means that registered
- // properties with an implicit initial value will not appear in the result of
- // Style[Non]InheritedVariables::GetCustomPropertyNames, so we need to
- // iterate though all registrations and add the initial values, if necessary.
- if (registry) {
- for (const auto& entry : *registry) {
- if (variables.Contains(entry.key))
- continue;
- const CSSValue* initial = entry.value->Initial();
- if (initial)
- variables.Set(entry.key, initial);
- }
+ for (const AtomicString& name : style.GetVariableNames()) {
+ const CSSValue* value =
+ ComputedStyleCSSValueMapping::Get(name, style, registry);
+ if (value)
+ variables.Set(name, value);
}
return variables;
diff --git a/chromium/third_party/blink/renderer/core/css/computed_style_css_value_mapping.h b/chromium/third_party/blink/renderer/core/css/computed_style_css_value_mapping.h
index 29103fc597a..79a8ffaf548 100644
--- a/chromium/third_party/blink/renderer/core/css/computed_style_css_value_mapping.h
+++ b/chromium/third_party/blink/renderer/core/css/computed_style_css_value_mapping.h
@@ -13,7 +13,7 @@ namespace blink {
class ComputedStyle;
class PropertyRegistry;
-class ComputedStyleCSSValueMapping {
+class CORE_EXPORT ComputedStyleCSSValueMapping {
STATIC_ONLY(ComputedStyleCSSValueMapping);
public:
diff --git a/chromium/third_party/blink/renderer/core/css/computed_style_css_value_mapping_test.cc b/chromium/third_party/blink/renderer/core/css/computed_style_css_value_mapping_test.cc
new file mode 100644
index 00000000000..cf16243319c
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/css/computed_style_css_value_mapping_test.cc
@@ -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.
+
+#include "third_party/blink/renderer/core/css/computed_style_css_value_mapping.h"
+#include "third_party/blink/renderer/core/css/css_test_helpers.h"
+#include "third_party/blink/renderer/core/dom/node_computed_style.h"
+#include "third_party/blink/renderer/core/html/html_element.h"
+#include "third_party/blink/renderer/core/testing/page_test_base.h"
+
+namespace blink {
+
+class ComputedStyleCSSValueMappingTest : public PageTestBase {};
+
+TEST_F(ComputedStyleCSSValueMappingTest, GetVariablesOnOldStyle) {
+ using css_test_helpers::RegisterProperty;
+
+ GetDocument().body()->setInnerHTML("<div id=target style='--x:red'></div>");
+ UpdateAllLifecyclePhasesForTest();
+
+ Element* target = GetDocument().getElementById("target");
+ ASSERT_TRUE(target);
+
+ auto before = ComputedStyleCSSValueMapping::GetVariables(
+ target->ComputedStyleRef(), GetDocument().GetPropertyRegistry());
+ EXPECT_EQ(1u, before.size());
+ EXPECT_TRUE(before.Contains("--x"));
+ EXPECT_FALSE(before.Contains("--y"));
+
+ RegisterProperty(GetDocument(), "--y", "<length>", "0px", false);
+
+ // Registering a property should not affect variables reported on a
+ // ComputedStyle created pre-registration.
+ auto after = ComputedStyleCSSValueMapping::GetVariables(
+ target->ComputedStyleRef(), GetDocument().GetPropertyRegistry());
+ EXPECT_EQ(1u, after.size());
+ EXPECT_TRUE(after.Contains("--x"));
+ EXPECT_FALSE(after.Contains("--y"));
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/css.dict b/chromium/third_party/blink/renderer/core/css/css.dict
index 25069da47a2..382461bbe31 100644
--- a/chromium/third_party/blink/renderer/core/css/css.dict
+++ b/chromium/third_party/blink/renderer/core/css/css.dict
@@ -713,7 +713,7 @@
"rgba"
"hsl"
"hsla"
-"-internal-light-dark-color"
+"-internal-light-dark"
"matrix"
"matrix3d"
"perspective"
@@ -1357,7 +1357,7 @@
"stroke-repeat"
"stroke-size"
"stroke-width"
-"subtree-visibility"
+"content-visibility"
"suffix"
"symbols"
"system"
diff --git a/chromium/third_party/blink/renderer/core/css/css.idl b/chromium/third_party/blink/renderer/core/css/css.idl
index ee1e393c58f..08315b2dea1 100644
--- a/chromium/third_party/blink/renderer/core/css/css.idl
+++ b/chromium/third_party/blink/renderer/core/css/css.idl
@@ -30,6 +30,7 @@
// https://drafts.csswg.org/css-conditional/#the-css-interface
[
+ Exposed=Window,
ImplementedAs=DOMWindowCSS
] interface CSS {
[CallWith=ExecutionContext] static boolean supports(DOMString property, DOMString value);
diff --git a/chromium/third_party/blink/renderer/core/css/css_computed_style_declaration.cc b/chromium/third_party/blink/renderer/core/css/css_computed_style_declaration.cc
index 4df6327a8ee..e7f3444a197 100644
--- a/chromium/third_party/blink/renderer/core/css/css_computed_style_declaration.cc
+++ b/chromium/third_party/blink/renderer/core/css/css_computed_style_declaration.cc
@@ -56,22 +56,35 @@ namespace {
// NOTE: Do not use this list, use computableProperties() instead
// to respect runtime enabling of CSS properties.
const CSSPropertyID kComputedPropertyArray[] = {
+ CSSPropertyID::kAlignContent, CSSPropertyID::kAlignItems,
+ CSSPropertyID::kAlignSelf, CSSPropertyID::kAlignmentBaseline,
CSSPropertyID::kAnimationDelay, CSSPropertyID::kAnimationDirection,
CSSPropertyID::kAnimationDuration, CSSPropertyID::kAnimationFillMode,
CSSPropertyID::kAnimationIterationCount, CSSPropertyID::kAnimationName,
CSSPropertyID::kAnimationPlayState, CSSPropertyID::kAnimationTimingFunction,
- CSSPropertyID::kBackgroundAttachment, CSSPropertyID::kBackgroundBlendMode,
- CSSPropertyID::kBackgroundClip, CSSPropertyID::kBackgroundColor,
- CSSPropertyID::kBackgroundImage, CSSPropertyID::kBackgroundOrigin,
+ CSSPropertyID::kAppearance, CSSPropertyID::kBackdropFilter,
+ CSSPropertyID::kBackfaceVisibility, CSSPropertyID::kBackgroundAttachment,
+ CSSPropertyID::kBackgroundBlendMode, CSSPropertyID::kBackgroundClip,
+ CSSPropertyID::kBackgroundColor, CSSPropertyID::kBackgroundImage,
+ CSSPropertyID::kBackgroundOrigin,
// more-specific background-position-x/y are non-standard
CSSPropertyID::kBackgroundPosition, CSSPropertyID::kBackgroundRepeat,
- CSSPropertyID::kBackgroundSize, CSSPropertyID::kBorderBottomColor,
+ CSSPropertyID::kBackgroundSize, CSSPropertyID::kBaselineShift,
+ CSSPropertyID::kBlockSize, CSSPropertyID::kBorderBlockEndColor,
+ CSSPropertyID::kBorderBlockEndStyle, CSSPropertyID::kBorderBlockEndWidth,
+ CSSPropertyID::kBorderBlockStartColor,
+ CSSPropertyID::kBorderBlockStartStyle,
+ CSSPropertyID::kBorderBlockStartWidth, CSSPropertyID::kBorderBottomColor,
CSSPropertyID::kBorderBottomLeftRadius,
CSSPropertyID::kBorderBottomRightRadius, CSSPropertyID::kBorderBottomStyle,
CSSPropertyID::kBorderBottomWidth, CSSPropertyID::kBorderCollapse,
CSSPropertyID::kBorderImageOutset, CSSPropertyID::kBorderImageRepeat,
CSSPropertyID::kBorderImageSlice, CSSPropertyID::kBorderImageSource,
- CSSPropertyID::kBorderImageWidth, CSSPropertyID::kBorderLeftColor,
+ CSSPropertyID::kBorderImageWidth, CSSPropertyID::kBorderInlineEndColor,
+ CSSPropertyID::kBorderInlineEndStyle, CSSPropertyID::kBorderInlineEndWidth,
+ CSSPropertyID::kBorderInlineStartColor,
+ CSSPropertyID::kBorderInlineStartStyle,
+ CSSPropertyID::kBorderInlineStartWidth, CSSPropertyID::kBorderLeftColor,
CSSPropertyID::kBorderLeftStyle, CSSPropertyID::kBorderLeftWidth,
CSSPropertyID::kBorderRightColor, CSSPropertyID::kBorderRightStyle,
CSSPropertyID::kBorderRightWidth, CSSPropertyID::kBorderTopColor,
@@ -80,59 +93,117 @@ const CSSPropertyID kComputedPropertyArray[] = {
CSSPropertyID::kBottom, CSSPropertyID::kBoxShadow,
CSSPropertyID::kBoxSizing, CSSPropertyID::kBreakAfter,
CSSPropertyID::kBreakBefore, CSSPropertyID::kBreakInside,
- CSSPropertyID::kCaptionSide, CSSPropertyID::kClear, CSSPropertyID::kClip,
- CSSPropertyID::kColor, CSSPropertyID::kContent, CSSPropertyID::kCursor,
- CSSPropertyID::kDirection, CSSPropertyID::kDisplay,
- CSSPropertyID::kEmptyCells, CSSPropertyID::kFloat,
+ CSSPropertyID::kBufferedRendering, CSSPropertyID::kCaptionSide,
+ CSSPropertyID::kCaretColor, CSSPropertyID::kClear, CSSPropertyID::kClip,
+ CSSPropertyID::kClipPath, CSSPropertyID::kClipRule, CSSPropertyID::kColor,
+ CSSPropertyID::kColorInterpolation,
+ CSSPropertyID::kColorInterpolationFilters, CSSPropertyID::kColorRendering,
+ CSSPropertyID::kColumnCount, CSSPropertyID::kColumnGap,
+ CSSPropertyID::kColumnRuleColor, CSSPropertyID::kColumnRuleStyle,
+ CSSPropertyID::kColumnRuleWidth, CSSPropertyID::kColumnSpan,
+ CSSPropertyID::kColumnWidth, CSSPropertyID::kContent,
+ CSSPropertyID::kCursor, CSSPropertyID::kCx, CSSPropertyID::kCy,
+ CSSPropertyID::kD, CSSPropertyID::kDirection, CSSPropertyID::kDisplay,
+ CSSPropertyID::kDominantBaseline, CSSPropertyID::kEmptyCells,
+ CSSPropertyID::kFill, CSSPropertyID::kFillOpacity, CSSPropertyID::kFillRule,
+ CSSPropertyID::kFilter, CSSPropertyID::kFlexBasis,
+ CSSPropertyID::kFlexDirection, CSSPropertyID::kFlexGrow,
+ CSSPropertyID::kFlexShrink, CSSPropertyID::kFlexWrap, CSSPropertyID::kFloat,
+ CSSPropertyID::kFloodColor, CSSPropertyID::kFloodOpacity,
CSSPropertyID::kFontFamily, CSSPropertyID::kFontKerning,
CSSPropertyID::kFontOpticalSizing, CSSPropertyID::kFontSize,
CSSPropertyID::kFontSizeAdjust, CSSPropertyID::kFontStretch,
CSSPropertyID::kFontStyle, CSSPropertyID::kFontVariant,
- CSSPropertyID::kFontVariantLigatures, CSSPropertyID::kFontVariantCaps,
- CSSPropertyID::kFontVariantNumeric, CSSPropertyID::kFontVariantEastAsian,
- CSSPropertyID::kFontWeight, CSSPropertyID::kHeight,
- CSSPropertyID::kImageOrientation, CSSPropertyID::kImageRendering,
- CSSPropertyID::kIsolation, CSSPropertyID::kJustifyItems,
- CSSPropertyID::kJustifySelf, CSSPropertyID::kLeft,
- CSSPropertyID::kLetterSpacing, CSSPropertyID::kLineHeight,
- CSSPropertyID::kLineHeightStep, CSSPropertyID::kListStyleImage,
- CSSPropertyID::kListStylePosition, CSSPropertyID::kListStyleType,
- CSSPropertyID::kMarginBottom, CSSPropertyID::kMarginLeft,
- CSSPropertyID::kMarginRight, CSSPropertyID::kMarginTop,
- CSSPropertyID::kMaxHeight, CSSPropertyID::kMaxWidth,
- CSSPropertyID::kMinHeight, CSSPropertyID::kMinWidth,
- CSSPropertyID::kMixBlendMode, CSSPropertyID::kObjectFit,
- CSSPropertyID::kObjectPosition, CSSPropertyID::kOffsetAnchor,
- CSSPropertyID::kOffsetDistance, CSSPropertyID::kOffsetPath,
- CSSPropertyID::kOffsetPosition, CSSPropertyID::kOffsetRotate,
- CSSPropertyID::kOpacity, CSSPropertyID::kOrphans,
+ CSSPropertyID::kFontVariantCaps, CSSPropertyID::kFontVariantEastAsian,
+ CSSPropertyID::kFontVariantLigatures, CSSPropertyID::kFontVariantNumeric,
+ CSSPropertyID::kFontWeight, CSSPropertyID::kGridAutoColumns,
+ CSSPropertyID::kGridAutoFlow, CSSPropertyID::kGridAutoRows,
+ CSSPropertyID::kGridColumnEnd, CSSPropertyID::kGridColumnStart,
+ CSSPropertyID::kGridRowEnd, CSSPropertyID::kGridRowStart,
+ CSSPropertyID::kGridTemplateAreas, CSSPropertyID::kGridTemplateColumns,
+ CSSPropertyID::kGridTemplateRows, CSSPropertyID::kHeight,
+ CSSPropertyID::kHyphens, CSSPropertyID::kImageOrientation,
+ CSSPropertyID::kImageRendering, CSSPropertyID::kInlineSize,
+ CSSPropertyID::kInsetBlockEnd, CSSPropertyID::kInsetBlockStart,
+ CSSPropertyID::kInsetInlineEnd, CSSPropertyID::kInsetInlineStart,
+ CSSPropertyID::kIsolation, CSSPropertyID::kJustifyContent,
+ CSSPropertyID::kJustifyItems, CSSPropertyID::kJustifySelf,
+ CSSPropertyID::kLeft, CSSPropertyID::kLetterSpacing,
+ CSSPropertyID::kLightingColor, CSSPropertyID::kLineBreak,
+ CSSPropertyID::kLineHeight, CSSPropertyID::kLineHeightStep,
+ CSSPropertyID::kListStyleImage, CSSPropertyID::kListStylePosition,
+ CSSPropertyID::kListStyleType, CSSPropertyID::kMarginBlockEnd,
+ CSSPropertyID::kMarginBlockStart, CSSPropertyID::kMarginBottom,
+ CSSPropertyID::kMarginInlineEnd, CSSPropertyID::kMarginInlineStart,
+ CSSPropertyID::kMarginLeft, CSSPropertyID::kMarginRight,
+ CSSPropertyID::kMarginTop, CSSPropertyID::kMarkerEnd,
+ CSSPropertyID::kMarkerMid, CSSPropertyID::kMarkerStart,
+ CSSPropertyID::kMask, CSSPropertyID::kMaskSourceType,
+ CSSPropertyID::kMaskType, CSSPropertyID::kMathStyle,
+ CSSPropertyID::kMathSuperscriptShiftStyle, CSSPropertyID::kMaxBlockSize,
+ CSSPropertyID::kMaxHeight, CSSPropertyID::kMaxInlineSize,
+ CSSPropertyID::kMaxWidth, CSSPropertyID::kMinBlockSize,
+ CSSPropertyID::kMinHeight, CSSPropertyID::kMinInlineSize,
+ CSSPropertyID::kMinWidth, CSSPropertyID::kMixBlendMode,
+ CSSPropertyID::kObjectFit, CSSPropertyID::kObjectPosition,
+ CSSPropertyID::kOffsetAnchor, CSSPropertyID::kOffsetDistance,
+ CSSPropertyID::kOffsetPath, CSSPropertyID::kOffsetPosition,
+ CSSPropertyID::kOffsetRotate, CSSPropertyID::kOpacity,
+ CSSPropertyID::kOrder, CSSPropertyID::kOrphans,
CSSPropertyID::kOutlineColor, CSSPropertyID::kOutlineOffset,
CSSPropertyID::kOutlineStyle, CSSPropertyID::kOutlineWidth,
- CSSPropertyID::kOverflowAnchor, CSSPropertyID::kOverflowWrap,
+ CSSPropertyID::kOverflowAnchor, CSSPropertyID::kOverflowBlock,
+ CSSPropertyID::kOverflowInline, CSSPropertyID::kOverflowWrap,
CSSPropertyID::kOverflowX, CSSPropertyID::kOverflowY,
- CSSPropertyID::kPaddingBottom, CSSPropertyID::kPaddingLeft,
- CSSPropertyID::kPaddingRight, CSSPropertyID::kPaddingTop,
- CSSPropertyID::kPointerEvents, CSSPropertyID::kPosition,
- CSSPropertyID::kResize, CSSPropertyID::kRight,
- CSSPropertyID::kScrollBehavior, CSSPropertyID::kScrollCustomization,
- CSSPropertyID::kSpeak, CSSPropertyID::kTableLayout, CSSPropertyID::kTabSize,
- CSSPropertyID::kTextAlign, CSSPropertyID::kTextAlignLast,
- CSSPropertyID::kTextDecoration, CSSPropertyID::kTextDecorationLine,
- CSSPropertyID::kTextDecorationStyle, CSSPropertyID::kTextDecorationColor,
- CSSPropertyID::kTextDecorationSkipInk, CSSPropertyID::kTextJustify,
- CSSPropertyID::kTextUnderlinePosition, CSSPropertyID::kTextIndent,
+ CSSPropertyID::kOverscrollBehaviorBlock,
+ CSSPropertyID::kOverscrollBehaviorInline, CSSPropertyID::kPaddingBlockEnd,
+ CSSPropertyID::kPaddingBlockStart, CSSPropertyID::kPaddingBottom,
+ CSSPropertyID::kPaddingInlineEnd, CSSPropertyID::kPaddingInlineStart,
+ CSSPropertyID::kPaddingLeft, CSSPropertyID::kPaddingRight,
+ CSSPropertyID::kPaddingTop, CSSPropertyID::kPaintOrder,
+ CSSPropertyID::kPerspective, CSSPropertyID::kPerspectiveOrigin,
+ CSSPropertyID::kPointerEvents, CSSPropertyID::kPosition, CSSPropertyID::kR,
+ CSSPropertyID::kResize, CSSPropertyID::kRight, CSSPropertyID::kRotate,
+ CSSPropertyID::kRowGap, CSSPropertyID::kRubyPosition, CSSPropertyID::kRx,
+ CSSPropertyID::kRy, CSSPropertyID::kScale, CSSPropertyID::kScrollBehavior,
+ CSSPropertyID::kScrollCustomization, CSSPropertyID::kScrollMarginBlockEnd,
+ CSSPropertyID::kScrollMarginBlockStart,
+ CSSPropertyID::kScrollMarginInlineEnd,
+ CSSPropertyID::kScrollMarginInlineStart,
+ CSSPropertyID::kScrollPaddingBlockEnd,
+ CSSPropertyID::kScrollPaddingBlockStart,
+ CSSPropertyID::kScrollPaddingInlineEnd,
+ CSSPropertyID::kScrollPaddingInlineStart,
+ CSSPropertyID::kShapeImageThreshold, CSSPropertyID::kShapeMargin,
+ CSSPropertyID::kShapeOutside, CSSPropertyID::kShapeRendering,
+ CSSPropertyID::kSpeak, CSSPropertyID::kStopColor,
+ CSSPropertyID::kStopOpacity, CSSPropertyID::kStroke,
+ CSSPropertyID::kStrokeDasharray, CSSPropertyID::kStrokeDashoffset,
+ CSSPropertyID::kStrokeLinecap, CSSPropertyID::kStrokeLinejoin,
+ CSSPropertyID::kStrokeMiterlimit, CSSPropertyID::kStrokeOpacity,
+ CSSPropertyID::kStrokeWidth, CSSPropertyID::kTabSize,
+ CSSPropertyID::kTableLayout, CSSPropertyID::kTextAlign,
+ CSSPropertyID::kTextAlignLast, CSSPropertyID::kTextAnchor,
+ CSSPropertyID::kTextDecoration, CSSPropertyID::kTextDecorationColor,
+ CSSPropertyID::kTextDecorationLine, CSSPropertyID::kTextDecorationSkipInk,
+ CSSPropertyID::kTextDecorationStyle, CSSPropertyID::kTextIndent,
+ CSSPropertyID::kTextJustify, CSSPropertyID::kTextOverflow,
CSSPropertyID::kTextRendering, CSSPropertyID::kTextShadow,
- CSSPropertyID::kTextSizeAdjust, CSSPropertyID::kTextOverflow,
- CSSPropertyID::kTextTransform, CSSPropertyID::kTop,
- CSSPropertyID::kTouchAction, CSSPropertyID::kTransitionDelay,
- CSSPropertyID::kTransitionDuration, CSSPropertyID::kTransitionProperty,
- CSSPropertyID::kTransitionTimingFunction, CSSPropertyID::kUnicodeBidi,
- CSSPropertyID::kVerticalAlign, CSSPropertyID::kVisibility,
- CSSPropertyID::kWhiteSpace, CSSPropertyID::kWidows, CSSPropertyID::kWidth,
- CSSPropertyID::kWillChange, CSSPropertyID::kWordBreak,
- CSSPropertyID::kWordSpacing, CSSPropertyID::kZIndex, CSSPropertyID::kZoom,
-
- CSSPropertyID::kWebkitAppearance, CSSPropertyID::kBackfaceVisibility,
+ CSSPropertyID::kTextSizeAdjust, CSSPropertyID::kTextTransform,
+ CSSPropertyID::kTextUnderlinePosition, CSSPropertyID::kTop,
+ CSSPropertyID::kTouchAction, CSSPropertyID::kTransform,
+ CSSPropertyID::kTransformOrigin, CSSPropertyID::kTransformStyle,
+ CSSPropertyID::kTransitionDelay, CSSPropertyID::kTransitionDuration,
+ CSSPropertyID::kTransitionProperty,
+ CSSPropertyID::kTransitionTimingFunction, CSSPropertyID::kTranslate,
+ CSSPropertyID::kUnicodeBidi, CSSPropertyID::kUserSelect,
+ CSSPropertyID::kVectorEffect, CSSPropertyID::kVerticalAlign,
+ CSSPropertyID::kVisibility, CSSPropertyID::kWhiteSpace,
+ CSSPropertyID::kWidows, CSSPropertyID::kWidth, CSSPropertyID::kWillChange,
+ CSSPropertyID::kWordBreak, CSSPropertyID::kWordSpacing,
+ CSSPropertyID::kWritingMode, CSSPropertyID::kX, CSSPropertyID::kY,
+ CSSPropertyID::kZIndex, CSSPropertyID::kZoom,
+ CSSPropertyID::kWebkitAppRegion,
CSSPropertyID::kWebkitBorderHorizontalSpacing,
CSSPropertyID::kWebkitBorderImage,
CSSPropertyID::kWebkitBorderVerticalSpacing, CSSPropertyID::kWebkitBoxAlign,
@@ -140,24 +211,10 @@ const CSSPropertyID kComputedPropertyArray[] = {
CSSPropertyID::kWebkitBoxDirection, CSSPropertyID::kWebkitBoxFlex,
CSSPropertyID::kWebkitBoxOrdinalGroup, CSSPropertyID::kWebkitBoxOrient,
CSSPropertyID::kWebkitBoxPack, CSSPropertyID::kWebkitBoxReflect,
- CSSPropertyID::kColumnCount, CSSPropertyID::kColumnGap,
- CSSPropertyID::kColumnRuleColor, CSSPropertyID::kColumnRuleStyle,
- CSSPropertyID::kColumnRuleWidth, CSSPropertyID::kColumnSpan,
- CSSPropertyID::kColumnWidth, CSSPropertyID::kBackdropFilter,
- CSSPropertyID::kAlignContent, CSSPropertyID::kAlignItems,
- CSSPropertyID::kAlignSelf, CSSPropertyID::kFlexBasis,
- CSSPropertyID::kFlexGrow, CSSPropertyID::kFlexShrink,
- CSSPropertyID::kFlexDirection, CSSPropertyID::kFlexWrap,
- CSSPropertyID::kJustifyContent, CSSPropertyID::kWebkitFontSmoothing,
- CSSPropertyID::kGridAutoColumns, CSSPropertyID::kGridAutoFlow,
- CSSPropertyID::kGridAutoRows, CSSPropertyID::kGridColumnEnd,
- CSSPropertyID::kGridColumnStart, CSSPropertyID::kGridTemplateAreas,
- CSSPropertyID::kGridTemplateColumns, CSSPropertyID::kGridTemplateRows,
- CSSPropertyID::kGridRowEnd, CSSPropertyID::kGridRowStart,
- CSSPropertyID::kRowGap, CSSPropertyID::kWebkitHighlight,
- CSSPropertyID::kHyphens, CSSPropertyID::kWebkitHyphenateCharacter,
- CSSPropertyID::kWebkitLineBreak, CSSPropertyID::kWebkitLineClamp,
- CSSPropertyID::kWebkitLocale, CSSPropertyID::kWebkitMaskBoxImage,
+ CSSPropertyID::kWebkitFontSmoothing, CSSPropertyID::kWebkitHighlight,
+ CSSPropertyID::kWebkitHyphenateCharacter, CSSPropertyID::kWebkitLineBreak,
+ CSSPropertyID::kWebkitLineClamp, CSSPropertyID::kWebkitLocale,
+ CSSPropertyID::kWebkitMaskBoxImage,
CSSPropertyID::kWebkitMaskBoxImageOutset,
CSSPropertyID::kWebkitMaskBoxImageRepeat,
CSSPropertyID::kWebkitMaskBoxImageSlice,
@@ -166,10 +223,7 @@ const CSSPropertyID kComputedPropertyArray[] = {
CSSPropertyID::kWebkitMaskComposite, CSSPropertyID::kWebkitMaskImage,
CSSPropertyID::kWebkitMaskOrigin, CSSPropertyID::kWebkitMaskPosition,
CSSPropertyID::kWebkitMaskRepeat, CSSPropertyID::kWebkitMaskSize,
- CSSPropertyID::kOrder, CSSPropertyID::kPerspective,
- CSSPropertyID::kPerspectiveOrigin, CSSPropertyID::kWebkitPrintColorAdjust,
- CSSPropertyID::kWebkitRtlOrdering, CSSPropertyID::kShapeOutside,
- CSSPropertyID::kShapeImageThreshold, CSSPropertyID::kShapeMargin,
+ CSSPropertyID::kWebkitPrintColorAdjust, CSSPropertyID::kWebkitRtlOrdering,
CSSPropertyID::kWebkitTapHighlightColor, CSSPropertyID::kWebkitTextCombine,
CSSPropertyID::kWebkitTextDecorationsInEffect,
CSSPropertyID::kWebkitTextEmphasisColor,
@@ -177,33 +231,8 @@ const CSSPropertyID kComputedPropertyArray[] = {
CSSPropertyID::kWebkitTextEmphasisStyle,
CSSPropertyID::kWebkitTextFillColor, CSSPropertyID::kWebkitTextOrientation,
CSSPropertyID::kWebkitTextSecurity, CSSPropertyID::kWebkitTextStrokeColor,
- CSSPropertyID::kWebkitTextStrokeWidth, CSSPropertyID::kTransform,
- CSSPropertyID::kTransformOrigin, CSSPropertyID::kTransformStyle,
- CSSPropertyID::kWebkitUserDrag, CSSPropertyID::kWebkitUserModify,
- CSSPropertyID::kUserSelect, CSSPropertyID::kWebkitWritingMode,
- CSSPropertyID::kWebkitAppRegion, CSSPropertyID::kBufferedRendering,
- CSSPropertyID::kClipPath, CSSPropertyID::kClipRule, CSSPropertyID::kMask,
- CSSPropertyID::kFilter, CSSPropertyID::kFloodColor,
- CSSPropertyID::kFloodOpacity, CSSPropertyID::kLightingColor,
- CSSPropertyID::kStopColor, CSSPropertyID::kStopOpacity,
- CSSPropertyID::kColorInterpolation,
- CSSPropertyID::kColorInterpolationFilters, CSSPropertyID::kColorRendering,
- CSSPropertyID::kFill, CSSPropertyID::kFillOpacity, CSSPropertyID::kFillRule,
- CSSPropertyID::kMarkerEnd, CSSPropertyID::kMarkerMid,
- CSSPropertyID::kMarkerStart, CSSPropertyID::kMaskType,
- CSSPropertyID::kMaskSourceType, CSSPropertyID::kShapeRendering,
- CSSPropertyID::kStroke, CSSPropertyID::kStrokeDasharray,
- CSSPropertyID::kStrokeDashoffset, CSSPropertyID::kStrokeLinecap,
- CSSPropertyID::kStrokeLinejoin, CSSPropertyID::kStrokeMiterlimit,
- CSSPropertyID::kStrokeOpacity, CSSPropertyID::kStrokeWidth,
- CSSPropertyID::kAlignmentBaseline, CSSPropertyID::kBaselineShift,
- CSSPropertyID::kDominantBaseline, CSSPropertyID::kTextAnchor,
- CSSPropertyID::kWritingMode, CSSPropertyID::kVectorEffect,
- CSSPropertyID::kPaintOrder, CSSPropertyID::kD, CSSPropertyID::kCx,
- CSSPropertyID::kCy, CSSPropertyID::kX, CSSPropertyID::kY, CSSPropertyID::kR,
- CSSPropertyID::kRx, CSSPropertyID::kRy, CSSPropertyID::kTranslate,
- CSSPropertyID::kRotate, CSSPropertyID::kScale, CSSPropertyID::kCaretColor,
- CSSPropertyID::kLineBreak, CSSPropertyID::kMathStyle};
+ CSSPropertyID::kWebkitTextStrokeWidth, CSSPropertyID::kWebkitUserDrag,
+ CSSPropertyID::kWebkitUserModify, CSSPropertyID::kWebkitWritingMode};
CSSValueID CssIdentifierForFontSizeKeyword(int keyword_size) {
DCHECK_NE(keyword_size, 0);
@@ -433,8 +462,7 @@ const CSSValue* CSSComputedStyleDeclaration::GetPropertyCSSValue(
String CSSComputedStyleDeclaration::GetPropertyValue(
CSSPropertyID property_id) const {
// allow_visited_style_ is true only for access from DevTools.
- if (!allow_visited_style_ &&
- property_id == CSSPropertyID::kWebkitAppearance) {
+ if (!allow_visited_style_ && property_id == CSSPropertyID::kAppearance) {
UseCounter::Count(
node_->GetDocument(),
WebFeature::kGetComputedStyleForWebkitAppearanceExcludeDevTools);
@@ -559,7 +587,7 @@ String CSSComputedStyleDeclaration::removeProperty(
const CSSValue* CSSComputedStyleDeclaration::GetPropertyCSSValueInternal(
CSSPropertyID property_id) {
- if (property_id == CSSPropertyID::kWebkitAppearance && node_) {
+ if (property_id == CSSPropertyID::kAppearance && node_) {
UseCounter::Count(node_->GetDocument(),
WebFeature::kGetComputedStyleWebkitAppearance);
}
diff --git a/chromium/third_party/blink/renderer/core/css/css_crossfade_value.cc b/chromium/third_party/blink/renderer/core/css/css_crossfade_value.cc
index 5051a541852..3e1ce9c3dbc 100644
--- a/chromium/third_party/blink/renderer/core/css/css_crossfade_value.cc
+++ b/chromium/third_party/blink/renderer/core/css/css_crossfade_value.cc
@@ -68,7 +68,7 @@ static ImageResourceContent* CachedImageForCSSValue(CSSValue* value,
if (auto* image_value = DynamicTo<CSSImageValue>(value)) {
StyleImage* style_image_resource =
- image_value->CacheImage(document, FetchParameters::kAllowPlaceholder);
+ image_value->CacheImage(document, FetchParameters::kNone);
if (!style_image_resource)
return nullptr;
diff --git a/chromium/third_party/blink/renderer/core/css/css_custom_property_declaration.h b/chromium/third_party/blink/renderer/core/css/css_custom_property_declaration.h
index f7d09e70029..6a92125c29c 100644
--- a/chromium/third_party/blink/renderer/core/css/css_custom_property_declaration.h
+++ b/chromium/third_party/blink/renderer/core/css/css_custom_property_declaration.h
@@ -8,6 +8,7 @@
#include "base/memory/scoped_refptr.h"
#include "third_party/blink/renderer/core/css/css_value.h"
#include "third_party/blink/renderer/core/css/css_variable_data.h"
+#include "third_party/blink/renderer/core/css/properties/css_parsing_utils.h"
#include "third_party/blink/renderer/core/css_value_keywords.h"
#include "third_party/blink/renderer/platform/wtf/casting.h"
#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
@@ -21,8 +22,7 @@ class CORE_EXPORT CSSCustomPropertyDeclaration : public CSSValue {
name_(name),
value_(nullptr),
value_id_(id) {
- DCHECK(id == CSSValueID::kInherit || id == CSSValueID::kInitial ||
- id == CSSValueID::kUnset);
+ DCHECK(css_parsing_utils::IsCSSWideKeyword(id));
}
CSSCustomPropertyDeclaration(const AtomicString& name,
@@ -43,6 +43,7 @@ class CORE_EXPORT CSSCustomPropertyDeclaration : public CSSValue {
return value_id_ == CSSValueID::kInitial ||
(!is_inherited_property && value_id_ == CSSValueID::kUnset);
}
+ bool IsRevert() const { return value_id_ == CSSValueID::kRevert; }
String CustomCSSText() const;
diff --git a/chromium/third_party/blink/renderer/core/css/css_default_style_sheets.cc b/chromium/third_party/blink/renderer/core/css/css_default_style_sheets.cc
index 35b4ac04a48..749dcb3ffb6 100644
--- a/chromium/third_party/blink/renderer/core/css/css_default_style_sheets.cc
+++ b/chromium/third_party/blink/renderer/core/css/css_default_style_sheets.cc
@@ -108,10 +108,14 @@ CSSDefaultStyleSheets::CSSDefaultStyleSheets()
#if DCHECK_IS_ON()
default_style_->CompactRulesIfNeeded();
+ default_mathml_style_->CompactRulesIfNeeded();
+ default_svg_style_->CompactRulesIfNeeded();
default_quirks_style_->CompactRulesIfNeeded();
default_print_style_->CompactRulesIfNeeded();
default_forced_color_style_->CompactRulesIfNeeded();
DCHECK(default_style_->UniversalRules()->IsEmpty());
+ DCHECK(default_mathml_style_->UniversalRules()->IsEmpty());
+ DCHECK(default_svg_style_->UniversalRules()->IsEmpty());
DCHECK(default_quirks_style_->UniversalRules()->IsEmpty());
DCHECK(default_print_style_->UniversalRules()->IsEmpty());
DCHECK(default_forced_color_style_->UniversalRules()->IsEmpty());
@@ -142,6 +146,8 @@ void CSSDefaultStyleSheets::PrepareForLeakDetection() {
void CSSDefaultStyleSheets::InitializeDefaultStyles() {
// This must be called only from constructor / PrepareForLeakDetection.
default_style_ = MakeGarbageCollected<RuleSet>();
+ default_mathml_style_ = MakeGarbageCollected<RuleSet>();
+ default_svg_style_ = MakeGarbageCollected<RuleSet>();
default_quirks_style_ = MakeGarbageCollected<RuleSet>();
default_print_style_ = MakeGarbageCollected<RuleSet>();
default_forced_color_style_ = MakeGarbageCollected<RuleSet>();
@@ -206,7 +212,7 @@ bool CSSDefaultStyleSheets::EnsureDefaultStyleSheetsForElement(
if (element.IsSVGElement() && !svg_style_sheet_) {
svg_style_sheet_ =
ParseUASheet(UncompressResourceAsASCIIString(IDR_UASTYLE_SVG_CSS));
- default_style_->AddRulesFromSheet(SvgStyleSheet(), ScreenEval());
+ default_svg_style_->AddRulesFromSheet(SvgStyleSheet(), ScreenEval());
default_print_style_->AddRulesFromSheet(SvgStyleSheet(), PrintEval());
default_forced_color_style_->AddRulesFromSheet(SvgStyleSheet(),
ForcedColorsEval());
@@ -220,7 +226,7 @@ bool CSSDefaultStyleSheets::EnsureDefaultStyleSheetsForElement(
RuntimeEnabledFeatures::MathMLCoreEnabled()
? UncompressResourceAsASCIIString(IDR_UASTYLE_MATHML_CSS)
: UncompressResourceAsASCIIString(IDR_UASTYLE_MATHML_FALLBACK_CSS));
- default_style_->AddRulesFromSheet(MathmlStyleSheet(), ScreenEval());
+ default_mathml_style_->AddRulesFromSheet(MathmlStyleSheet(), ScreenEval());
default_print_style_->AddRulesFromSheet(MathmlStyleSheet(), PrintEval());
changed_default_style = true;
}
@@ -312,6 +318,8 @@ void CSSDefaultStyleSheets::EnsureDefaultStyleSheetForFullscreen() {
void CSSDefaultStyleSheets::Trace(Visitor* visitor) {
visitor->Trace(default_style_);
+ visitor->Trace(default_mathml_style_);
+ visitor->Trace(default_svg_style_);
visitor->Trace(default_quirks_style_);
visitor->Trace(default_print_style_);
visitor->Trace(default_view_source_style_);
diff --git a/chromium/third_party/blink/renderer/core/css/css_default_style_sheets.h b/chromium/third_party/blink/renderer/core/css/css_default_style_sheets.h
index d46f6d86a1a..56040ac93c6 100644
--- a/chromium/third_party/blink/renderer/core/css/css_default_style_sheets.h
+++ b/chromium/third_party/blink/renderer/core/css/css_default_style_sheets.h
@@ -48,6 +48,8 @@ class CSSDefaultStyleSheets final
void EnsureDefaultStyleSheetForFullscreen();
RuleSet* DefaultStyle() { return default_style_.Get(); }
+ RuleSet* DefaultMathMLStyle() { return default_mathml_style_.Get(); }
+ RuleSet* DefaultSVGStyle() { return default_svg_style_.Get(); }
RuleSet* DefaultQuirksStyle() { return default_quirks_style_.Get(); }
RuleSet* DefaultPrintStyle() { return default_print_style_.Get(); }
RuleSet* DefaultViewSourceStyle();
@@ -94,6 +96,8 @@ class CSSDefaultStyleSheets final
void InitializeDefaultStyles();
Member<RuleSet> default_style_;
+ Member<RuleSet> default_mathml_style_;
+ Member<RuleSet> default_svg_style_;
Member<RuleSet> default_quirks_style_;
Member<RuleSet> default_print_style_;
Member<RuleSet> default_view_source_style_;
diff --git a/chromium/third_party/blink/renderer/core/css/css_font_face.cc b/chromium/third_party/blink/renderer/core/css/css_font_face.cc
index 8794978bc9b..8002ecb47d2 100644
--- a/chromium/third_party/blink/renderer/core/css/css_font_face.cc
+++ b/chromium/third_party/blink/renderer/core/css/css_font_face.cc
@@ -228,6 +228,17 @@ void CSSFontFace::SetLoadStatus(FontFace::LoadStatusType new_status) {
}
}
+bool CSSFontFace::UpdatePeriod() {
+ if (LoadStatus() == FontFace::kLoaded)
+ return false;
+ bool changed = false;
+ for (CSSFontFaceSource* source : sources_) {
+ if (source->UpdatePeriod())
+ changed = true;
+ }
+ return changed;
+}
+
void CSSFontFace::Trace(Visitor* visitor) {
visitor->Trace(segmented_font_faces_);
visitor->Trace(sources_);
diff --git a/chromium/third_party/blink/renderer/core/css/css_font_face.h b/chromium/third_party/blink/renderer/core/css/css_font_face.h
index 1c725193245..7727f1f7f98 100644
--- a/chromium/third_party/blink/renderer/core/css/css_font_face.h
+++ b/chromium/third_party/blink/renderer/core/css/css_font_face.h
@@ -80,6 +80,11 @@ class CORE_EXPORT CSSFontFace final : public GarbageCollected<CSSFontFace> {
void Load();
void Load(const FontDescription&);
+ // Recalculate the font loading timeline period for the font face.
+ // https://drafts.csswg.org/css-fonts-4/#font-display-timeline
+ // Returns true if the display period is changed.
+ bool UpdatePeriod();
+
bool HadBlankText() { return IsValid() && sources_.front()->HadBlankText(); }
void Trace(Visitor*);
diff --git a/chromium/third_party/blink/renderer/core/css/css_font_face_rule.idl b/chromium/third_party/blink/renderer/core/css/css_font_face_rule.idl
index 2e2a7530a30..074647a4b1b 100644
--- a/chromium/third_party/blink/renderer/core/css/css_font_face_rule.idl
+++ b/chromium/third_party/blink/renderer/core/css/css_font_face_rule.idl
@@ -20,6 +20,8 @@
// https://drafts.csswg.org/css-fonts/#om-fontface
-interface CSSFontFaceRule : CSSRule {
+[
+ Exposed=Window
+] interface CSSFontFaceRule : CSSRule {
[Measure] readonly attribute CSSStyleDeclaration style;
};
diff --git a/chromium/third_party/blink/renderer/core/css/css_font_face_source.h b/chromium/third_party/blink/renderer/core/css/css_font_face_source.h
index c0d4dcf95b3..9ae4aa78d58 100644
--- a/chromium/third_party/blink/renderer/core/css/css_font_face_source.h
+++ b/chromium/third_party/blink/renderer/core/css/css_font_face_source.h
@@ -70,6 +70,10 @@ class CORE_EXPORT CSSFontFaceSource
virtual bool IsInBlockPeriod() const { return false; }
virtual bool IsInFailurePeriod() const { return false; }
+ // Recalculate the font loading timeline period for the font face.
+ // https://drafts.csswg.org/css-fonts-4/#font-display-timeline
+ virtual bool UpdatePeriod() { return false; }
+
// For UMA reporting
virtual bool HadBlankText() { return false; }
virtual void PaintRequested() {}
diff --git a/chromium/third_party/blink/renderer/core/css/css_font_face_src_value.cc b/chromium/third_party/blink/renderer/core/css/css_font_face_src_value.cc
index 75f347ac69e..928d9462520 100644
--- a/chromium/third_party/blink/renderer/core/css/css_font_face_src_value.cc
+++ b/chromium/third_party/blink/renderer/core/css/css_font_face_src_value.cc
@@ -88,8 +88,11 @@ FontResource& CSSFontFaceSrcValue::Fetch(ExecutionContext* context,
resource_request.SetReferrerPolicy(
ReferrerPolicyResolveDefault(referrer_.referrer_policy));
resource_request.SetReferrerString(referrer_.referrer);
+ if (is_ad_related_)
+ resource_request.SetIsAdResource();
ResourceLoaderOptions options;
options.initiator_info.name = fetch_initiator_type_names::kCSS;
+ options.initiator_info.referrer = referrer_.referrer;
FetchParameters params(std::move(resource_request), options);
if (base::FeatureList::IsEnabled(
features::kWebFontsCacheAwareTimeoutAdaption)) {
diff --git a/chromium/third_party/blink/renderer/core/css/css_font_face_src_value.h b/chromium/third_party/blink/renderer/core/css/css_font_face_src_value.h
index b51006a53bc..00e9e461eef 100644
--- a/chromium/third_party/blink/renderer/core/css/css_font_face_src_value.h
+++ b/chromium/third_party/blink/renderer/core/css/css_font_face_src_value.h
@@ -45,18 +45,20 @@ class CORE_EXPORT CSSFontFaceSrcValue : public CSSValue {
const String& absolute_resource,
const Referrer& referrer,
network::mojom::CSPDisposition should_check_content_security_policy,
- OriginClean origin_clean) {
+ OriginClean origin_clean,
+ bool is_ad_related) {
return MakeGarbageCollected<CSSFontFaceSrcValue>(
specified_resource, absolute_resource, referrer, false,
- should_check_content_security_policy, origin_clean);
+ should_check_content_security_policy, origin_clean, is_ad_related);
}
static CSSFontFaceSrcValue* CreateLocal(
const String& absolute_resource,
network::mojom::CSPDisposition should_check_content_security_policy,
- OriginClean origin_clean) {
+ OriginClean origin_clean,
+ bool is_ad_related) {
return MakeGarbageCollected<CSSFontFaceSrcValue>(
g_empty_string, absolute_resource, Referrer(), true,
- should_check_content_security_policy, origin_clean);
+ should_check_content_security_policy, origin_clean, is_ad_related);
}
CSSFontFaceSrcValue(
@@ -65,7 +67,8 @@ class CORE_EXPORT CSSFontFaceSrcValue : public CSSValue {
const Referrer& referrer,
bool local,
network::mojom::CSPDisposition should_check_content_security_policy,
- OriginClean origin_clean)
+ OriginClean origin_clean,
+ bool is_ad_related)
: CSSValue(kFontFaceSrcClass),
absolute_resource_(absolute_resource),
specified_resource_(specified_resource),
@@ -73,7 +76,8 @@ class CORE_EXPORT CSSFontFaceSrcValue : public CSSValue {
is_local_(local),
should_check_content_security_policy_(
should_check_content_security_policy),
- origin_clean_(origin_clean) {}
+ origin_clean_(origin_clean),
+ is_ad_related_(is_ad_related) {}
const String& GetResource() const { return absolute_resource_; }
const String& Format() const { return format_; }
@@ -106,6 +110,7 @@ class CORE_EXPORT CSSFontFaceSrcValue : public CSSValue {
const bool is_local_;
const network::mojom::CSPDisposition should_check_content_security_policy_;
const OriginClean origin_clean_;
+ bool is_ad_related_;
class FontResourceHelper : public GarbageCollected<FontResourceHelper>,
public FontResourceClient {
diff --git a/chromium/third_party/blink/renderer/core/css/css_font_selector.cc b/chromium/third_party/blink/renderer/core/css/css_font_selector.cc
index 7708bc41cfa..fb466e3a2a3 100644
--- a/chromium/third_party/blink/renderer/core/css/css_font_selector.cc
+++ b/chromium/third_party/blink/renderer/core/css/css_font_selector.cc
@@ -37,6 +37,7 @@
#include "third_party/blink/renderer/core/frame/web_feature.h"
#include "third_party/blink/renderer/core/loader/frame_loader.h"
#include "third_party/blink/renderer/platform/fonts/font_cache.h"
+#include "third_party/blink/renderer/platform/fonts/font_fallback_map.h"
#include "third_party/blink/renderer/platform/fonts/font_matching_metrics.h"
#include "third_party/blink/renderer/platform/fonts/font_selector_client.h"
#include "third_party/blink/renderer/platform/fonts/simple_font_data.h"
@@ -72,24 +73,25 @@ void CSSFontSelector::UnregisterForInvalidationCallbacks(
clients_.erase(client);
}
-void CSSFontSelector::DispatchInvalidationCallbacks() {
+void CSSFontSelector::DispatchInvalidationCallbacks(
+ FontInvalidationReason reason) {
font_face_cache_.IncrementVersion();
HeapVector<Member<FontSelectorClient>> clients;
CopyToVector(clients_, clients);
for (auto& client : clients) {
if (client) {
- client->FontsNeedUpdate(this);
+ client->FontsNeedUpdate(this, reason);
}
}
}
-void CSSFontSelector::FontFaceInvalidated() {
- DispatchInvalidationCallbacks();
+void CSSFontSelector::FontFaceInvalidated(FontInvalidationReason reason) {
+ DispatchInvalidationCallbacks(reason);
}
void CSSFontSelector::FontCacheInvalidated() {
- DispatchInvalidationCallbacks();
+ DispatchInvalidationCallbacks(FontInvalidationReason::kGeneralInvalidation);
}
scoped_refptr<FontData> CSSFontSelector::GetFontData(
diff --git a/chromium/third_party/blink/renderer/core/css/css_font_selector.h b/chromium/third_party/blink/renderer/core/css/css_font_selector.h
index 62baf6b8639..fb07ea47607 100644
--- a/chromium/third_party/blink/renderer/core/css/css_font_selector.h
+++ b/chromium/third_party/blink/renderer/core/css/css_font_selector.h
@@ -70,7 +70,7 @@ class CORE_EXPORT CSSFontSelector : public FontSelector {
bool IsPlatformFamilyMatchAvailable(const FontDescription&,
const AtomicString& family) override;
- void FontFaceInvalidated() override;
+ void FontFaceInvalidated(FontInvalidationReason) override;
// FontCacheClient implementation
void FontCacheInvalidated() override;
@@ -91,7 +91,7 @@ class CORE_EXPORT CSSFontSelector : public FontSelector {
void Trace(Visitor*) override;
protected:
- void DispatchInvalidationCallbacks();
+ void DispatchInvalidationCallbacks(FontInvalidationReason);
private:
// TODO(Oilpan): Ideally this should just be a traced Member but that will
diff --git a/chromium/third_party/blink/renderer/core/css/css_image_set_value.cc b/chromium/third_party/blink/renderer/core/css/css_image_set_value.cc
index 6a9f23a83df..3cc48f2f6b9 100644
--- a/chromium/third_party/blink/renderer/core/css/css_image_set_value.cc
+++ b/chromium/third_party/blink/renderer/core/css/css_image_set_value.cc
@@ -67,6 +67,12 @@ void CSSImageSetValue::FillImageSet() {
image.referrer.referrer = image_value.GetReferrer().referrer;
image.referrer.referrer_policy = image_value.GetReferrer().referrer_policy;
image.scale_factor = scale_factor;
+
+ // Only set for the first image as all images in a set should have identical
+ // is_ad_related bits.
+ if (!images_in_set_.size())
+ is_ad_related_ = image_value.GetIsAdRelated();
+ DCHECK_EQ(is_ad_related_, image_value.GetIsAdRelated());
images_in_set_.push_back(image);
++i;
}
@@ -101,7 +107,7 @@ StyleImage* CSSImageSetValue::CachedImage(float device_scale_factor) const {
StyleImage* CSSImageSetValue::CacheImage(
const Document& document,
float device_scale_factor,
- FetchParameters::ImageRequestOptimization image_request_optimization,
+ FetchParameters::ImageRequestBehavior image_request_behavior,
CrossOriginAttributeValue cross_origin) {
if (!images_in_set_.size())
FillImageSet();
@@ -116,10 +122,13 @@ StyleImage* CSSImageSetValue::CacheImage(
resource_request.SetReferrerPolicy(
ReferrerPolicyResolveDefault(image.referrer.referrer_policy));
resource_request.SetReferrerString(image.referrer.referrer);
+ if (is_ad_related_)
+ resource_request.SetIsAdResource();
ResourceLoaderOptions options;
options.initiator_info.name = parser_mode_ == kUASheetMode
? fetch_initiator_type_names::kUacss
: fetch_initiator_type_names::kCSS;
+ options.initiator_info.referrer = image.referrer.referrer;
FetchParameters params(std::move(resource_request), options);
if (cross_origin != kCrossOriginAttributeNotSet) {
diff --git a/chromium/third_party/blink/renderer/core/css/css_image_set_value.h b/chromium/third_party/blink/renderer/core/css/css_image_set_value.h
index 846cebf49a0..0b474dc65c7 100644
--- a/chromium/third_party/blink/renderer/core/css/css_image_set_value.h
+++ b/chromium/third_party/blink/renderer/core/css/css_image_set_value.h
@@ -49,7 +49,7 @@ class CSSImageSetValue : public CSSValueList {
StyleImage* CacheImage(
const Document&,
float device_scale_factor,
- FetchParameters::ImageRequestOptimization,
+ FetchParameters::ImageRequestBehavior,
CrossOriginAttributeValue = kCrossOriginAttributeNotSet);
String CustomCSSText() const;
@@ -77,9 +77,10 @@ class CSSImageSetValue : public CSSValueList {
return first.scale_factor < second.scale_factor;
}
- float cached_scale_factor_;
Member<StyleImage> cached_image_;
+ float cached_scale_factor_;
+ bool is_ad_related_ = false;
CSSParserMode parser_mode_;
Vector<ImageWithScale> images_in_set_;
};
diff --git a/chromium/third_party/blink/renderer/core/css/css_image_value.cc b/chromium/third_party/blink/renderer/core/css/css_image_value.cc
index 118e1179436..018ad1720cb 100644
--- a/chromium/third_party/blink/renderer/core/css/css_image_value.cc
+++ b/chromium/third_party/blink/renderer/core/css/css_image_value.cc
@@ -43,26 +43,21 @@ CSSImageValue::CSSImageValue(const AtomicString& raw_value,
const KURL& url,
const Referrer& referrer,
OriginClean origin_clean,
+ bool is_ad_related,
StyleImage* image)
: CSSValue(kImageClass),
relative_url_(raw_value),
referrer_(referrer),
absolute_url_(url.GetString()),
cached_image_(image),
- origin_clean_(origin_clean) {}
-
-CSSImageValue::CSSImageValue(const AtomicString& absolute_url,
- OriginClean origin_clean)
- : CSSValue(kImageClass),
- relative_url_(absolute_url),
- absolute_url_(absolute_url),
- origin_clean_(OriginClean::kFalse) {}
+ origin_clean_(origin_clean),
+ is_ad_related_(is_ad_related) {}
CSSImageValue::~CSSImageValue() = default;
StyleImage* CSSImageValue::CacheImage(
const Document& document,
- FetchParameters::ImageRequestOptimization image_request_optimization,
+ FetchParameters::ImageRequestBehavior image_request_behavior,
CrossOriginAttributeValue cross_origin) {
if (!cached_image_) {
if (absolute_url_.IsEmpty())
@@ -71,10 +66,13 @@ StyleImage* CSSImageValue::CacheImage(
resource_request.SetReferrerPolicy(
ReferrerPolicyResolveDefault(referrer_.referrer_policy));
resource_request.SetReferrerString(referrer_.referrer);
+ if (is_ad_related_)
+ resource_request.SetIsAdResource();
ResourceLoaderOptions options;
options.initiator_info.name = initiator_name_.IsEmpty()
? fetch_initiator_type_names::kCSS
: initiator_name_;
+ options.initiator_info.referrer = referrer_.referrer;
FetchParameters params(std::move(resource_request), options);
if (cross_origin != kCrossOriginAttributeNotSet) {
@@ -83,7 +81,7 @@ StyleImage* CSSImageValue::CacheImage(
}
bool is_lazily_loaded =
- image_request_optimization == FetchParameters::kDeferImageLoad &&
+ image_request_behavior == FetchParameters::kDeferImageLoad &&
// Only http/https images are eligible to be lazily loaded.
params.Url().ProtocolIsInHTTPFamily();
if (is_lazily_loaded) {
diff --git a/chromium/third_party/blink/renderer/core/css/css_image_value.h b/chromium/third_party/blink/renderer/core/css/css_image_value.h
index 39469eeb232..ed57fce9a75 100644
--- a/chromium/third_party/blink/renderer/core/css/css_image_value.h
+++ b/chromium/third_party/blink/renderer/core/css/css_image_value.h
@@ -43,8 +43,8 @@ class CORE_EXPORT CSSImageValue : public CSSValue {
const KURL&,
const Referrer&,
OriginClean origin_clean,
+ bool is_ad_related,
StyleImage* image = nullptr);
- CSSImageValue(const AtomicString& absolute_url, OriginClean origin_clean);
~CSSImageValue();
bool IsCachePending() const { return !cached_image_; }
@@ -54,13 +54,14 @@ class CORE_EXPORT CSSImageValue : public CSSValue {
}
StyleImage* CacheImage(
const Document&,
- FetchParameters::ImageRequestOptimization,
+ FetchParameters::ImageRequestBehavior,
CrossOriginAttributeValue = kCrossOriginAttributeNotSet);
const String& Url() const { return absolute_url_; }
const String& RelativeUrl() const { return relative_url_; }
const Referrer& GetReferrer() const { return referrer_; }
+ bool GetIsAdRelated() const { return is_ad_related_; }
void ReResolveURL(const Document&) const;
@@ -75,13 +76,13 @@ class CORE_EXPORT CSSImageValue : public CSSValue {
CSSImageValue* ValueWithURLMadeAbsolute() const {
return MakeGarbageCollected<CSSImageValue>(
absolute_url_, KURL(absolute_url_), Referrer(), origin_clean_,
- cached_image_.Get());
+ is_ad_related_, cached_image_.Get());
}
CSSImageValue* Clone() const {
return MakeGarbageCollected<CSSImageValue>(
relative_url_, KURL(absolute_url_), Referrer(), origin_clean_,
- cached_image_.Get());
+ is_ad_related_, cached_image_.Get());
}
void SetInitiator(const AtomicString& name) { initiator_name_ = name; }
@@ -101,6 +102,9 @@ class CORE_EXPORT CSSImageValue : public CSSValue {
// Whether the stylesheet that requested this image is origin-clean:
// https://drafts.csswg.org/cssom-1/#concept-css-style-sheet-origin-clean-flag
const OriginClean origin_clean_;
+
+ // Whether this was created by an ad-related CSSParserContext.
+ const bool is_ad_related_;
};
template <>
diff --git a/chromium/third_party/blink/renderer/core/css/css_light_dark_color_pair_test.cc b/chromium/third_party/blink/renderer/core/css/css_light_dark_color_pair_test.cc
deleted file mode 100644
index e3523d7c609..00000000000
--- a/chromium/third_party/blink/renderer/core/css/css_light_dark_color_pair_test.cc
+++ /dev/null
@@ -1,42 +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/core/css/css_light_dark_color_pair.h"
-
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/renderer/core/css/parser/css_parser.h"
-
-namespace blink {
-
-namespace {
-
-const CSSValue* CreateLightDarkColorPair(const char* value) {
- auto* ua_context = MakeGarbageCollected<CSSParserContext>(
- kUASheetMode, SecureContextMode::kInsecureContext);
- return CSSParser::ParseSingleValue(CSSPropertyID::kColor, value, ua_context);
-}
-
-TEST(CSSLightDarkColorPairTest, Equals) {
- const auto* value1 =
- CreateLightDarkColorPair("-internal-light-dark-color(red, green)");
- const auto* value2 =
- CreateLightDarkColorPair("-internal-light-dark-color(red, green)");
- const auto* value3 =
- CreateLightDarkColorPair("-internal-light-dark-color(#000, #fff)");
- const auto* value4 = CreateLightDarkColorPair(
- "-internal-light-dark-color(rgb(0, 0, 0), rgb(255, 255, 255))");
- ASSERT_TRUE(value1);
- ASSERT_TRUE(value2);
- ASSERT_TRUE(value3);
- ASSERT_TRUE(value4);
- EXPECT_TRUE(*value1 == *value1);
- EXPECT_TRUE(*value1 == *value2);
- EXPECT_TRUE(*value3 == *value3);
- EXPECT_TRUE(*value4 == *value4);
- EXPECT_TRUE(*value3 == *value4);
-}
-
-} // namespace
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/css_light_dark_color_pair.cc b/chromium/third_party/blink/renderer/core/css/css_light_dark_value_pair.cc
index 201654e4264..543745cab06 100644
--- a/chromium/third_party/blink/renderer/core/css/css_light_dark_color_pair.cc
+++ b/chromium/third_party/blink/renderer/core/css/css_light_dark_value_pair.cc
@@ -2,14 +2,14 @@
// 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/core/css/css_light_dark_color_pair.h"
+#include "third_party/blink/renderer/core/css/css_light_dark_value_pair.h"
namespace blink {
-String CSSLightDarkColorPair::CustomCSSText() const {
+String CSSLightDarkValuePair::CustomCSSText() const {
String first = First().CssText();
String second = Second().CssText();
- return "-internal-light-dark-color(" + first + ", " + second + ")";
+ return "-internal-light-dark(" + first + ", " + second + ")";
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/css_light_dark_color_pair.h b/chromium/third_party/blink/renderer/core/css/css_light_dark_value_pair.h
index 994dc1b35fa..ecac48a85a6 100644
--- a/chromium/third_party/blink/renderer/core/css/css_light_dark_color_pair.h
+++ b/chromium/third_party/blink/renderer/core/css/css_light_dark_value_pair.h
@@ -2,17 +2,17 @@
// 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_CORE_CSS_CSS_LIGHT_DARK_COLOR_PAIR_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_LIGHT_DARK_COLOR_PAIR_H_
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_LIGHT_DARK_VALUE_PAIR_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_LIGHT_DARK_VALUE_PAIR_H_
#include "third_party/blink/renderer/core/css/css_value_pair.h"
namespace blink {
-class CORE_EXPORT CSSLightDarkColorPair : public CSSValuePair {
+class CORE_EXPORT CSSLightDarkValuePair : public CSSValuePair {
public:
- CSSLightDarkColorPair(const CSSValue* first, const CSSValue* second)
- : CSSValuePair(kLightDarkColorPairClass, first, second) {}
+ CSSLightDarkValuePair(const CSSValue* first, const CSSValue* second)
+ : CSSValuePair(kLightDarkValuePairClass, first, second) {}
String CustomCSSText() const;
void TraceAfterDispatch(blink::Visitor* visitor) const {
CSSValuePair::TraceAfterDispatch(visitor);
@@ -20,12 +20,12 @@ class CORE_EXPORT CSSLightDarkColorPair : public CSSValuePair {
};
template <>
-struct DowncastTraits<CSSLightDarkColorPair> {
+struct DowncastTraits<CSSLightDarkValuePair> {
static bool AllowFrom(const CSSValue& value) {
- return value.IsLightDarkColorPair();
+ return value.IsLightDarkValuePair();
}
};
} // namespace blink
-#endif // THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_LIGHT_DARK_COLOR_PAIR_H_
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_LIGHT_DARK_VALUE_PAIR_H_
diff --git a/chromium/third_party/blink/renderer/core/css/css_light_dark_value_pair_test.cc b/chromium/third_party/blink/renderer/core/css/css_light_dark_value_pair_test.cc
new file mode 100644
index 00000000000..a77871ee6fc
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/css/css_light_dark_value_pair_test.cc
@@ -0,0 +1,65 @@
+// 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/core/css/css_light_dark_value_pair.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/core/css/parser/css_parser.h"
+
+namespace blink {
+
+namespace {
+
+const CSSValue* ParseUAPropertyValue(CSSPropertyID id, const char* value) {
+ auto* ua_context = MakeGarbageCollected<CSSParserContext>(
+ kUASheetMode, SecureContextMode::kInsecureContext);
+ return CSSParser::ParseSingleValue(id, value, ua_context);
+}
+
+TEST(CSSLightDarkValuePairTest, ColorEquals) {
+ const auto* value1 = ParseUAPropertyValue(CSSPropertyID::kColor,
+ "-internal-light-dark(red, green)");
+ const auto* value2 = ParseUAPropertyValue(CSSPropertyID::kColor,
+ "-internal-light-dark(red, green)");
+ const auto* value3 = ParseUAPropertyValue(CSSPropertyID::kColor,
+ "-internal-light-dark(#000, #fff)");
+ const auto* value4 = ParseUAPropertyValue(
+ CSSPropertyID::kColor,
+ "-internal-light-dark(rgb(0, 0, 0), rgb(255, 255, 255))");
+ ASSERT_TRUE(value1);
+ ASSERT_TRUE(value2);
+ ASSERT_TRUE(value3);
+ ASSERT_TRUE(value4);
+ EXPECT_TRUE(*value1 == *value1);
+ EXPECT_TRUE(*value1 == *value2);
+ EXPECT_TRUE(*value3 == *value3);
+ EXPECT_TRUE(*value4 == *value4);
+ EXPECT_TRUE(*value3 == *value4);
+}
+
+TEST(CSSLightDarkValuePairTest, BackgroundImageEquals) {
+ const auto* value1 =
+ ParseUAPropertyValue(CSSPropertyID::kBackgroundImage,
+ "-internal-light-dark(none, url(dark.png))");
+ const auto* value2 =
+ ParseUAPropertyValue(CSSPropertyID::kBackgroundImage,
+ "-internal-light-dark(none, url(dark.png))");
+ const auto* value3 = ParseUAPropertyValue(CSSPropertyID::kBackgroundImage,
+ "-internal-light-dark(none, none)");
+ const auto* value4 =
+ ParseUAPropertyValue(CSSPropertyID::kBackgroundImage, "none");
+ ASSERT_TRUE(value1);
+ ASSERT_TRUE(value2);
+ ASSERT_TRUE(value3);
+ ASSERT_TRUE(value4);
+ EXPECT_TRUE(*value1 == *value1);
+ EXPECT_TRUE(*value1 == *value2);
+ EXPECT_TRUE(*value3 == *value3);
+ EXPECT_TRUE(*value4 == *value4);
+ EXPECT_FALSE(*value3 == *value4);
+}
+
+} // namespace
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/css_math_expression_node.cc b/chromium/third_party/blink/renderer/core/css/css_math_expression_node.cc
index b274e03e1fe..b60c35e45f7 100644
--- a/chromium/third_party/blink/renderer/core/css/css_math_expression_node.cc
+++ b/chromium/third_party/blink/renderer/core/css/css_math_expression_node.cc
@@ -229,10 +229,7 @@ double CSSMathExpressionNumericLiteral::ComputeLengthPx(
case kCalcAngle:
case kCalcFrequency:
case kCalcPercentLength:
- case kCalcPercentNumber:
case kCalcTime:
- case kCalcLengthNumber:
- case kCalcPercentLengthNumber:
case kCalcOther:
NOTREACHED();
break;
@@ -285,43 +282,26 @@ bool CSSMathExpressionNumericLiteral::InvolvesPercentageComparisons() const {
// ------ End of CSSMathExpressionNumericLiteral member functions
static const CalculationCategory kAddSubtractResult[kCalcOther][kCalcOther] = {
- /* CalcNumber */ {kCalcNumber, kCalcLengthNumber, kCalcPercentNumber,
- kCalcPercentNumber, kCalcOther, kCalcOther, kCalcOther,
- kCalcOther, kCalcLengthNumber, kCalcPercentLengthNumber},
+ /* CalcNumber */ {kCalcNumber, kCalcOther, kCalcOther, kCalcOther,
+ kCalcOther, kCalcOther, kCalcOther},
/* CalcLength */
- {kCalcLengthNumber, kCalcLength, kCalcPercentLength, kCalcOther,
- kCalcPercentLength, kCalcOther, kCalcOther, kCalcOther, kCalcLengthNumber,
- kCalcPercentLengthNumber},
+ {kCalcOther, kCalcLength, kCalcPercentLength, kCalcPercentLength,
+ kCalcOther, kCalcOther, kCalcOther},
/* CalcPercent */
- {kCalcPercentNumber, kCalcPercentLength, kCalcPercent, kCalcPercentNumber,
- kCalcPercentLength, kCalcOther, kCalcOther, kCalcOther,
- kCalcPercentLengthNumber, kCalcPercentLengthNumber},
- /* CalcPercentNumber */
- {kCalcPercentNumber, kCalcPercentLengthNumber, kCalcPercentNumber,
- kCalcPercentNumber, kCalcPercentLengthNumber, kCalcOther, kCalcOther,
- kCalcOther, kCalcOther, kCalcPercentLengthNumber},
+ {kCalcOther, kCalcPercentLength, kCalcPercent, kCalcPercentLength,
+ kCalcOther, kCalcOther, kCalcOther},
/* CalcPercentLength */
- {kCalcPercentLengthNumber, kCalcPercentLength, kCalcPercentLength,
- kCalcPercentLengthNumber, kCalcPercentLength, kCalcOther, kCalcOther,
- kCalcOther, kCalcOther, kCalcPercentLengthNumber},
+ {kCalcOther, kCalcPercentLength, kCalcPercentLength, kCalcPercentLength,
+ kCalcOther, kCalcOther, kCalcOther},
/* CalcAngle */
- {kCalcOther, kCalcOther, kCalcOther, kCalcOther, kCalcOther, kCalcAngle,
- kCalcOther, kCalcOther, kCalcOther, kCalcOther},
+ {kCalcOther, kCalcOther, kCalcOther, kCalcOther, kCalcAngle, kCalcOther,
+ kCalcOther},
/* CalcTime */
- {kCalcOther, kCalcOther, kCalcOther, kCalcOther, kCalcOther, kCalcOther,
- kCalcTime, kCalcOther, kCalcOther, kCalcOther},
+ {kCalcOther, kCalcOther, kCalcOther, kCalcOther, kCalcOther, kCalcTime,
+ kCalcOther},
/* CalcFrequency */
{kCalcOther, kCalcOther, kCalcOther, kCalcOther, kCalcOther, kCalcOther,
- kCalcOther, kCalcFrequency, kCalcOther, kCalcOther},
- /* CalcLengthNumber */
- {kCalcLengthNumber, kCalcLengthNumber, kCalcPercentLengthNumber,
- kCalcPercentLengthNumber, kCalcPercentLengthNumber, kCalcOther, kCalcOther,
- kCalcOther, kCalcLengthNumber, kCalcPercentLengthNumber},
- /* CalcPercentLengthNumber */
- {kCalcPercentLengthNumber, kCalcPercentLengthNumber,
- kCalcPercentLengthNumber, kCalcPercentLengthNumber,
- kCalcPercentLengthNumber, kCalcOther, kCalcOther, kCalcOther,
- kCalcPercentLengthNumber, kCalcPercentLengthNumber}};
+ kCalcFrequency}};
static CalculationCategory DetermineCategory(
const CSSMathExpressionNode& left_side,
@@ -729,9 +709,6 @@ CSSPrimitiveValue::UnitType CSSMathExpressionBinaryOperation::ResolvedUnitType()
case kCalcFrequency:
return CSSPrimitiveValue::UnitType::kHertz;
case kCalcPercentLength:
- case kCalcPercentNumber:
- case kCalcLengthNumber:
- case kCalcPercentLengthNumber:
case kCalcOther:
return CSSPrimitiveValue::UnitType::kUnknown;
}
diff --git a/chromium/third_party/blink/renderer/core/css/css_math_expression_node.h b/chromium/third_party/blink/renderer/core/css/css_math_expression_node.h
index b1e932b61dc..1d1b76f0006 100644
--- a/chromium/third_party/blink/renderer/core/css/css_math_expression_node.h
+++ b/chromium/third_party/blink/renderer/core/css/css_math_expression_node.h
@@ -47,17 +47,14 @@ class CSSNumericLiteralValue;
// The order of this enum should not change since its elements are used as
// indices in the addSubtractResult matrix.
enum CalculationCategory {
- kCalcNumber = 0,
+ kCalcNumber,
kCalcLength,
kCalcPercent,
- kCalcPercentNumber,
kCalcPercentLength,
kCalcAngle,
kCalcTime,
kCalcFrequency,
- kCalcLengthNumber,
- kCalcPercentLengthNumber,
- kCalcOther
+ kCalcOther,
};
class CORE_EXPORT CSSMathExpressionNode
@@ -121,9 +118,7 @@ class CORE_EXPORT CSSMathExpressionNode
CalculationCategory Category() const { return category_; }
bool HasPercentage() const {
- return category_ == kCalcPercent || category_ == kCalcPercentNumber ||
- category_ == kCalcPercentLength ||
- category_ == kCalcPercentLengthNumber;
+ return category_ == kCalcPercent || category_ == kCalcPercentLength;
}
// Returns the unit type of the math expression *without doing any type
diff --git a/chromium/third_party/blink/renderer/core/css/css_properties.json5 b/chromium/third_party/blink/renderer/core/css/css_properties.json5
index 6ec7f584d08..4982b995445 100644
--- a/chromium/third_party/blink/renderer/core/css/css_properties.json5
+++ b/chromium/third_party/blink/renderer/core/css/css_properties.json5
@@ -83,8 +83,8 @@
// - is_descriptor
// Whether it is a CSS descriptor. Descriptors define the characteristics of
- // an at-rule. E.g. @viewport is an at-rule, and width is a valid descriptor
- // for @viewport. Descriptors and CSS properties with the same name are
+ // an at-rule. E.g. @font-face is an at-rule, and src is a valid descriptor
+ // for @font-face. Descriptors and CSS properties with the same name are
// handled together in this file.
// TODO(crbug.com/752745): Don't use CSSPropertyID for descriptors.
// - is_property
@@ -110,6 +110,16 @@
valid_type: "bool",
},
+ // - semi_independent_variable
+ // This property affects to the {Inherited, NonInherited}Variable data fields so that we
+ // can assume that the custom properties might not depend on any other property. We can
+ // handle these properties so that they are excluded from the shared Inherited/NohInherited
+ // logic, like the Equal and inheritance functions.
+ semi_independent_variable: {
+ default: false,
+ valid_type: "bool",
+ },
+
// - affected_by_all
// The affected_by_all flag indicates whether a change to the CSS property
// "all" affects this property.
@@ -145,6 +155,28 @@
valid_type: "bool",
},
+ // - computed_value_comparable
+ //
+ // If true, a CSSProperty::ComputedValuesEqual function is generated.
+ computed_value_comparable: {
+ default: false,
+ valid_type: "bool",
+ },
+
+ // - computed_value_compare_fields
+ //
+ // If present, the ComputedStyle fields listed will be used in the
+ // generated ComputedvaluesEqual function. This is useful if the value
+ // of a property is stored in multiple fields. For example, for
+ // vertical-align:
+ //
+ // computed_value_compare_fields: ['VerticalAlign', 'GetVerticalAlignLength']
+ //
+ // Has no effect unless computed_value_comparable is true.
+ computed_value_compare_fields: {
+ default: [],
+ },
+
// - runtime_flag
// The name of the flag on RuntimeEnabledFeatures
// (e.g. "CSSOverscrollBehavior") that conditionally enables the
@@ -448,6 +480,22 @@
default: false,
valid_type: "bool",
},
+
+ // - is_border
+ // The property, when used by the author, will disable any native
+ // appearance on UI elements.
+ is_border: {
+ default: false,
+ valid_type: "bool",
+ },
+
+ // - is_background
+ // The property, when used by the author, will disable any native
+ // appearance on UI elements.
+ is_background: {
+ default: false,
+ valid_type: "bool",
+ },
},
// Members in the data objects should appear in the same order as in the
@@ -672,6 +720,7 @@
style_builder_custom_functions: ["value"],
priority: "High",
valid_for_marker: true,
+ computed_value_comparable: true,
},
{
name: "font-family",
@@ -928,7 +977,7 @@
typedom_types: ["Keyword"],
default_value: "mixed",
getter: "GetTextOrientation",
- style_builder_custom_functions: ["value"],
+ style_builder_custom_functions: ["initial", "inherit", "value"],
priority: "High",
},
{
@@ -949,17 +998,19 @@
typedom_types: ["Keyword"],
default_value: "horizontal-tb",
type_name: "WritingMode",
- style_builder_custom_functions: ["value"],
+ style_builder_custom_functions: ["initial", "inherit", "value"],
priority: "High",
+ computed_value_comparable: true,
},
{
name: "-webkit-writing-mode",
property_methods: ["CSSValueFromComputedStyleInternal"],
inherited: true,
type_name: "WritingMode",
- style_builder_custom_functions: ["value"],
+ style_builder_custom_functions: ["initial", "inherit", "value"],
priority: "High",
surrogate_for: "writing-mode",
+ computed_value_comparable: true,
},
{
name: "text-rendering",
@@ -1069,6 +1120,7 @@
},
valid_for_first_letter: true,
valid_for_cue: true,
+ is_background: true,
},
{
name: "background-blend-mode",
@@ -1086,6 +1138,7 @@
fill_type_getter: "GetBlendMode",
},
valid_for_first_letter: true,
+ is_background: true,
},
{
name: "background-clip",
@@ -1099,6 +1152,7 @@
},
valid_for_first_letter: true,
valid_for_cue: true,
+ is_background: true,
},
{
name: "background-color",
@@ -1120,6 +1174,7 @@
affected_by_forced_colors: true,
valid_for_first_letter: true,
valid_for_cue: true,
+ is_background: true,
},
{
name: "background-image",
@@ -1135,6 +1190,7 @@
},
valid_for_first_letter: true,
valid_for_cue: true,
+ is_background: true,
},
{
name: "background-origin",
@@ -1148,6 +1204,7 @@
},
valid_for_first_letter: true,
valid_for_cue: true,
+ is_background: true,
},
{
name: "background-position-x",
@@ -1159,6 +1216,7 @@
},
valid_for_first_letter: true,
valid_for_cue: true,
+ is_background: true,
},
{
name: "background-position-y",
@@ -1170,6 +1228,7 @@
},
valid_for_first_letter: true,
valid_for_cue: true,
+ is_background: true,
},
{
name: "background-repeat-x",
@@ -1202,6 +1261,7 @@
},
valid_for_first_letter: true,
valid_for_cue: true,
+ is_background: true,
},
{
name: "baseline-shift",
@@ -1228,6 +1288,8 @@
style_builder_template: "color",
affected_by_forced_colors: true,
valid_for_first_letter: true,
+ is_border: true,
+ computed_value_comparable: true,
},
{
name: "border-bottom-left-radius",
@@ -1241,6 +1303,7 @@
converter: "ConvertRadius",
typedom_types: ["Length", "Percentage"],
valid_for_first_letter: true,
+ is_border: true,
},
{
name: "border-bottom-right-radius",
@@ -1254,6 +1317,7 @@
converter: "ConvertRadius",
typedom_types: ["Length", "Percentage"],
valid_for_first_letter: true,
+ is_border: true,
},
{
name: "border-bottom-style",
@@ -1268,6 +1332,7 @@
default_value: "none",
type_name: "EBorderStyle",
valid_for_first_letter: true,
+ is_border: true,
},
{
name: "border-bottom-width",
@@ -1283,6 +1348,7 @@
computed_style_custom_functions: ["getter", "setter"],
converter: "ConvertBorderWidth",
valid_for_first_letter: true,
+ is_border: true,
},
{
name: "border-collapse",
@@ -1304,6 +1370,7 @@
modifier_type: "Outset",
},
valid_for_first_letter: true,
+ is_border: true,
},
{
name: "border-image-repeat",
@@ -1315,6 +1382,7 @@
modifier_type: "Repeat",
},
valid_for_first_letter: true,
+ is_border: true,
},
{
name: "border-image-slice",
@@ -1326,6 +1394,7 @@
modifier_type: "Slice",
},
valid_for_first_letter: true,
+ is_border: true,
},
{
name: "border-image-source",
@@ -1335,6 +1404,7 @@
typedom_types: ["Keyword", "Image"],
style_builder_custom_functions: ["value"],
valid_for_first_letter: true,
+ is_border: true,
},
{
name: "border-image-width",
@@ -1347,6 +1417,7 @@
modifier_type: "Width",
},
valid_for_first_letter: true,
+ is_border: true,
},
{
name: "border-left-color",
@@ -1364,6 +1435,8 @@
style_builder_template: "color",
affected_by_forced_colors: true,
valid_for_first_letter: true,
+ is_border: true,
+ computed_value_comparable: true,
},
{
name: "border-left-style",
@@ -1378,6 +1451,7 @@
default_value: "none",
type_name: "EBorderStyle",
valid_for_first_letter: true,
+ is_border: true,
},
{
name: "border-left-width",
@@ -1393,6 +1467,7 @@
computed_style_custom_functions: ["getter", "setter"],
converter: "ConvertBorderWidth",
valid_for_first_letter: true,
+ is_border: true,
},
{
name: "border-right-color",
@@ -1410,6 +1485,8 @@
style_builder_template: "color",
affected_by_forced_colors: true,
valid_for_first_letter: true,
+ is_border: true,
+ computed_value_comparable: true,
},
{
name: "border-right-style",
@@ -1424,6 +1501,7 @@
default_value: "none",
type_name: "EBorderStyle",
valid_for_first_letter: true,
+ is_border: true,
},
{
name: "border-right-width",
@@ -1439,6 +1517,7 @@
computed_style_custom_functions: ["getter", "setter"],
converter: "ConvertBorderWidth",
valid_for_first_letter: true,
+ is_border: true,
},
{
name: "border-top-color",
@@ -1456,6 +1535,8 @@
style_builder_template: "color",
affected_by_forced_colors: true,
valid_for_first_letter: true,
+ is_border: true,
+ computed_value_comparable: true,
},
{
name: "border-top-left-radius",
@@ -1469,6 +1550,7 @@
converter: "ConvertRadius",
typedom_types: ["Length", "Percentage"],
valid_for_first_letter: true,
+ is_border: true,
},
{
name: "border-top-right-radius",
@@ -1482,6 +1564,7 @@
converter: "ConvertRadius",
typedom_types: ["Length", "Percentage"],
valid_for_first_letter: true,
+ is_border: true,
},
{
name: "border-top-style",
@@ -1496,6 +1579,7 @@
default_value: "none",
type_name: "EBorderStyle",
valid_for_first_letter: true,
+ is_border: true,
},
{
name: "border-top-width",
@@ -1511,6 +1595,7 @@
computed_style_custom_functions: ["getter", "setter"],
converter: "ConvertBorderWidth",
valid_for_first_letter: true,
+ is_border: true,
},
{
name: "bottom",
@@ -1523,6 +1608,7 @@
default_value: "Length()",
typedom_types: ["Keyword", "Length", "Percentage"],
converter: "ConvertLengthOrAuto",
+ computed_value_comparable: true,
},
{
name: "box-shadow",
@@ -2197,6 +2283,7 @@
default_value: "Length()",
typedom_types: ["Keyword", "Length", "Percentage"],
converter: "ConvertLengthOrAuto",
+ computed_value_comparable: true,
},
{
name: "letter-spacing",
@@ -2413,6 +2500,16 @@
runtime_flag: "CSSMathStyle"
},
{
+ name: "math-superscript-shift-style",
+ property_methods: ["CSSValueFromComputedStyleInternal"],
+ field_template: "keyword",
+ inherited: true,
+ keywords: ["inline", "display"],
+ typedom_types: ["Keyword"],
+ default_value: "display",
+ runtime_flag: "CSSMathSuperscriptShiftStyle"
+ },
+ {
name: "max-height",
property_methods: ["ParseSingleValue", "CSSValueFromComputedStyleInternal"],
is_descriptor: true,
@@ -2631,11 +2728,11 @@
property_methods: ["ParseSingleValue", "CSSValueFromComputedStyleInternal"],
interpolable: true,
field_group: "*",
- field_template: "primitive",
- default_value: "0",
- type_name: "int",
- computed_style_custom_functions: ["getter"],
- converter: "ConvertComputedLength<int>",
+ field_template: "external",
+ include_paths: ["third_party/blink/renderer/platform/geometry/layout_unit.h"],
+ default_value: "LayoutUnit(0)",
+ type_name: "LayoutUnit",
+ converter: "ConvertLayoutUnit",
typedom_types: ["Length"],
valid_for_cue: true,
},
@@ -2663,8 +2760,8 @@
include_paths: ["third_party/blink/renderer/platform/geometry/layout_unit.h"],
default_value: "LayoutUnit(3)",
type_name: "LayoutUnit",
- computed_style_custom_functions: ["initial", "getter", "setter"],
- converter: "ConvertLineWidth<unsigned short>",
+ computed_style_custom_functions: ["getter", "setter"],
+ converter: "ConvertBorderWidth",
keywords: ["thin", "medium", "thick"],
typedom_types: ["Keyword", "Length"],
valid_for_cue: true,
@@ -2825,6 +2922,17 @@
runtime_flag: "NamedPages"
},
{
+ name: "page-orientation",
+ is_descriptor: true,
+ field_template: "primitive",
+ field_group: "*",
+ type_name: "PageOrientation",
+ field_size: 2,
+ default_value: "PageOrientation::kUpright",
+ include_paths: ["third_party/blink/public/common/css/page_orientation.h"],
+ runtime_flag: "NamedPages"
+ },
+ {
name: "paint-order",
property_methods: ["ParseSingleValue", "CSSValueFromComputedStyleInternal"],
inherited: true,
@@ -2898,13 +3006,13 @@
typedom_types: ["Keyword"]
},
{
- name: "subtree-visibility",
+ name: "content-visibility",
property_methods: ["ParseSingleValue", "CSSValueFromComputedStyleInternal"],
field_template: "keyword",
keywords: ["visible", "auto", "hidden", "hidden-matchable"],
default_value: "visible",
typedom_types: ["Keyword"],
- runtime_flag: "CSSSubtreeVisibility"
+ runtime_flag: "CSSContentVisibility"
},
{
name: "resize",
@@ -2928,6 +3036,7 @@
default_value: "Length()",
typedom_types: ["Keyword", "Length", "Percentage"],
converter: "ConvertLengthOrAuto",
+ computed_value_comparable: true,
},
{
name: "r",
@@ -3464,6 +3573,22 @@
valid_for_cue: true,
},
{
+ name: "text-decoration-thickness",
+ runtime_flag: "UnderlineOffsetThickness",
+ property_methods: ["ParseSingleValue", "CSSValueFromComputedStyleInternal"],
+ # TODO: Move to core/style?
+ include_paths: ["third_party/blink/renderer/core/style/text_decoration_thickness.h"],
+ inherited: true,
+ field_group: "*",
+ field_template: "external",
+ type_name: "TextDecorationThickness",
+ default_value: "TextDecorationThickness(Length::Auto())",
+ converter: "ConvertTextDecorationThickness",
+ keywords: ["auto", "from-font"],
+ typedom_types: ["Keyword", "Length", "Percentage"],
+ valid_for_first_letter: true,
+ },
+ {
name: "text-indent",
property_methods: ["ParseSingleValue", "CSSValueFromComputedStyleInternal"],
interpolable: true,
@@ -3537,12 +3662,26 @@
independent: true,
inherited: true,
field_template: "keyword",
- keywords: ["capitalize", "uppercase", "lowercase", "none"],
+ keywords: ["capitalize", "uppercase", "lowercase", "none", "math-auto"],
typedom_types: ["Keyword"],
default_value: "none",
valid_for_first_letter: true,
},
{
+ name: "text-underline-offset",
+ property_methods: ["ParseSingleValue", "CSSValueFromComputedStyleInternal"],
+ inherited: true,
+ field_group: "*",
+ field_template: "<length>",
+ default_value: "Length()",
+ name_for_methods: "TextUnderlineOffset",
+ runtime_flag: "UnderlineOffsetThickness",
+ converter: "ConvertTextUnderlineOffset",
+ keywords: ["auto"],
+ typedom_types: ["Keyword", "Length", "Percentage"],
+ valid_for_first_letter: true,
+ },
+ {
name: "text-underline-position",
property_methods: ["ParseSingleValue", "CSSValueFromComputedStyleInternal"],
inherited: true,
@@ -3568,6 +3707,7 @@
default_value: "Length()",
typedom_types: ["Keyword", "Length", "Percentage"],
converter: "ConvertLengthOrAuto",
+ computed_value_comparable: true,
},
{
name: "touch-action",
@@ -3701,6 +3841,8 @@
typedom_types: ["Keyword", "Length", "Percentage"],
keywords: ["baseline", "sub", "super", "text-top", "text-bottom", "middle"],
valid_for_first_letter: true,
+ computed_value_comparable: true,
+ computed_value_compare_fields: ['VerticalAlign', 'GetVerticalAlignLength']
},
{
name: "visibility",
@@ -3732,8 +3874,8 @@
converter: "ConvertLength",
},
{
- name: "-webkit-appearance",
- property_methods: ["CSSValueFromComputedStyleInternal"],
+ name: "appearance",
+ property_methods: ["ParseSingleValue", "CSSValueFromComputedStyleInternal"],
field_group: "*",
field_size: 5,
field_template: "primitive",
@@ -3742,6 +3884,10 @@
type_name: "ControlPart",
},
{
+ name: "-webkit-appearance",
+ alias_for: "appearance",
+ },
+ {
name: "-webkit-app-region",
property_methods: ["CSSValueFromComputedStyleInternal"],
field_group: "*",
@@ -4169,6 +4315,15 @@
keywords: ["before", "after"],
default_value: "before",
type_name: "RubyPosition",
+ converter: "ConvertRubyPosition",
+ },
+ {
+ name: "ruby-position",
+ property_methods: ["CSSValueFromComputedStyleInternal"],
+ inherited: true,
+ type_name: "RubyPosition",
+ converter: "ConvertRubyPosition",
+ surrogate_for: "-webkit-ruby-position",
},
{
name: "-webkit-tap-highlight-color",
@@ -5697,18 +5852,6 @@
initial_color: "StyleColor::CurrentColor",
},
},
- {
- name: "-internal-effective-zoom",
- property_methods: ["ParseSingleValue"],
- inherited: true,
- field_template: "primitive",
- type_name: "float",
- default_value: "1.0f",
- field_group: "*",
- priority: "High",
- style_builder_custom_functions: ["initial", "inherit", "value"],
- surrogate_for: "zoom",
- },
// Name: -internal-empty-line-height:
// Value: none | fabricated
diff --git a/chromium/third_party/blink/renderer/core/css/css_properties_ranking.json5 b/chromium/third_party/blink/renderer/core/css/css_properties_ranking.json5
index 92919e7e046..9472321e728 100644
--- a/chromium/third_party/blink/renderer/core/css/css_properties_ranking.json5
+++ b/chromium/third_party/blink/renderer/core/css/css_properties_ranking.json5
@@ -693,7 +693,7 @@
"border-inline-width",
"inset-block-start",
"syntax",
- "subtree-visibility",
+ "content-visibility",
"origin-trial-test-property",
],
"properties": {}
diff --git a/chromium/third_party/blink/renderer/core/css/css_property_rule.cc b/chromium/third_party/blink/renderer/core/css/css_property_rule.cc
index 8910daf28af..4309e861c73 100644
--- a/chromium/third_party/blink/renderer/core/css/css_property_rule.cc
+++ b/chromium/third_party/blink/renderer/core/css/css_property_rule.cc
@@ -4,9 +4,12 @@
#include "third_party/blink/renderer/core/css/css_property_rule.h"
+#include "third_party/blink/renderer/core/css/css_identifier_value.h"
#include "third_party/blink/renderer/core/css/css_property_value_set.h"
+#include "third_party/blink/renderer/core/css/css_string_value.h"
#include "third_party/blink/renderer/core/css/style_rule.h"
#include "third_party/blink/renderer/core/css/style_rule_css_style_declaration.h"
+#include "third_party/blink/renderer/core/css_value_keywords.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
namespace blink {
@@ -17,32 +20,72 @@ CSSPropertyRule::CSSPropertyRule(StyleRuleProperty* property_rule,
CSSPropertyRule::~CSSPropertyRule() = default;
-CSSStyleDeclaration* CSSPropertyRule::style() const {
- if (!properties_cssom_wrapper_) {
- properties_cssom_wrapper_ =
- MakeGarbageCollected<StyleRuleCSSStyleDeclaration>(
- property_rule_->MutableProperties(),
- const_cast<CSSPropertyRule*>(this));
- }
-
- return properties_cssom_wrapper_.Get();
-}
-
String CSSPropertyRule::cssText() const {
- // TODO(https://crbug.com/978783): Implement this.
- return "";
+ // https://drafts.css-houdini.org/css-properties-values-api-1/#serialize-a-csspropertyrule
+ StringBuilder builder;
+ builder.Append("@property ");
+ builder.Append(property_rule_->GetName());
+ builder.Append(" { ");
+ if (const CSSValue* syntax = property_rule_->GetSyntax()) {
+ DCHECK(syntax->IsStringValue());
+ builder.Append("syntax: ");
+ builder.Append(syntax->CssText());
+ builder.Append("; ");
+ }
+ if (const CSSValue* inherits = property_rule_->Inherits()) {
+ DCHECK(*inherits == *CSSIdentifierValue::Create(CSSValueID::kTrue) ||
+ *inherits == *CSSIdentifierValue::Create(CSSValueID::kFalse));
+ builder.Append("inherits: ");
+ builder.Append(inherits->CssText());
+ builder.Append("; ");
+ }
+ if (const CSSValue* initial = property_rule_->GetInitialValue()) {
+ builder.Append("initial-value:");
+ builder.Append(initial->CssText());
+ builder.Append("; ");
+ }
+ builder.Append("}");
+ return builder.ToString();
}
void CSSPropertyRule::Reattach(StyleRuleBase* rule) {
DCHECK(rule);
property_rule_ = To<StyleRuleProperty>(rule);
- if (properties_cssom_wrapper_)
- properties_cssom_wrapper_->Reattach(property_rule_->MutableProperties());
+}
+
+String CSSPropertyRule::name() const {
+ return property_rule_->GetName();
+}
+
+String CSSPropertyRule::syntax() const {
+ if (const CSSValue* syntax = property_rule_->GetSyntax())
+ return To<CSSStringValue>(*syntax).Value();
+ return g_null_atom;
+}
+
+bool CSSPropertyRule::inherits() const {
+ if (const CSSValue* inherits = property_rule_->Inherits()) {
+ switch (To<CSSIdentifierValue>(*inherits).GetValueID()) {
+ case CSSValueID::kTrue:
+ return true;
+ case CSSValueID::kFalse:
+ return false;
+ default:
+ NOTREACHED();
+ break;
+ }
+ }
+ return false;
+}
+
+String CSSPropertyRule::initialValue() const {
+ if (const CSSValue* initial = property_rule_->GetInitialValue())
+ return initial->CssText();
+ return g_null_atom;
}
void CSSPropertyRule::Trace(Visitor* visitor) {
visitor->Trace(property_rule_);
- visitor->Trace(properties_cssom_wrapper_);
CSSRule::Trace(visitor);
}
diff --git a/chromium/third_party/blink/renderer/core/css/css_property_rule.h b/chromium/third_party/blink/renderer/core/css/css_property_rule.h
index 2b5f55aea45..ba5a0dafbf6 100644
--- a/chromium/third_party/blink/renderer/core/css/css_property_rule.h
+++ b/chromium/third_party/blink/renderer/core/css/css_property_rule.h
@@ -11,9 +11,7 @@
namespace blink {
-class CSSStyleDeclaration;
class StyleRuleProperty;
-class StyleRuleCSSStyleDeclaration;
class CSSPropertyRule final : public CSSRule {
DEFINE_WRAPPERTYPEINFO();
@@ -25,7 +23,10 @@ class CSSPropertyRule final : public CSSRule {
String cssText() const override;
void Reattach(StyleRuleBase*) override;
- CSSStyleDeclaration* style() const;
+ String name() const;
+ String syntax() const;
+ bool inherits() const;
+ String initialValue() const;
void Trace(Visitor*) override;
@@ -33,7 +34,6 @@ class CSSPropertyRule final : public CSSRule {
CSSRule::Type type() const override { return kPropertyRule; }
Member<StyleRuleProperty> property_rule_;
- mutable Member<StyleRuleCSSStyleDeclaration> properties_cssom_wrapper_;
};
template <>
diff --git a/chromium/third_party/blink/renderer/core/css/css_property_rule.idl b/chromium/third_party/blink/renderer/core/css/css_property_rule.idl
index 6ab4ed76dfd..90d05d5bcde 100644
--- a/chromium/third_party/blink/renderer/core/css/css_property_rule.idl
+++ b/chromium/third_party/blink/renderer/core/css/css_property_rule.idl
@@ -3,7 +3,11 @@
// found in the LICENSE file.
[
+ Exposed=Window,
RuntimeEnabled=CSSVariables2AtProperty
] interface CSSPropertyRule : CSSRule {
- readonly attribute CSSStyleDeclaration style;
+ readonly attribute CSSOMString name;
+ readonly attribute CSSOMString syntax;
+ readonly attribute boolean inherits;
+ readonly attribute CSSOMString? initialValue;
};
diff --git a/chromium/third_party/blink/renderer/core/css/css_revert_value.cc b/chromium/third_party/blink/renderer/core/css/css_revert_value.cc
new file mode 100644
index 00000000000..e0d1b7b7a78
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/css/css_revert_value.cc
@@ -0,0 +1,24 @@
+// 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/core/css/css_revert_value.h"
+
+#include "third_party/blink/renderer/core/css/css_value_pool.h"
+#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+
+namespace blink {
+namespace cssvalue {
+
+CSSRevertValue* CSSRevertValue::Create() {
+ DCHECK(RuntimeEnabledFeatures::CSSRevertEnabled());
+ return CssValuePool().RevertValue();
+}
+
+String CSSRevertValue::CustomCSSText() const {
+ return "revert";
+}
+
+} // namespace cssvalue
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/css_revert_value.h b/chromium/third_party/blink/renderer/core/css/css_revert_value.h
new file mode 100644
index 00000000000..5630c918a9a
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/css/css_revert_value.h
@@ -0,0 +1,44 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_REVERT_VALUE_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_REVERT_VALUE_H_
+
+#include "base/memory/scoped_refptr.h"
+#include "base/util/type_safety/pass_key.h"
+#include "third_party/blink/renderer/core/css/css_value.h"
+#include "third_party/blink/renderer/platform/wtf/casting.h"
+
+namespace blink {
+
+class CSSValuePool;
+
+namespace cssvalue {
+
+class CORE_EXPORT CSSRevertValue : public CSSValue {
+ public:
+ static CSSRevertValue* Create();
+
+ explicit CSSRevertValue(util::PassKey<CSSValuePool>)
+ : CSSValue(kRevertClass) {}
+
+ String CustomCSSText() const;
+
+ bool Equals(const CSSRevertValue&) const { return true; }
+
+ void TraceAfterDispatch(blink::Visitor* visitor) {
+ CSSValue::TraceAfterDispatch(visitor);
+ }
+};
+
+} // namespace cssvalue
+
+template <>
+struct DowncastTraits<cssvalue::CSSRevertValue> {
+ static bool AllowFrom(const CSSValue& value) { return value.IsRevertValue(); }
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_REVERT_VALUE_H_
diff --git a/chromium/third_party/blink/renderer/core/css/css_revert_value_test.cc b/chromium/third_party/blink/renderer/core/css/css_revert_value_test.cc
new file mode 100644
index 00000000000..a3508c24d1d
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/css/css_revert_value_test.cc
@@ -0,0 +1,36 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/css/css_revert_value.h"
+#include "third_party/blink/renderer/core/css/css_initial_value.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+
+namespace blink {
+
+using CSSRevertValue = cssvalue::CSSRevertValue;
+
+TEST(CSSRevertValueTest, IsCSSWideKeyword) {
+ ScopedCSSRevertForTest scoped_revert(true);
+ EXPECT_TRUE(CSSRevertValue::Create()->IsCSSWideKeyword());
+}
+
+TEST(CSSRevertValueTest, CssText) {
+ ScopedCSSRevertForTest scoped_revert(true);
+ EXPECT_EQ("revert", CSSRevertValue::Create()->CssText());
+}
+
+TEST(CSSRevertValueTest, Equals) {
+ ScopedCSSRevertForTest scoped_revert(true);
+ EXPECT_EQ(*CSSRevertValue::Create(), *CSSRevertValue::Create());
+}
+
+TEST(CSSRevertValueTest, NotEquals) {
+ ScopedCSSRevertForTest scoped_revert(true);
+ EXPECT_FALSE(*CSSRevertValue::Create() == *CSSInitialValue::Create());
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/css_rule.idl b/chromium/third_party/blink/renderer/core/css/css_rule.idl
index 875cdc60ae8..24c7dc13a96 100644
--- a/chromium/third_party/blink/renderer/core/css/css_rule.idl
+++ b/chromium/third_party/blink/renderer/core/css/css_rule.idl
@@ -46,10 +46,6 @@
// https://drafts.csswg.org/css-conditional/#extentions-to-cssrule-interface
const unsigned short SUPPORTS_RULE = 12;
- // CSS Device Adaptation
- // https://drafts.csswg.org/css-device-adapt/#css-rule-interface
- [RuntimeEnabled=CSSViewport] const unsigned short VIEWPORT_RULE = 15;
-
// CSS Properties and Values Level 1
// https://drafts.css-houdini.org/css-properties-values-api/#extensions-to-css-rule-interface
[RuntimeEnabled=CSSVariables2AtProperty] const unsigned short PROPERTY_RULE = 18;
diff --git a/chromium/third_party/blink/renderer/core/css/css_segmented_font_face.cc b/chromium/third_party/blink/renderer/core/css/css_segmented_font_face.cc
index d5294ee7a9e..d905879ef94 100644
--- a/chromium/third_party/blink/renderer/core/css/css_segmented_font_face.cc
+++ b/chromium/third_party/blink/renderer/core/css/css_segmented_font_face.cc
@@ -25,6 +25,8 @@
#include "third_party/blink/renderer/core/css/css_segmented_font_face.h"
+#include "base/bind.h"
+#include "base/callback.h"
#include "third_party/blink/renderer/core/css/css_font_face.h"
#include "third_party/blink/renderer/core/css/css_font_selector.h"
#include "third_party/blink/renderer/platform/fonts/font_cache.h"
@@ -49,7 +51,7 @@ CSSSegmentedFontFace::CSSSegmentedFontFace(
FontSelectionCapabilities font_selection_capabilities)
: font_selection_capabilities_(font_selection_capabilities),
font_data_table_(kFontDataTableMaxSize),
- first_non_css_connected_face_(font_faces_.end()),
+ font_faces_(MakeGarbageCollected<FontFaceList>()),
approximate_character_count_(0) {}
CSSSegmentedFontFace::~CSSSegmentedFontFace() = default;
@@ -64,11 +66,12 @@ void CSSSegmentedFontFace::PruneTable() {
bool CSSSegmentedFontFace::IsValid() const {
// Valid if at least one font face is valid.
- for (const auto& font_face : font_faces_) {
- if (font_face->CssFontFace()->IsValid())
- return true;
- }
- return false;
+ return font_faces_->ForEachUntilTrue(
+ WTF::BindRepeating([](Member<FontFace> font_face) -> bool {
+ if (font_face->CssFontFace()->IsValid())
+ return true;
+ return false;
+ }));
}
void CSSSegmentedFontFace::FontFaceInvalidated() {
@@ -79,26 +82,13 @@ void CSSSegmentedFontFace::AddFontFace(FontFace* font_face,
bool css_connected) {
PruneTable();
font_face->CssFontFace()->AddSegmentedFontFace(this);
- if (css_connected) {
- font_faces_.InsertBefore(first_non_css_connected_face_, font_face);
- } else {
- FontFaceList::AddResult result = font_faces_.insert(font_face);
- if (first_non_css_connected_face_ == font_faces_.end()) {
- --first_non_css_connected_face_;
- DCHECK_EQ(result.stored_value, &*first_non_css_connected_face_);
- }
- }
+ font_faces_->Insert(font_face, css_connected);
}
void CSSSegmentedFontFace::RemoveFontFace(FontFace* font_face) {
- FontFaceList::iterator it = font_faces_.find(font_face);
- if (it == font_faces_.end())
+ if (!font_faces_->Erase(font_face))
return;
- if (it == first_non_css_connected_face_)
- ++first_non_css_connected_face_;
- font_faces_.erase(it);
-
PruneTable();
font_face->CssFontFace()->RemoveSegmentedFontFace(this);
}
@@ -145,23 +135,30 @@ scoped_refptr<FontData> CSSSegmentedFontFace::GetFontData(
font_selection_request.slope == ItalicSlopeValue());
}
- for (FontFaceList::reverse_iterator it = font_faces_.rbegin();
- it != font_faces_.rend(); ++it) {
- if (!(*it)->CssFontFace()->IsValid())
- continue;
- if (scoped_refptr<SimpleFontData> face_font_data =
- (*it)->CssFontFace()->GetFontData(requested_font_description)) {
- DCHECK(!face_font_data->IsSegmented());
- if (face_font_data->IsCustomFont()) {
- created_font_data->AppendFace(base::AdoptRef(new FontDataForRangeSet(
- std::move(face_font_data), (*it)->CssFontFace()->Ranges())));
- } else {
- created_font_data->AppendFace(
- base::AdoptRef(new FontDataForRangeSetFromCache(
- std::move(face_font_data), (*it)->CssFontFace()->Ranges())));
- }
- }
- }
+ font_faces_->ForEachReverse(WTF::BindRepeating(
+ [](const FontDescription& requested_font_description,
+ scoped_refptr<SegmentedFontData> created_font_data,
+ Member<FontFace> font_face) {
+ if (!font_face->CssFontFace()->IsValid())
+ return;
+ if (scoped_refptr<SimpleFontData> face_font_data =
+ font_face->CssFontFace()->GetFontData(
+ requested_font_description)) {
+ DCHECK(!face_font_data->IsSegmented());
+ if (face_font_data->IsCustomFont()) {
+ created_font_data->AppendFace(base::AdoptRef(
+ new FontDataForRangeSet(std::move(face_font_data),
+ font_face->CssFontFace()->Ranges())));
+ } else {
+ created_font_data->AppendFace(
+ base::AdoptRef(new FontDataForRangeSetFromCache(
+ std::move(face_font_data),
+ font_face->CssFontFace()->Ranges())));
+ }
+ }
+ },
+ requested_font_description, created_font_data));
+
if (created_font_data->NumFaces()) {
scoped_refptr<SegmentedFontData> put_to_cache(created_font_data);
font_data_table_.Put(std::move(key), std::move(put_to_cache));
@@ -177,13 +174,16 @@ void CSSSegmentedFontFace::WillUseFontData(
const FontDescription& font_description,
const String& text) {
approximate_character_count_ += text.length();
- for (FontFaceList::reverse_iterator it = font_faces_.rbegin();
- it != font_faces_.rend(); ++it) {
- if ((*it)->LoadStatus() != FontFace::kUnloaded)
- break;
- if ((*it)->CssFontFace()->MaybeLoadFont(font_description, text))
- break;
- }
+ font_faces_->ForEachReverseUntilTrue(WTF::BindRepeating(
+ [](const FontDescription& font_description, const String& text,
+ Member<FontFace> font_face) -> bool {
+ if (font_face->LoadStatus() != FontFace::kUnloaded)
+ return true;
+ if (font_face->CssFontFace()->MaybeLoadFont(font_description, text))
+ return true;
+ return false;
+ },
+ font_description, text));
}
void CSSSegmentedFontFace::WillUseRange(
@@ -192,34 +192,155 @@ void CSSSegmentedFontFace::WillUseRange(
// Iterating backwards since later defined unicode-range faces override
// previously defined ones, according to the CSS3 fonts module.
// https://drafts.csswg.org/css-fonts/#composite-fonts
- for (FontFaceList::reverse_iterator it = font_faces_.rbegin();
- it != font_faces_.rend(); ++it) {
- CSSFontFace* css_font_face = (*it)->CssFontFace();
- if (css_font_face->MaybeLoadFont(font_description, range_set))
- break;
- }
+ font_faces_->ForEachReverseUntilTrue(WTF::BindRepeating(
+ [](const blink::FontDescription& font_description,
+ const blink::FontDataForRangeSet& range_set,
+ Member<FontFace> font_face) -> bool {
+ CSSFontFace* css_font_face = font_face->CssFontFace();
+ if (css_font_face->MaybeLoadFont(font_description, range_set))
+ return true;
+ return false;
+ },
+ font_description, range_set));
}
bool CSSSegmentedFontFace::CheckFont(const String& text) const {
- for (const auto& font_face : font_faces_) {
- if (font_face->LoadStatus() != FontFace::kLoaded &&
- font_face->CssFontFace()->Ranges()->IntersectsWith(text))
- return false;
- }
- return true;
+ return font_faces_->ForEachUntilFalse(WTF::BindRepeating(
+ [](const String& text, Member<FontFace> font_face) -> bool {
+ if (font_face->LoadStatus() != FontFace::kLoaded &&
+ font_face->CssFontFace()->Ranges()->IntersectsWith(text))
+ return false;
+ return true;
+ },
+ text));
}
void CSSSegmentedFontFace::Match(const String& text,
- HeapVector<Member<FontFace>>& faces) const {
- for (const auto& font_face : font_faces_) {
- if (font_face->CssFontFace()->Ranges()->IntersectsWith(text))
- faces.push_back(font_face);
- }
+ HeapVector<Member<FontFace>>* faces) const {
+ // WTF::BindRepeating requires WrapPersistent around |faces|, which is fine,
+ // because the wrap's lifetime is contained to this function.
+ font_faces_->ForEach(WTF::BindRepeating(
+ [](const String& text, HeapVector<Member<FontFace>>* faces,
+ Member<FontFace> font_face) {
+ if (font_face->CssFontFace()->Ranges()->IntersectsWith(text))
+ faces->push_back(font_face);
+ },
+ text, WrapPersistent(faces)));
}
void CSSSegmentedFontFace::Trace(Visitor* visitor) {
- visitor->Trace(first_non_css_connected_face_);
visitor->Trace(font_faces_);
}
+bool FontFaceList::IsEmpty() const {
+ return css_connected_face_.IsEmpty() && non_css_connected_face_.IsEmpty();
+}
+
+void FontFaceList::Insert(FontFace* font_face, bool css_connected) {
+ if (css_connected) {
+ css_connected_face_.insert(font_face);
+ } else {
+ non_css_connected_face_.insert(font_face);
+ }
+}
+
+bool FontFaceList::Erase(FontFace* font_face) {
+ FontFaceListPart::iterator it = css_connected_face_.find(font_face);
+ if (it != css_connected_face_.end()) {
+ css_connected_face_.erase(it);
+ return true;
+ }
+ it = non_css_connected_face_.find(font_face);
+ if (it != non_css_connected_face_.end()) {
+ non_css_connected_face_.erase(it);
+ return true;
+ }
+ return false;
+}
+
+// A callback that will be fed into |ForEach*UntilTrue|.
+// |callback| wants the |ForEach*UntilFalse| operation to stop iterating on
+// false, so its return value has to be negated in order for it to work with
+// |ForEach*UntilTrue|.
+static bool NegatingCallback(
+ const base::RepeatingCallback<bool(Member<FontFace>)>& callback,
+ Member<FontFace> font_face) {
+ return !callback.Run(font_face);
+}
+
+// A callback that will be fed into |ForEach*UntilTrue|, when we want it to
+// always continue iterating, so false has to be always returned.
+static bool FalseReturningCallback(
+ const base::RepeatingCallback<void(Member<FontFace>)>& callback,
+ Member<FontFace> font_face) {
+ callback.Run(font_face);
+ return false;
+}
+
+bool FontFaceList::ForEachUntilTrue(
+ const base::RepeatingCallback<bool(Member<FontFace>)>& callback) const {
+ for (Member<FontFace> font_face : css_connected_face_) {
+ if (callback.Run(font_face))
+ return true;
+ }
+ for (Member<FontFace> font_face : non_css_connected_face_) {
+ if (callback.Run(font_face))
+ return true;
+ }
+ return false;
+}
+
+bool FontFaceList::ForEachUntilFalse(
+ const base::RepeatingCallback<bool(Member<FontFace>)>& callback) const {
+ base::RepeatingCallback<bool(Member<FontFace>)> negating_callback =
+ WTF::BindRepeating(NegatingCallback, callback);
+ // When |callback| returns |false|, |ForEachUntilTrue(negating_callback)| will
+ // stop iterating and return |true|, so negate it.
+ return !ForEachUntilTrue(negating_callback);
+}
+
+void FontFaceList::ForEach(
+ const base::RepeatingCallback<void(Member<FontFace>)>& func) const {
+ base::RepeatingCallback<bool(Member<FontFace>)> false_returning_callback =
+ WTF::BindRepeating(FalseReturningCallback, func);
+ ForEachUntilTrue(false_returning_callback);
+}
+
+bool FontFaceList::ForEachReverseUntilTrue(
+ const base::RepeatingCallback<bool(Member<FontFace>)>& func) const {
+ for (auto it = non_css_connected_face_.rbegin();
+ it != non_css_connected_face_.rend(); ++it) {
+ if (func.Run(*it))
+ return true;
+ }
+ for (auto it = css_connected_face_.rbegin(); it != css_connected_face_.rend();
+ ++it) {
+ if (func.Run(*it))
+ return true;
+ }
+ return false;
+}
+
+bool FontFaceList::ForEachReverseUntilFalse(
+ const base::RepeatingCallback<bool(Member<FontFace>)>& callback) const {
+ base::RepeatingCallback<bool(Member<FontFace>)> negating_callback =
+ WTF::BindRepeating(NegatingCallback, callback);
+ // When |callback| returns |false|,
+ // |ForEachReverseUntilTrue(negating_callback)| will stop iterating and return
+ // |true|, so negate it.
+ return !ForEachReverseUntilTrue(negating_callback);
+}
+
+void FontFaceList::ForEachReverse(
+ const base::RepeatingCallback<void(Member<FontFace>)>& callback) const {
+ base::RepeatingCallback<bool(Member<FontFace>)> false_returning_callback =
+ WTF::BindRepeating(FalseReturningCallback, callback);
+ ForEachReverseUntilTrue(false_returning_callback);
+}
+
+void FontFaceList::Trace(Visitor* visitor) {
+ visitor->Trace(css_connected_face_);
+ visitor->Trace(non_css_connected_face_);
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/css_segmented_font_face.h b/chromium/third_party/blink/renderer/core/css/css_segmented_font_face.h
index 75933f47f7c..84da73e58f2 100644
--- a/chromium/third_party/blink/renderer/core/css/css_segmented_font_face.h
+++ b/chromium/third_party/blink/renderer/core/css/css_segmented_font_face.h
@@ -26,6 +26,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_SEGMENTED_FONT_FACE_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_SEGMENTED_FONT_FACE_H_
+#include "base/callback.h"
#include "third_party/blink/renderer/platform/fonts/font_cache_key.h"
#include "third_party/blink/renderer/platform/fonts/font_selection_types.h"
#include "third_party/blink/renderer/platform/fonts/segmented_font_data.h"
@@ -42,6 +43,47 @@ class FontDescription;
class FontFace;
class SegmentedFontData;
+// CSSSegmentedFontFace stores two FontFace list-sets, CSS-connected and
+// non-CSS-connected. This class combines the two such that they can be
+// conveniently operated as one.
+// Note however, |Insert| has to be instructed which sub-list to insert it to.
+// Iterating over the combined set, behaves as if all non-CSS-connected
+// FontFaces were stored after the CSS-connected ones.
+class FontFaceList : public GarbageCollected<FontFaceList> {
+ using FontFaceListPart = HeapListHashSet<Member<FontFace>>;
+
+ public:
+ bool IsEmpty() const;
+ void Insert(FontFace* font_face, bool css_connected);
+ bool Erase(FontFace* font_face);
+
+ // Iterate over CSS-connected FontFaces first, and then non-CSS-connected
+ // ones.
+ // Modifying the collection is not allowed during iteration.
+ bool ForEachUntilTrue(
+ const base::RepeatingCallback<bool(Member<FontFace>)>& callback) const;
+ bool ForEachUntilFalse(
+ const base::RepeatingCallback<bool(Member<FontFace>)>& callback) const;
+ void ForEach(
+ const base::RepeatingCallback<void(Member<FontFace>)>& callback) const;
+
+ // Iterate (in reverse order) over non-CSS-connected FontFaces first, and
+ // then CSS-connected ones.
+ // Modifying the collection is not allowed during iteration.
+ bool ForEachReverseUntilTrue(
+ const base::RepeatingCallback<bool(Member<FontFace>)>& callback) const;
+ bool ForEachReverseUntilFalse(
+ const base::RepeatingCallback<bool(Member<FontFace>)>& callback) const;
+ void ForEachReverse(
+ const base::RepeatingCallback<void(Member<FontFace>)>& callback) const;
+
+ void Trace(Visitor* visitor);
+
+ private:
+ FontFaceListPart css_connected_face_;
+ FontFaceListPart non_css_connected_face_;
+};
+
class CSSSegmentedFontFace final
: public GarbageCollected<CSSSegmentedFontFace> {
public:
@@ -58,12 +100,12 @@ class CSSSegmentedFontFace final
void AddFontFace(FontFace*, bool css_connected);
void RemoveFontFace(FontFace*);
- bool IsEmpty() const { return font_faces_.IsEmpty(); }
+ bool IsEmpty() const { return font_faces_->IsEmpty(); }
scoped_refptr<FontData> GetFontData(const FontDescription&);
bool CheckFont(const String&) const;
- void Match(const String&, HeapVector<Member<FontFace>>&) const;
+ void Match(const String&, HeapVector<Member<FontFace>>*) const;
void WillUseFontData(const FontDescription&, const String& text);
void WillUseRange(const FontDescription&, const blink::FontDataForRangeSet&);
size_t ApproximateCharacterCount() const {
@@ -76,16 +118,13 @@ class CSSSegmentedFontFace final
void PruneTable();
bool IsValid() const;
- using FontFaceList = HeapListHashSet<Member<FontFace>>;
-
FontSelectionCapabilities font_selection_capabilities_;
WTF::LruCache<FontCacheKey, scoped_refptr<SegmentedFontData>>
font_data_table_;
// All non-CSS-connected FontFaces are stored after the CSS-connected ones.
- FontFaceList font_faces_;
- FontFaceList::iterator first_non_css_connected_face_;
+ Member<FontFaceList> font_faces_;
// Approximate number of characters styled with this CSSSegmentedFontFace.
// LayoutText::StyleDidChange() increments this on the first
diff --git a/chromium/third_party/blink/renderer/core/css/css_style_declaration_test.cc b/chromium/third_party/blink/renderer/core/css/css_style_declaration_test.cc
index f4a15721b3f..5bfe780b1f9 100644
--- a/chromium/third_party/blink/renderer/core/css/css_style_declaration_test.cc
+++ b/chromium/third_party/blink/renderer/core/css/css_style_declaration_test.cc
@@ -7,6 +7,8 @@
#include "third_party/blink/renderer/core/css/css_rule_list.h"
#include "third_party/blink/renderer/core/css/css_style_rule.h"
#include "third_party/blink/renderer/core/css/css_test_helpers.h"
+#include "third_party/blink/renderer/core/dom/document.h"
+#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -25,4 +27,62 @@ TEST(CSSStyleDeclarationTest, getPropertyShorthand) {
EXPECT_EQ(AtomicString(), style->GetPropertyShorthand("padding"));
}
+TEST(CSSStyleDeclarationTest, ParsingRevertWithFeatureEnabled) {
+ ScopedCSSRevertForTest scoped_revert(true);
+
+ css_test_helpers::TestStyleSheet sheet;
+ sheet.AddCSSRules("div { top: revert; --x: revert; }");
+ ASSERT_TRUE(sheet.CssRules());
+ ASSERT_EQ(1u, sheet.CssRules()->length());
+ CSSStyleRule* style_rule = To<CSSStyleRule>(sheet.CssRules()->item(0));
+ CSSStyleDeclaration* style = style_rule->style();
+ ASSERT_TRUE(style);
+ EXPECT_EQ("revert", style->getPropertyValue("top"));
+ EXPECT_EQ("revert", style->getPropertyValue("--x"));
+
+ // Test setProperty/getPropertyValue:
+
+ DummyExceptionStateForTesting exception_state;
+
+ style->SetPropertyInternal(CSSPropertyID::kLeft, "left", "revert", false,
+ SecureContextMode::kSecureContext,
+ exception_state);
+ style->SetPropertyInternal(CSSPropertyID::kVariable, "--y", " revert", false,
+ SecureContextMode::kSecureContext,
+ exception_state);
+
+ EXPECT_EQ("revert", style->getPropertyValue("left"));
+ EXPECT_EQ("revert", style->getPropertyValue("--y"));
+ EXPECT_FALSE(exception_state.HadException());
+}
+
+TEST(CSSStyleDeclarationTest, ParsingRevertWithFeatureDisabled) {
+ ScopedCSSRevertForTest scoped_revert(false);
+
+ css_test_helpers::TestStyleSheet sheet;
+ sheet.AddCSSRules("div { top: revert; --x: revert; }");
+ ASSERT_TRUE(sheet.CssRules());
+ ASSERT_EQ(1u, sheet.CssRules()->length());
+ CSSStyleRule* style_rule = To<CSSStyleRule>(sheet.CssRules()->item(0));
+ CSSStyleDeclaration* style = style_rule->style();
+ ASSERT_TRUE(style);
+ EXPECT_EQ("", style->getPropertyValue("top"));
+ EXPECT_EQ(" revert", style->getPropertyValue("--x"));
+
+ // Test setProperty/getPropertyValue:
+
+ DummyExceptionStateForTesting exception_state;
+
+ style->SetPropertyInternal(CSSPropertyID::kLeft, "left", "revert", false,
+ SecureContextMode::kSecureContext,
+ exception_state);
+ style->SetPropertyInternal(CSSPropertyID::kVariable, "--y", " revert", false,
+ SecureContextMode::kSecureContext,
+ exception_state);
+
+ EXPECT_EQ("", style->getPropertyValue("left"));
+ EXPECT_EQ(" revert", style->getPropertyValue("--y"));
+ EXPECT_FALSE(exception_state.HadException());
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/css_style_sheet.cc b/chromium/third_party/blink/renderer/core/css/css_style_sheet.cc
index 096dc2743b7..f3779c87812 100644
--- a/chromium/third_party/blink/renderer/core/css/css_style_sheet.cc
+++ b/chromium/third_party/blink/renderer/core/css/css_style_sheet.cc
@@ -40,6 +40,7 @@
#include "third_party/blink/renderer/core/html/html_link_element.h"
#include "third_party/blink/renderer/core/html/html_style_element.h"
#include "third_party/blink/renderer/core/html_names.h"
+#include "third_party/blink/renderer/core/inspector/console_message.h"
#include "third_party/blink/renderer/core/probe/core_probes.h"
#include "third_party/blink/renderer/core/svg/svg_style_element.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
@@ -94,9 +95,12 @@ const Document* CSSStyleSheet::SingleOwnerDocument(
CSSStyleSheet* CSSStyleSheet::Create(Document& document,
const CSSStyleSheetInit* options,
ExceptionState& exception_state) {
- // Folowing steps at spec draft
- // https://wicg.github.io/construct-stylesheets/#dom-cssstylesheet-cssstylesheet
auto* parser_context = MakeGarbageCollected<CSSParserContext>(document);
+ if (AdTracker::IsAdScriptExecutingInDocument(&document))
+ parser_context->SetIsAdRelated();
+
+ // Following steps at spec draft
+ // https://wicg.github.io/construct-stylesheets/#dom-cssstylesheet-cssstylesheet
auto* contents = MakeGarbageCollected<StyleSheetContents>(parser_context);
CSSStyleSheet* sheet = MakeGarbageCollected<CSSStyleSheet>(contents, nullptr);
sheet->SetAssociatedDocument(&document);
@@ -138,6 +142,8 @@ CSSStyleSheet* CSSStyleSheet::CreateInline(Node& owner_node,
owner_node.GetDocument(), owner_node.GetDocument().BaseURL(),
true /* origin_clean */, owner_node.GetDocument().GetReferrerPolicy(),
encoding);
+ if (AdTracker::IsAdScriptExecutingInDocument(&owner_node.GetDocument()))
+ parser_context->SetIsAdRelated();
auto* sheet = MakeGarbageCollected<StyleSheetContents>(parser_context,
base_url.GetString());
return MakeGarbageCollected<CSSStyleSheet>(sheet, owner_node, true,
@@ -358,8 +364,8 @@ unsigned CSSStyleSheet::insertRule(const String& rule_string,
RuleMutationScope mutation_scope(this);
if (rule->IsImportRule() && is_constructed_) {
exception_state.ThrowDOMException(
- DOMExceptionCode::kNotAllowedError,
- "Can't insert @import rules to a constructed stylesheet.");
+ DOMExceptionCode::kSyntaxError,
+ "Can't insert @import rules into a constructed stylesheet.");
return 0;
}
bool success = contents_->WrapperInsertRule(rule, index);
@@ -460,15 +466,11 @@ ScriptPromise CSSStyleSheet::replace(ScriptState* script_state,
DOMExceptionCode::kNotAllowedError,
"Can't call replace on non-constructed CSSStyleSheets."));
}
- // Parses the text synchronously, loads import rules asynchronously.
- SetText(text, true /* allow_import_rules */, nullptr);
- if (!IsLoading())
- return ScriptPromise::Cast(script_state, ToV8(this, script_state));
- // We're loading a stylesheet that contains @import rules. This is deprecated.
- Deprecation::CountDeprecation(OwnerDocument(),
- WebFeature::kCssStyleSheetReplaceWithImport);
- resolver_ = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
- return resolver_->Promise();
+ SetText(text, CSSImportRules::kIgnoreWithWarning);
+ // We currently parse synchronously, and since @import support was removed,
+ // nothing else happens asynchronously. This API is left as-is, so that future
+ // async parsing can still be supported here.
+ return ScriptPromise::Cast(script_state, ToV8(this, script_state));
}
void CSSStyleSheet::replaceSync(const String& text,
@@ -478,7 +480,7 @@ void CSSStyleSheet::replaceSync(const String& text,
DOMExceptionCode::kNotAllowedError,
"Can't call replaceSync on non-constructed CSSStyleSheets.");
}
- SetText(text, false /* allow_import_rules */, &exception_state);
+ SetText(text, CSSImportRules::kIgnoreWithWarning);
}
void CSSStyleSheet::ResolveReplacePromiseIfNeeded(bool load_error_occured) {
@@ -569,19 +571,21 @@ void CSSStyleSheet::SetLoadCompleted(bool completed) {
contents_->ClientLoadStarted(this);
}
-void CSSStyleSheet::SetText(const String& text,
- bool allow_import_rules,
- ExceptionState* exception_state) {
+void CSSStyleSheet::SetText(const String& text, CSSImportRules import_rules) {
child_rule_cssom_wrappers_.clear();
CSSStyleSheet::RuleMutationScope mutation_scope(this);
contents_->ClearRules();
- if (contents_->ParseString(text, allow_import_rules) ==
- ParseSheetResult::kHasUnallowedImportRule) {
- DCHECK(exception_state);
- exception_state->ThrowDOMException(DOMExceptionCode::kNotAllowedError,
- "@import rules are not allowed when "
- "creating stylesheet synchronously.");
+ bool allow_imports = import_rules == CSSImportRules::kAllow;
+ if (contents_->ParseString(text, allow_imports) ==
+ ParseSheetResult::kHasUnallowedImportRule &&
+ import_rules == CSSImportRules::kIgnoreWithWarning) {
+ OwnerDocument()->AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>(
+ mojom::blink::ConsoleMessageSource::kJavaScript,
+ mojom::blink::ConsoleMessageLevel::kWarning,
+ "@import rules are not allowed here. See "
+ "https://github.com/WICG/construct-stylesheets/issues/"
+ "119#issuecomment-588352418."));
}
}
diff --git a/chromium/third_party/blink/renderer/core/css/css_style_sheet.h b/chromium/third_party/blink/renderer/core/css/css_style_sheet.h
index 84d53558a22..238b5d2ddcf 100644
--- a/chromium/third_party/blink/renderer/core/css/css_style_sheet.h
+++ b/chromium/third_party/blink/renderer/core/css/css_style_sheet.h
@@ -48,6 +48,11 @@ class ScriptPromiseResolver;
class ScriptState;
class StyleSheetContents;
+enum class CSSImportRules {
+ kAllow,
+ kIgnoreWithWarning,
+};
+
class CORE_EXPORT CSSStyleSheet final : public StyleSheet {
DEFINE_WRAPPERTYPEINFO();
@@ -189,9 +194,7 @@ class CORE_EXPORT CSSStyleSheet final : public StyleSheet {
bool SheetLoaded();
bool LoadCompleted() const { return load_completed_; }
void StartLoadingDynamicSheet();
- // If `allow_import_rules` is false, an ExceptionState pointer must be
- // provided, otherwise it can be null.
- void SetText(const String&, bool allow_import_rules, ExceptionState*);
+ void SetText(const String&, CSSImportRules);
void SetMedia(MediaList*);
void SetAlternateFromConstructor(bool);
bool CanBeActivated(const String& current_preferrable_name) const;
diff --git a/chromium/third_party/blink/renderer/core/css/css_syntax_definition.cc b/chromium/third_party/blink/renderer/core/css/css_syntax_definition.cc
index 1a3977717f2..a3dc48a5378 100644
--- a/chromium/third_party/blink/renderer/core/css/css_syntax_definition.cc
+++ b/chromium/third_party/blink/renderer/core/css/css_syntax_definition.cc
@@ -142,7 +142,7 @@ const CSSValue* ConsumeSyntaxComponent(const CSSSyntaxComponent& syntax,
const CSSValue* CSSSyntaxDefinition::Parse(CSSParserTokenRange range,
const CSSParserContext& context,
bool is_animation_tainted) const {
- if (IsTokenStream()) {
+ if (IsUniversal()) {
// TODO(crbug.com/579788): Implement 'revert'.
// TODO(crbug.com/882285): Make 'default' invalid as <custom-ident>.
if (CouldConsumeReservedKeyword(range))
diff --git a/chromium/third_party/blink/renderer/core/css/css_syntax_definition.h b/chromium/third_party/blink/renderer/core/css/css_syntax_definition.h
index 60a2308039d..4e4854bc019 100644
--- a/chromium/third_party/blink/renderer/core/css/css_syntax_definition.h
+++ b/chromium/third_party/blink/renderer/core/css/css_syntax_definition.h
@@ -19,7 +19,9 @@ class CORE_EXPORT CSSSyntaxDefinition {
const CSSValue* Parse(CSSParserTokenRange,
const CSSParserContext&,
bool is_animation_tainted) const;
- bool IsTokenStream() const {
+
+ // https://drafts.css-houdini.org/css-properties-values-api-1/#universal-syntax-descriptor
+ bool IsUniversal() const {
return syntax_components_.size() == 1 &&
syntax_components_[0].GetType() == CSSSyntaxType::kTokenStream;
}
diff --git a/chromium/third_party/blink/renderer/core/css/css_syntax_string_parser.cc b/chromium/third_party/blink/renderer/core/css/css_syntax_string_parser.cc
index 41c81652c14..a045ab45f32 100644
--- a/chromium/third_party/blink/renderer/core/css/css_syntax_string_parser.cc
+++ b/chromium/third_party/blink/renderer/core/css/css_syntax_string_parser.cc
@@ -150,7 +150,6 @@ bool CSSSyntaxStringParser::ConsumeDataTypeName(CSSSyntaxType& type) {
bool CSSSyntaxStringParser::ConsumeIdent(String& ident) {
ident = ConsumeName(input_);
- // TODO(crbug.com/579788): Implement 'revert'.
// TODO(crbug.com/882285): Make 'default' invalid as <custom-ident>.
return !css_property_parser_helpers::IsCSSWideKeyword(ident) &&
!css_property_parser_helpers::IsRevertKeyword(ident) &&
diff --git a/chromium/third_party/blink/renderer/core/css/css_syntax_string_parser_test.cc b/chromium/third_party/blink/renderer/core/css/css_syntax_string_parser_test.cc
index 9dc46a53894..e5e74d8d7f2 100644
--- a/chromium/third_party/blink/renderer/core/css/css_syntax_string_parser_test.cc
+++ b/chromium/third_party/blink/renderer/core/css/css_syntax_string_parser_test.cc
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/core/css/css_syntax_string_parser.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/core/css/css_syntax_component.h"
+#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
namespace blink {
@@ -47,6 +48,7 @@ class CSSSyntaxStringParserTest : public testing::Test {
TEST_F(CSSSyntaxStringParserTest, UniversalDescriptor) {
auto universal = CreateUniversalDescriptor();
+ EXPECT_TRUE(universal.IsUniversal());
EXPECT_EQ(universal, *CSSSyntaxStringParser("*").Parse());
EXPECT_EQ(universal, *CSSSyntaxStringParser(" * ").Parse());
EXPECT_EQ(universal, *CSSSyntaxStringParser("\r*\r\n").Parse());
@@ -118,6 +120,15 @@ TEST_F(CSSSyntaxStringParserTest, InvalidIdents) {
EXPECT_FALSE(CSSSyntaxStringParser("initial").Parse());
EXPECT_FALSE(CSSSyntaxStringParser("inherit").Parse());
EXPECT_FALSE(CSSSyntaxStringParser("unset").Parse());
+ EXPECT_FALSE(CSSSyntaxStringParser("default").Parse());
+ EXPECT_FALSE(CSSSyntaxStringParser("revert").Parse());
+
+ // 'revert' is forbidden also with CSSRevert toggled.
+ {
+ ScopedCSSRevertForTest scoped_revert(
+ !RuntimeEnabledFeatures::CSSRevertEnabled());
+ EXPECT_FALSE(CSSSyntaxStringParser("revert").Parse());
+ }
}
TEST_F(CSSSyntaxStringParserTest, Combinator) {
diff --git a/chromium/third_party/blink/renderer/core/css/css_test_helpers.cc b/chromium/third_party/blink/renderer/core/css/css_test_helpers.cc
index 874c1d50e6d..e0e74d3da07 100644
--- a/chromium/third_party/blink/renderer/core/css/css_test_helpers.cc
+++ b/chromium/third_party/blink/renderer/core/css/css_test_helpers.cc
@@ -7,8 +7,10 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_property_definition.h"
#include "third_party/blink/renderer/core/css/css_custom_ident_value.h"
+#include "third_party/blink/renderer/core/css/css_numeric_literal_value.h"
#include "third_party/blink/renderer/core/css/css_rule_list.h"
#include "third_party/blink/renderer/core/css/css_style_sheet.h"
+#include "third_party/blink/renderer/core/css/css_syntax_string_parser.h"
#include "third_party/blink/renderer/core/css/css_variable_data.h"
#include "third_party/blink/renderer/core/css/parser/css_parser_context.h"
#include "third_party/blink/renderer/core/css/parser/css_parser_local_context.h"
@@ -62,17 +64,37 @@ void TestStyleSheet::AddCSSRules(const String& css_text, bool is_empty_sheet) {
ASSERT_EQ(style_sheet_->length(), sheet_length);
}
+PropertyRegistration* CreatePropertyRegistration(const String& name) {
+ auto syntax_definition = CSSSyntaxStringParser("*").Parse();
+ DCHECK(syntax_definition);
+ return MakeGarbageCollected<PropertyRegistration>(
+ AtomicString(name), *syntax_definition, false /* inherits */,
+ nullptr /* initial */, nullptr /* initial_variable_data */);
+}
+
+PropertyRegistration* CreateLengthRegistration(const String& name, int px) {
+ auto syntax_definition = CSSSyntaxStringParser("<length>").Parse();
+ DCHECK(syntax_definition);
+ const CSSValue* initial =
+ CSSNumericLiteralValue::Create(px, CSSPrimitiveValue::UnitType::kPixels);
+ return MakeGarbageCollected<PropertyRegistration>(
+ AtomicString(name), *syntax_definition, false /* inherits */, initial,
+ CreateVariableData(initial->CssText()));
+}
+
void RegisterProperty(Document& document,
const String& name,
const String& syntax,
- const String& initial_value,
+ const base::Optional<String>& initial_value,
bool is_inherited) {
+ DCHECK(!initial_value || !initial_value.value().IsNull());
DummyExceptionStateForTesting exception_state;
PropertyDefinition* property_definition = PropertyDefinition::Create();
property_definition->setName(name);
property_definition->setSyntax(syntax);
- property_definition->setInitialValue(initial_value);
property_definition->setInherits(is_inherited);
+ if (initial_value)
+ property_definition->setInitialValue(initial_value.value());
PropertyRegistration::registerProperty(document.GetExecutionContext(),
property_definition, exception_state);
ASSERT_FALSE(exception_state.HadException());
diff --git a/chromium/third_party/blink/renderer/core/css/css_test_helpers.h b/chromium/third_party/blink/renderer/core/css/css_test_helpers.h
index 9b220f7659c..04bb35fdb16 100644
--- a/chromium/third_party/blink/renderer/core/css/css_test_helpers.h
+++ b/chromium/third_party/blink/renderer/core/css/css_test_helpers.h
@@ -16,6 +16,7 @@ class CSSStyleSheet;
class CSSVariableData;
class CSSValue;
class CSSProperty;
+class PropertyRegistration;
namespace css_test_helpers {
@@ -43,10 +44,18 @@ class TestStyleSheet {
Persistent<CSSStyleSheet> style_sheet_;
};
+// Create a PropertyRegistration for the given name. The syntax, initial value,
+// and inherited status are all undefined.
+PropertyRegistration* CreatePropertyRegistration(const String& name);
+
+// Create a non-inherited PropertyRegistration with syntax <length>, and the
+// given value in pixels as the initial value.
+PropertyRegistration* CreateLengthRegistration(const String& name, int px);
+
void RegisterProperty(Document& document,
const String& name,
const String& syntax,
- const String& initial_value,
+ const base::Optional<String>& initial_value,
bool is_inherited);
scoped_refptr<CSSVariableData> CreateVariableData(String);
diff --git a/chromium/third_party/blink/renderer/core/css/css_value.cc b/chromium/third_party/blink/renderer/core/css/css_value.cc
index d849ce2795d..91576fbf13f 100644
--- a/chromium/third_party/blink/renderer/core/css/css_value.cc
+++ b/chromium/third_party/blink/renderer/core/css/css_value.cc
@@ -55,7 +55,7 @@
#include "third_party/blink/renderer/core/css/css_invalid_variable_value.h"
#include "third_party/blink/renderer/core/css/css_keyframe_shorthand_value.h"
#include "third_party/blink/renderer/core/css/css_layout_function_value.h"
-#include "third_party/blink/renderer/core/css/css_light_dark_color_pair.h"
+#include "third_party/blink/renderer/core/css/css_light_dark_value_pair.h"
#include "third_party/blink/renderer/core/css/css_math_function_value.h"
#include "third_party/blink/renderer/core/css/css_numeric_literal_value.h"
#include "third_party/blink/renderer/core/css/css_paint_value.h"
@@ -65,6 +65,7 @@
#include "third_party/blink/renderer/core/css/css_quad_value.h"
#include "third_party/blink/renderer/core/css/css_ray_value.h"
#include "third_party/blink/renderer/core/css/css_reflect_value.h"
+#include "third_party/blink/renderer/core/css/css_revert_value.h"
#include "third_party/blink/renderer/core/css/css_shadow_value.h"
#include "third_party/blink/renderer/core/css/css_string_value.h"
#include "third_party/blink/renderer/core/css/css_timing_function_value.h"
@@ -212,6 +213,8 @@ bool CSSValue::operator==(const CSSValue& other) const {
return CompareCSSValues<CSSInitialValue>(*this, other);
case kUnsetClass:
return CompareCSSValues<cssvalue::CSSUnsetValue>(*this, other);
+ case kRevertClass:
+ return CompareCSSValues<cssvalue::CSSRevertValue>(*this, other);
case kGridAutoRepeatClass:
return CompareCSSValues<cssvalue::CSSGridAutoRepeatValue>(*this, other);
case kGridIntegerRepeatClass:
@@ -270,8 +273,8 @@ bool CSSValue::operator==(const CSSValue& other) const {
other);
case kInvalidVariableValueClass:
return CompareCSSValues<CSSInvalidVariableValue>(*this, other);
- case kLightDarkColorPairClass:
- return CompareCSSValues<CSSLightDarkColorPair>(*this, other);
+ case kLightDarkValuePairClass:
+ return CompareCSSValues<CSSLightDarkValuePair>(*this, other);
}
NOTREACHED();
return false;
@@ -331,6 +334,8 @@ String CSSValue::CssText() const {
return To<CSSInheritedValue>(this)->CustomCSSText();
case kUnsetClass:
return To<cssvalue::CSSUnsetValue>(this)->CustomCSSText();
+ case kRevertClass:
+ return To<cssvalue::CSSRevertValue>(this)->CustomCSSText();
case kInitialClass:
return To<CSSInitialValue>(this)->CustomCSSText();
case kGridAutoRepeatClass:
@@ -386,8 +391,8 @@ String CSSValue::CssText() const {
return To<cssvalue::CSSPendingSubstitutionValue>(this)->CustomCSSText();
case kInvalidVariableValueClass:
return To<CSSInvalidVariableValue>(this)->CustomCSSText();
- case kLightDarkColorPairClass:
- return To<CSSLightDarkColorPair>(this)->CustomCSSText();
+ case kLightDarkValuePairClass:
+ return To<CSSLightDarkValuePair>(this)->CustomCSSText();
}
NOTREACHED();
return String();
@@ -475,6 +480,9 @@ void CSSValue::FinalizeGarbageCollectedObject() {
case kUnsetClass:
To<cssvalue::CSSUnsetValue>(this)->~CSSUnsetValue();
return;
+ case kRevertClass:
+ To<cssvalue::CSSRevertValue>(this)->~CSSRevertValue();
+ return;
case kGridAutoRepeatClass:
To<cssvalue::CSSGridAutoRepeatValue>(this)->~CSSGridAutoRepeatValue();
return;
@@ -559,8 +567,8 @@ void CSSValue::FinalizeGarbageCollectedObject() {
case kInvalidVariableValueClass:
To<CSSInvalidVariableValue>(this)->~CSSInvalidVariableValue();
return;
- case kLightDarkColorPairClass:
- To<CSSLightDarkColorPair>(this)->~CSSLightDarkColorPair();
+ case kLightDarkValuePairClass:
+ To<CSSLightDarkValuePair>(this)->~CSSLightDarkValuePair();
return;
}
NOTREACHED();
@@ -648,6 +656,9 @@ void CSSValue::Trace(Visitor* visitor) {
case kUnsetClass:
To<cssvalue::CSSUnsetValue>(this)->TraceAfterDispatch(visitor);
return;
+ case kRevertClass:
+ To<cssvalue::CSSRevertValue>(this)->TraceAfterDispatch(visitor);
+ return;
case kGridAutoRepeatClass:
To<cssvalue::CSSGridAutoRepeatValue>(this)->TraceAfterDispatch(visitor);
return;
@@ -732,8 +743,8 @@ void CSSValue::Trace(Visitor* visitor) {
case kInvalidVariableValueClass:
To<CSSInvalidVariableValue>(this)->TraceAfterDispatch(visitor);
return;
- case kLightDarkColorPairClass:
- To<CSSLightDarkColorPair>(this)->TraceAfterDispatch(visitor);
+ case kLightDarkValuePairClass:
+ To<CSSLightDarkValuePair>(this)->TraceAfterDispatch(visitor);
return;
}
NOTREACHED();
diff --git a/chromium/third_party/blink/renderer/core/css/css_value.h b/chromium/third_party/blink/renderer/core/css/css_value.h
index db205280304..521575903e5 100644
--- a/chromium/third_party/blink/renderer/core/css/css_value.h
+++ b/chromium/third_party/blink/renderer/core/css/css_value.h
@@ -109,8 +109,9 @@ class CORE_EXPORT CSSValue : public GarbageCollected<CSSValue> {
bool IsInheritedValue() const { return class_type_ == kInheritedClass; }
bool IsInitialValue() const { return class_type_ == kInitialClass; }
bool IsUnsetValue() const { return class_type_ == kUnsetClass; }
+ bool IsRevertValue() const { return class_type_ == kRevertClass; }
bool IsCSSWideKeyword() const {
- return class_type_ >= kInheritedClass && class_type_ <= kUnsetClass;
+ return class_type_ >= kInheritedClass && class_type_ <= kRevertClass;
}
bool IsLayoutFunctionValue() const {
return class_type_ == kLayoutFunctionClass;
@@ -169,8 +170,8 @@ class CORE_EXPORT CSSValue : public GarbageCollected<CSSValue> {
bool IsShorthandWrapperValue() const {
return class_type_ == kKeyframeShorthandClass;
}
- bool IsLightDarkColorPair() const {
- return class_type_ == kLightDarkColorPairClass;
+ bool IsLightDarkValuePair() const {
+ return class_type_ == kLightDarkValuePairClass;
}
bool HasFailedOrCanceledSubresources() const;
@@ -201,7 +202,7 @@ class CORE_EXPORT CSSValue : public GarbageCollected<CSSValue> {
kStringClass,
kURIClass,
kValuePairClass,
- kLightDarkColorPairClass,
+ kLightDarkValuePairClass,
// Basic shape classes.
// TODO(sashab): Represent these as a single subclass, BasicShapeClass.
@@ -236,6 +237,7 @@ class CORE_EXPORT CSSValue : public GarbageCollected<CSSValue> {
kInheritedClass,
kInitialClass,
kUnsetClass,
+ kRevertClass,
kReflectClass,
kShadowClass,
diff --git a/chromium/third_party/blink/renderer/core/css/css_value_id_mappings.h b/chromium/third_party/blink/renderer/core/css/css_value_id_mappings.h
index b6cc1d096e6..ccc3d93dc50 100644
--- a/chromium/third_party/blink/renderer/core/css/css_value_id_mappings.h
+++ b/chromium/third_party/blink/renderer/core/css/css_value_id_mappings.h
@@ -489,6 +489,19 @@ inline CSSValueID PlatformEnumToCSSValueID(EListStyleType v) {
return CSSValueID::kDisc;
}
+template <>
+inline PageOrientation CssValueIDToPlatformEnum(CSSValueID v) {
+ if (v == CSSValueID::kUpright)
+ return PageOrientation::kUpright;
+ if (v == CSSValueID::kRotateLeft)
+ return PageOrientation::kRotateLeft;
+ if (v == CSSValueID::kRotateRight)
+ return PageOrientation::kRotateRight;
+
+ NOTREACHED();
+ return PageOrientation::kUpright;
+}
+
} // namespace blink
#endif
diff --git a/chromium/third_party/blink/renderer/core/css/css_value_keywords.json5 b/chromium/third_party/blink/renderer/core/css/css_value_keywords.json5
index 3b7a8b92b34..66b6f044cd1 100644
--- a/chromium/third_party/blink/renderer/core/css/css_value_keywords.json5
+++ b/chromium/third_party/blink/renderer/core/css/css_value_keywords.json5
@@ -442,6 +442,7 @@
"uppercase",
"lowercase",
//none
+ "math-auto",
//
// visibility
//
@@ -623,9 +624,15 @@
// auto
// none
- // text-underline-position
+ //
+ // text-decoration-thickness
+ //
// auto
"from-font",
+
+ // text-underline-position
+ // auto
+ // "from-font",
// under
// left
// right
@@ -784,6 +791,7 @@
//
"document",
"reset",
+ "-internal-reset-effective",
//
// user-zoom
@@ -900,6 +908,11 @@
// image-orientation
"from-image",
+ // page-orientation
+ // upright
+ "rotate-left",
+ "rotate-right",
+
// shape-outside
"nonzero",
"evenodd",
@@ -1087,7 +1100,7 @@
"rgba",
"hsl",
"hsla",
- "-internal-light-dark-color",
+ "-internal-light-dark",
// transform
"matrix",
@@ -1221,7 +1234,7 @@
// none
"back-button",
- // subtree-visibility
+ // content-visibility
"hidden-matchable",
// -internal-empty-line-height
@@ -1231,5 +1244,10 @@
// @supports selector(...)
// https://drafts.csswg.org/css-conditional-4/#typedef-supports-selector-fn
"selector",
+
+ // (screen-spanning) media feature
+ // none
+ "single-fold-vertical",
+ "single-fold-horizontal",
],
}
diff --git a/chromium/third_party/blink/renderer/core/css/css_value_pool.cc b/chromium/third_party/blink/renderer/core/css/css_value_pool.cc
index 1d62b641b68..fa730f16c4b 100644
--- a/chromium/third_party/blink/renderer/core/css/css_value_pool.cc
+++ b/chromium/third_party/blink/renderer/core/css/css_value_pool.cc
@@ -45,6 +45,7 @@ CSSValuePool::CSSValuePool()
: inherited_value_(MakeGarbageCollected<CSSInheritedValue>()),
initial_value_(MakeGarbageCollected<CSSInitialValue>()),
unset_value_(MakeGarbageCollected<CSSUnsetValue>(PassKey())),
+ revert_value_(MakeGarbageCollected<CSSRevertValue>(PassKey())),
invalid_variable_value_(MakeGarbageCollected<CSSInvalidVariableValue>()),
color_transparent_(
MakeGarbageCollected<cssvalue::CSSColorValue>(Color::kTransparent)),
@@ -62,6 +63,7 @@ void CSSValuePool::Trace(Visitor* visitor) {
visitor->Trace(inherited_value_);
visitor->Trace(initial_value_);
visitor->Trace(unset_value_);
+ visitor->Trace(revert_value_);
visitor->Trace(invalid_variable_value_);
visitor->Trace(color_transparent_);
visitor->Trace(color_white_);
diff --git a/chromium/third_party/blink/renderer/core/css/css_value_pool.h b/chromium/third_party/blink/renderer/core/css/css_value_pool.h
index c2fb257666c..7d978f1c6b8 100644
--- a/chromium/third_party/blink/renderer/core/css/css_value_pool.h
+++ b/chromium/third_party/blink/renderer/core/css/css_value_pool.h
@@ -39,6 +39,7 @@
#include "third_party/blink/renderer/core/css/css_invalid_variable_value.h"
#include "third_party/blink/renderer/core/css/css_numeric_literal_value.h"
#include "third_party/blink/renderer/core/css/css_property_names.h"
+#include "third_party/blink/renderer/core/css/css_revert_value.h"
#include "third_party/blink/renderer/core/css/css_unset_value.h"
#include "third_party/blink/renderer/core/css/css_value_list.h"
#include "third_party/blink/renderer/core/css_value_keywords.h"
@@ -55,6 +56,7 @@ class CORE_EXPORT CSSValuePool final : public GarbageCollected<CSSValuePool> {
static const int kMaximumCacheableIntegerValue = 255;
using CSSColorValue = cssvalue::CSSColorValue;
using CSSUnsetValue = cssvalue::CSSUnsetValue;
+ using CSSRevertValue = cssvalue::CSSRevertValue;
using ColorValueCache = HeapHashMap<unsigned, Member<CSSColorValue>>;
static const unsigned kMaximumColorCacheSize = 512;
using FontFaceValueCache =
@@ -71,6 +73,7 @@ class CORE_EXPORT CSSValuePool final : public GarbageCollected<CSSValuePool> {
CSSInheritedValue* InheritedValue() { return inherited_value_; }
CSSInitialValue* InitialValue() { return initial_value_; }
CSSUnsetValue* UnsetValue() { return unset_value_; }
+ CSSRevertValue* RevertValue() { return revert_value_; }
CSSInvalidVariableValue* InvalidVariableValue() {
return invalid_variable_value_;
}
@@ -134,6 +137,7 @@ class CORE_EXPORT CSSValuePool final : public GarbageCollected<CSSValuePool> {
Member<CSSInheritedValue> inherited_value_;
Member<CSSInitialValue> initial_value_;
Member<CSSUnsetValue> unset_value_;
+ Member<CSSRevertValue> revert_value_;
Member<CSSInvalidVariableValue> invalid_variable_value_;
Member<CSSColorValue> color_transparent_;
Member<CSSColorValue> color_white_;
diff --git a/chromium/third_party/blink/renderer/core/css/css_viewport_rule.cc b/chromium/third_party/blink/renderer/core/css/css_viewport_rule.cc
deleted file mode 100644
index 90a2ce21992..00000000000
--- a/chromium/third_party/blink/renderer/core/css/css_viewport_rule.cc
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright (C) 2012 Intel Corporation. All rights reserved.
- * Copyright (C) 2012 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 THE COPYRIGHT HOLDER "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 HOLDER 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/core/css/css_viewport_rule.h"
-
-#include "third_party/blink/renderer/core/css/css_property_value_set.h"
-#include "third_party/blink/renderer/core/css/style_rule.h"
-#include "third_party/blink/renderer/core/css/style_rule_css_style_declaration.h"
-#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
-
-namespace blink {
-
-CSSViewportRule::CSSViewportRule(StyleRuleViewport* viewport_rule,
- CSSStyleSheet* sheet)
- : CSSRule(sheet), viewport_rule_(viewport_rule) {}
-
-CSSViewportRule::~CSSViewportRule() = default;
-
-CSSStyleDeclaration* CSSViewportRule::style() const {
- if (!properties_cssom_wrapper_) {
- properties_cssom_wrapper_ =
- MakeGarbageCollected<StyleRuleCSSStyleDeclaration>(
- viewport_rule_->MutableProperties(),
- const_cast<CSSViewportRule*>(this));
- }
-
- return properties_cssom_wrapper_.Get();
-}
-
-String CSSViewportRule::cssText() const {
- StringBuilder result;
- result.Append("@viewport { ");
-
- String decls = viewport_rule_->Properties().AsText();
- result.Append(decls);
- if (!decls.IsEmpty())
- result.Append(' ');
-
- result.Append('}');
-
- return result.ToString();
-}
-
-void CSSViewportRule::Reattach(StyleRuleBase* rule) {
- DCHECK(rule);
- viewport_rule_ = To<StyleRuleViewport>(rule);
- if (properties_cssom_wrapper_)
- properties_cssom_wrapper_->Reattach(viewport_rule_->MutableProperties());
-}
-
-void CSSViewportRule::Trace(Visitor* visitor) {
- visitor->Trace(viewport_rule_);
- visitor->Trace(properties_cssom_wrapper_);
- CSSRule::Trace(visitor);
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/css_viewport_rule.h b/chromium/third_party/blink/renderer/core/css/css_viewport_rule.h
deleted file mode 100644
index 1806a6739f6..00000000000
--- a/chromium/third_party/blink/renderer/core/css/css_viewport_rule.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 2012 Intel Corporation. All rights reserved.
- * Copyright (C) 2012 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 THE COPYRIGHT HOLDER "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 HOLDER 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_CORE_CSS_CSS_VIEWPORT_RULE_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_VIEWPORT_RULE_H_
-
-#include "third_party/blink/renderer/core/css/css_rule.h"
-#include "third_party/blink/renderer/platform/heap/handle.h"
-#include "third_party/blink/renderer/platform/wtf/casting.h"
-
-namespace blink {
-
-class CSSStyleDeclaration;
-class StyleRuleViewport;
-class StyleRuleCSSStyleDeclaration;
-
-class CSSViewportRule final : public CSSRule {
- DEFINE_WRAPPERTYPEINFO();
-
- public:
- CSSViewportRule(StyleRuleViewport*, CSSStyleSheet*);
- ~CSSViewportRule() override;
-
- String cssText() const override;
- void Reattach(StyleRuleBase*) override;
-
- CSSStyleDeclaration* style() const;
-
- void Trace(Visitor*) override;
-
- private:
- CSSRule::Type type() const override { return kViewportRule; }
-
- Member<StyleRuleViewport> viewport_rule_;
- mutable Member<StyleRuleCSSStyleDeclaration> properties_cssom_wrapper_;
-};
-
-template <>
-struct DowncastTraits<CSSViewportRule> {
- static bool AllowFrom(const CSSRule& rule) {
- return rule.type() == CSSRule::kViewportRule;
- }
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_VIEWPORT_RULE_H_
diff --git a/chromium/third_party/blink/renderer/core/css/css_viewport_rule.idl b/chromium/third_party/blink/renderer/core/css/css_viewport_rule.idl
deleted file mode 100644
index 26d84823c3c..00000000000
--- a/chromium/third_party/blink/renderer/core/css/css_viewport_rule.idl
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2012 Intel Corporation. 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 THE COPYRIGHT HOLDER “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 HOLDER 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.
- */
-
-// https://drafts.csswg.org/css-device-adapt/#css-viewport-rule-interface
-
-[
- RuntimeEnabled=CSSViewport,
- Exposed=Window
-] interface CSSViewportRule : CSSRule {
- readonly attribute CSSStyleDeclaration style;
-};
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/computed_style_property_map.cc b/chromium/third_party/blink/renderer/core/css/cssom/computed_style_property_map.cc
index aacccd53811..ba32024dfb7 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/computed_style_property_map.cc
+++ b/chromium/third_party/blink/renderer/core/css/cssom/computed_style_property_map.cc
@@ -18,22 +18,6 @@
namespace blink {
-namespace {
-
-const CSSValue* ComputedTransform(const ComputedStyle& style) {
- if (style.Transform().Operations().size() == 0)
- return CSSIdentifierValue::Create(CSSValueID::kNone);
-
- CSSValueList* components = CSSValueList::CreateSpaceSeparated();
- for (const auto& operation : style.Transform().Operations()) {
- components->Append(*ComputedStyleUtils::ValueForTransformOperation(
- *operation, style.EffectiveZoom()));
- }
- return components;
-}
-
-} // namespace
-
unsigned int ComputedStylePropertyMap::size() const {
const ComputedStyle* style = UpdateStyle();
if (!style)
@@ -103,18 +87,8 @@ const CSSValue* ComputedStylePropertyMap::GetProperty(
if (!style)
return nullptr;
- // Special cases for properties where CSSProperty::CSSValueFromComputedStyle
- // doesn't return the correct computed value
- switch (property_id) {
- case CSSPropertyID::kTransform:
- return ComputedTransform(*style);
- case CSSPropertyID::kLineHeight:
- return ComputedStyleUtils::ComputedValueForLineHeight(*style);
- default:
- return CSSProperty::Get(property_id)
- .CSSValueFromComputedStyle(*style, nullptr /* layout_object */,
- false /* allow_visited_style */);
- }
+ return ComputedStyleUtils::ComputedPropertyValue(
+ CSSProperty::Get(property_id), *style);
}
const CSSValue* ComputedStylePropertyMap::GetCustomProperty(
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/css_keyword_value.cc b/chromium/third_party/blink/renderer/core/css/cssom/css_keyword_value.cc
index 28df68d1e94..f7fbef3b3dd 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/css_keyword_value.cc
+++ b/chromium/third_party/blink/renderer/core/css/cssom/css_keyword_value.cc
@@ -8,6 +8,7 @@
#include "third_party/blink/renderer/core/css/css_identifier_value.h"
#include "third_party/blink/renderer/core/css/css_inherited_value.h"
#include "third_party/blink/renderer/core/css/css_initial_value.h"
+#include "third_party/blink/renderer/core/css/css_revert_value.h"
#include "third_party/blink/renderer/core/css/css_unset_value.h"
#include "third_party/blink/renderer/core/css/parser/css_property_parser.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
@@ -38,6 +39,10 @@ CSSKeywordValue* CSSKeywordValue::FromCSSValue(const CSSValue& value) {
return MakeGarbageCollected<CSSKeywordValue>(
getValueName(CSSValueID::kUnset));
}
+ if (value.IsRevertValue()) {
+ return MakeGarbageCollected<CSSKeywordValue>(
+ getValueName(CSSValueID::kRevert));
+ }
if (auto* identifier_value = DynamicTo<CSSIdentifierValue>(value)) {
return MakeGarbageCollected<CSSKeywordValue>(
getValueName(identifier_value->GetValueID()));
@@ -86,6 +91,8 @@ const CSSValue* CSSKeywordValue::ToCSSValue() const {
return CSSInitialValue::Create();
case (CSSValueID::kUnset):
return cssvalue::CSSUnsetValue::Create();
+ case (CSSValueID::kRevert):
+ return cssvalue::CSSRevertValue::Create();
case (CSSValueID::kInvalid):
return MakeGarbageCollected<CSSCustomIdentValue>(
AtomicString(keyword_value_));
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/style_property_map_test.cc b/chromium/third_party/blink/renderer/core/css/cssom/style_property_map_test.cc
new file mode 100644
index 00000000000..b8be3a9a4b2
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/css/cssom/style_property_map_test.cc
@@ -0,0 +1,100 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/css/cssom/style_property_map.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/core/css/cssom/css_keyword_value.h"
+#include "third_party/blink/renderer/core/css/cssom/inline_style_property_map.h"
+#include "third_party/blink/renderer/core/html/html_element.h"
+#include "third_party/blink/renderer/core/testing/page_test_base.h"
+#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
+
+namespace blink {
+
+class StylePropertyMapTest : public PageTestBase {};
+
+TEST_F(StylePropertyMapTest, SetRevertWithFeatureEnabled) {
+ ScopedCSSRevertForTest scoped_revert(true);
+
+ DummyExceptionStateForTesting exception_state;
+
+ HeapVector<CSSStyleValueOrString> revert_string;
+ revert_string.push_back(CSSStyleValueOrString::FromString(" revert"));
+
+ HeapVector<CSSStyleValueOrString> revert_style_value;
+ revert_style_value.push_back(CSSStyleValueOrString::FromCSSStyleValue(
+ CSSKeywordValue::Create("revert", exception_state)));
+
+ auto* map =
+ MakeGarbageCollected<InlineStylePropertyMap>(GetDocument().body());
+
+ map->set(GetDocument().GetExecutionContext(), "top", revert_string,
+ exception_state);
+ map->set(GetDocument().GetExecutionContext(), "left", revert_style_value,
+ exception_state);
+
+ CSSStyleValue* top =
+ map->get(GetDocument().GetExecutionContext(), "top", exception_state);
+ CSSStyleValue* left =
+ map->get(GetDocument().GetExecutionContext(), "left", exception_state);
+
+ ASSERT_TRUE(DynamicTo<CSSKeywordValue>(top));
+ EXPECT_EQ(CSSValueID::kRevert,
+ DynamicTo<CSSKeywordValue>(top)->KeywordValueID());
+
+ ASSERT_TRUE(DynamicTo<CSSKeywordValue>(left));
+ EXPECT_EQ(CSSValueID::kRevert,
+ DynamicTo<CSSKeywordValue>(top)->KeywordValueID());
+
+ EXPECT_FALSE(exception_state.HadException());
+}
+
+TEST_F(StylePropertyMapTest, SetRevertWithFeatureDisabled) {
+ ScopedCSSRevertForTest scoped_revert(false);
+
+ HeapVector<CSSStyleValueOrString> revert_string;
+ revert_string.push_back(CSSStyleValueOrString::FromString(" revert"));
+
+ HeapVector<CSSStyleValueOrString> revert_style_value;
+
+ DummyExceptionStateForTesting exception_state;
+ revert_style_value.push_back(CSSStyleValueOrString::FromCSSStyleValue(
+ CSSKeywordValue::Create("revert", exception_state)));
+ EXPECT_FALSE(exception_state.HadException());
+
+ auto* map =
+ MakeGarbageCollected<InlineStylePropertyMap>(GetDocument().body());
+
+ {
+ DummyExceptionStateForTesting exception_state;
+ map->set(GetDocument().GetExecutionContext(), "top", revert_string,
+ exception_state);
+ EXPECT_TRUE(exception_state.HadException());
+ }
+ {
+ DummyExceptionStateForTesting exception_state;
+ map->set(GetDocument().GetExecutionContext(), "left", revert_style_value,
+ exception_state);
+ EXPECT_TRUE(exception_state.HadException());
+ }
+ {
+ DummyExceptionStateForTesting exception_state;
+ map->set(GetDocument().GetExecutionContext(), "--y", revert_style_value,
+ exception_state);
+ EXPECT_TRUE(exception_state.HadException());
+ }
+
+ CSSStyleValue* top =
+ map->get(GetDocument().GetExecutionContext(), "top", exception_state);
+ CSSStyleValue* left =
+ map->get(GetDocument().GetExecutionContext(), "left", exception_state);
+ CSSStyleValue* y =
+ map->get(GetDocument().GetExecutionContext(), "--y", exception_state);
+
+ EXPECT_FALSE(top);
+ EXPECT_FALSE(left);
+ EXPECT_FALSE(y);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/font_display_auto_lcp_align_test.cc b/chromium/third_party/blink/renderer/core/css/font_display_auto_lcp_align_test.cc
new file mode 100644
index 00000000000..3845a9e7fc6
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/css/font_display_auto_lcp_align_test.cc
@@ -0,0 +1,393 @@
+// 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 "base/test/scoped_feature_list.h"
+#include "third_party/blink/public/common/features.h"
+#include "third_party/blink/renderer/core/css/font_face_set_document.h"
+#include "third_party/blink/renderer/core/dom/element.h"
+#include "third_party/blink/renderer/core/layout/layout_object.h"
+#include "third_party/blink/renderer/core/loader/document_loader.h"
+#include "third_party/blink/renderer/core/style/computed_style.h"
+#include "third_party/blink/renderer/core/testing/sim/sim_request.h"
+#include "third_party/blink/renderer/core/testing/sim/sim_test.h"
+#include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
+
+namespace blink {
+
+class FontDisplayAutoLCPAlignTestBase : public SimTest {
+ public:
+ void SetUp() override {
+ std::map<std::string, std::string> parameters;
+ parameters["intervention-mode"] = intervention_mode_;
+ scoped_feature_list_.InitAndEnableFeatureWithParameters(
+ features::kAlignFontDisplayAutoTimeoutWithLCPGoal, parameters);
+ SimTest::SetUp();
+ }
+
+ static Vector<char> ReadAhemWoff2() {
+ return test::ReadFromFile(test::CoreTestDataPath("Ahem.woff2"))
+ ->CopyAs<Vector<char>>();
+ }
+
+ protected:
+ Element* GetTarget() { return GetDocument().getElementById("target"); }
+
+ const Font& GetTargetFont() {
+ return GetTarget()->GetLayoutObject()->Style()->GetFont();
+ }
+
+ std::string intervention_mode_;
+ base::test::ScopedFeatureList scoped_feature_list_;
+};
+
+class FontDisplayAutoLCPAlignFailureModeTest
+ : public FontDisplayAutoLCPAlignTestBase {
+ public:
+ void SetUp() override {
+ intervention_mode_ = "failure";
+ FontDisplayAutoLCPAlignTestBase::SetUp();
+ }
+};
+
+TEST_F(FontDisplayAutoLCPAlignFailureModeTest, FontFinishesBeforeLCPLimit) {
+ SimRequest main_resource("https://example.com", "text/html");
+ SimRequest font_resource("https://example.com/Ahem.woff2", "font/woff2");
+
+ LoadURL("https://example.com");
+ main_resource.Complete(R"HTML(
+ <!doctype html>
+ <style>
+ @font-face {
+ font-family: custom-font;
+ src: url(https://example.com/Ahem.woff2) format("woff2");
+ }
+ #target {
+ font: 25px/1 custom-font, monospace;
+ }
+ </style>
+ <span id=target style="position:relative">0123456789</span>
+ )HTML");
+
+ // The first frame is rendered with invisible fallback, as the web font is
+ // still loading, and is in the block display period.
+ Compositor().BeginFrame();
+ EXPECT_GT(250, GetTarget()->OffsetWidth());
+ EXPECT_TRUE(GetTargetFont().ShouldSkipDrawing());
+
+ font_resource.Complete(ReadAhemWoff2());
+
+ // The next frame is rendered with the web font.
+ Compositor().BeginFrame();
+ EXPECT_EQ(250, GetTarget()->OffsetWidth());
+ EXPECT_FALSE(GetTargetFont().ShouldSkipDrawing());
+}
+
+TEST_F(FontDisplayAutoLCPAlignFailureModeTest, FontFinishesAfterLCPLimit) {
+ SimRequest main_resource("https://example.com", "text/html");
+ SimRequest font_resource("https://example.com/Ahem.woff2", "font/woff2");
+
+ LoadURL("https://example.com");
+ main_resource.Complete(R"HTML(
+ <!doctype html>
+ <style>
+ @font-face {
+ font-family: custom-font;
+ src: url(https://example.com/Ahem.woff2) format("woff2");
+ }
+ #target {
+ font: 25px/1 custom-font, monospace;
+ }
+ </style>
+ <span id=target style="position:relative">0123456789</span>
+ )HTML");
+
+ // The first frame is rendered with invisible fallback, as the web font is
+ // still loading, and is in the block display period.
+ Compositor().BeginFrame();
+ EXPECT_GT(250, GetTarget()->OffsetWidth());
+ EXPECT_TRUE(GetTargetFont().ShouldSkipDrawing());
+
+ // Wait until we reach the LCP limit, and the relevant timeout fires.
+ test::RunDelayedTasks(base::TimeDelta::FromMilliseconds(
+ features::kAlignFontDisplayAutoTimeoutWithLCPGoalTimeoutParam.Get()));
+
+ // After reaching the LCP limit, the web font should enter the failure
+ // display period. We should render visible fallback for it.
+ Compositor().BeginFrame();
+ EXPECT_GT(250, GetTarget()->OffsetWidth());
+ EXPECT_FALSE(GetTargetFont().ShouldSkipDrawing());
+
+ font_resource.Complete(ReadAhemWoff2());
+
+ // We shouldn't use the web font even if it loads now. It's already in the
+ // failure display period.
+ Compositor().BeginFrame();
+ EXPECT_GT(250, GetTarget()->OffsetWidth());
+ EXPECT_FALSE(GetTargetFont().ShouldSkipDrawing());
+}
+
+TEST_F(FontDisplayAutoLCPAlignFailureModeTest, FontFaceAddedAfterLCPLimit) {
+ SimRequest main_resource("https://example.com", "text/html");
+ SimRequest font_resource("https://example.com/Ahem.woff2", "font/woff2");
+
+ LoadURL("https://example.com");
+ main_resource.Write("<!doctype html>");
+
+ // Wait until we reach the LCP limit, and the relevant timeout fires.
+ test::RunDelayedTasks(base::TimeDelta::FromMilliseconds(
+ features::kAlignFontDisplayAutoTimeoutWithLCPGoalTimeoutParam.Get()));
+
+ main_resource.Complete(R"HTML(
+ <style>
+ @font-face {
+ font-family: custom-font;
+ src: url(https://example.com/Ahem.woff2) format("woff2");
+ }
+ #target {
+ font: 25px/1 custom-font, monospace;
+ }
+ </style>
+ <span id=target style="position:relative">0123456789</span>
+ )HTML");
+
+ font_resource.Complete(ReadAhemWoff2());
+
+ // Since the font face is added after the LCP limit and is not in the memory
+ // cache, we'll treated as already in the failure period to prevent any
+ // latency or layout shifting. We should rendering visible fallback for it.
+ Compositor().BeginFrame();
+ EXPECT_GT(250, GetTarget()->OffsetWidth());
+ EXPECT_FALSE(GetTargetFont().ShouldSkipDrawing());
+}
+
+TEST_F(FontDisplayAutoLCPAlignFailureModeTest,
+ FontFaceInMemoryCacheAddedAfterLCPLimit) {
+ SimRequest main_resource("https://example.com", "text/html");
+ SimRequest font_resource("https://example.com/Ahem.woff2", "font/woff2");
+
+ LoadURL("https://example.com");
+ main_resource.Write(R"HTML(
+ <!doctype html>
+ <link rel="preload" as="font" type="font/woff2"
+ href="https://example.com/Ahem.woff2" crossorigin>
+ )HTML");
+
+ font_resource.Complete(ReadAhemWoff2());
+
+ // Wait until we reach the LCP limit, and the relevant timeout fires.
+ test::RunDelayedTasks(base::TimeDelta::FromMilliseconds(
+ features::kAlignFontDisplayAutoTimeoutWithLCPGoalTimeoutParam.Get()));
+
+ main_resource.Complete(R"HTML(
+ <style>
+ @font-face {
+ font-family: custom-font;
+ src: url(https://example.com/Ahem.woff2) format("woff2");
+ }
+ #target {
+ font: 25px/1 custom-font, monospace;
+ }
+ </style>
+ <span id=target style="position:relative">0123456789</span>
+ )HTML");
+
+ // The font face is added after the LCP limit, but it's already preloaded and
+ // available from the memory cache. We'll render with it as it's immediate
+ // available.
+ Compositor().BeginFrame();
+ EXPECT_EQ(250, GetTarget()->OffsetWidth());
+ EXPECT_FALSE(GetTargetFont().ShouldSkipDrawing());
+}
+
+// https://crbug.com/1065508
+TEST_F(FontDisplayAutoLCPAlignFailureModeTest,
+ TimeoutFiredAfterDocumentShutdown) {
+ SimRequest main_resource("https://example.com/", "text/html");
+ SimRequest font_resource("https://example.com/Ahem.woff2", "font/woff2");
+
+ LoadURL("https://example.com");
+ main_resource.Complete(R"HTML(
+ <!doctype html>
+ <style>
+ @font-face {
+ font-family: custom-font;
+ src: url(https://example.com/Ahem.woff2) format("woff2");
+ }
+ #target {
+ font: 25px/1 custom-font, monospace;
+ }
+ </style>
+ <span id=target style="position:relative">0123456789</span>
+ )HTML");
+
+ font_resource.Finish();
+
+ SimRequest next_page_resource("https://example2.com/", "text/html");
+ LoadURL("https://example2.com/");
+
+ // Wait until we reach the LCP limit, and the timeout for the previous
+ // document fires. Shouldn't crash here.
+ test::RunDelayedTasks(base::TimeDelta::FromMilliseconds(
+ features::kAlignFontDisplayAutoTimeoutWithLCPGoalTimeoutParam.Get()));
+
+ next_page_resource.Finish();
+}
+
+class FontDisplayAutoLCPAlignSwapModeTest
+ : public FontDisplayAutoLCPAlignTestBase {
+ public:
+ void SetUp() override {
+ intervention_mode_ = "swap";
+ FontDisplayAutoLCPAlignTestBase::SetUp();
+ }
+};
+
+TEST_F(FontDisplayAutoLCPAlignSwapModeTest, FontFinishesBeforeLCPLimit) {
+ SimRequest main_resource("https://example.com", "text/html");
+ SimRequest font_resource("https://example.com/Ahem.woff2", "font/woff2");
+
+ LoadURL("https://example.com");
+ main_resource.Complete(R"HTML(
+ <!doctype html>
+ <style>
+ @font-face {
+ font-family: custom-font;
+ src: url(https://example.com/Ahem.woff2) format("woff2");
+ }
+ #target {
+ font: 25px/1 custom-font, monospace;
+ }
+ </style>
+ <span id=target style="position:relative">0123456789</span>
+ )HTML");
+
+ // The first frame is rendered with invisible fallback, as the web font is
+ // still loading, and is in the block display period.
+ Compositor().BeginFrame();
+ EXPECT_GT(250, GetTarget()->OffsetWidth());
+ EXPECT_TRUE(GetTargetFont().ShouldSkipDrawing());
+
+ font_resource.Complete(ReadAhemWoff2());
+
+ // The next frame is rendered with the web font.
+ Compositor().BeginFrame();
+ EXPECT_EQ(250, GetTarget()->OffsetWidth());
+ EXPECT_FALSE(GetTargetFont().ShouldSkipDrawing());
+}
+
+TEST_F(FontDisplayAutoLCPAlignSwapModeTest, FontFinishesAfterLCPLimit) {
+ SimRequest main_resource("https://example.com", "text/html");
+ SimRequest font_resource("https://example.com/Ahem.woff2", "font/woff2");
+
+ LoadURL("https://example.com");
+ main_resource.Complete(R"HTML(
+ <!doctype html>
+ <style>
+ @font-face {
+ font-family: custom-font;
+ src: url(https://example.com/Ahem.woff2) format("woff2");
+ }
+ #target {
+ font: 25px/1 custom-font, monospace;
+ }
+ </style>
+ <span id=target style="position:relative">0123456789</span>
+ )HTML");
+
+ // The first frame is rendered with invisible fallback, as the web font is
+ // still loading, and is in the block display period.
+ Compositor().BeginFrame();
+ EXPECT_GT(250, GetTarget()->OffsetWidth());
+ EXPECT_TRUE(GetTargetFont().ShouldSkipDrawing());
+
+ // Wait until we reach the LCP limit, and the relevant timeout fires.
+ test::RunDelayedTasks(base::TimeDelta::FromMilliseconds(
+ features::kAlignFontDisplayAutoTimeoutWithLCPGoalTimeoutParam.Get()));
+
+ // After reaching the LCP limit, the web font should enter the swap
+ // display period. We should render visible fallback for it.
+ Compositor().BeginFrame();
+ EXPECT_GT(250, GetTarget()->OffsetWidth());
+ EXPECT_FALSE(GetTargetFont().ShouldSkipDrawing());
+
+ font_resource.Complete(ReadAhemWoff2());
+
+ // The web font swaps in after finishing loading.
+ Compositor().BeginFrame();
+ EXPECT_EQ(250, GetTarget()->OffsetWidth());
+ EXPECT_FALSE(GetTargetFont().ShouldSkipDrawing());
+}
+
+TEST_F(FontDisplayAutoLCPAlignSwapModeTest, FontFaceAddedAfterLCPLimit) {
+ SimRequest main_resource("https://example.com", "text/html");
+ SimRequest font_resource("https://example.com/Ahem.woff2", "font/woff2");
+
+ LoadURL("https://example.com");
+ main_resource.Write("<!doctype html>");
+
+ // Wait until we reach the LCP limit, and the relevant timeout fires.
+ test::RunDelayedTasks(base::TimeDelta::FromMilliseconds(
+ features::kAlignFontDisplayAutoTimeoutWithLCPGoalTimeoutParam.Get()));
+
+ main_resource.Complete(R"HTML(
+ <style>
+ @font-face {
+ font-family: custom-font;
+ src: url(https://example.com/Ahem.woff2) format("woff2");
+ }
+ #target {
+ font: 25px/1 custom-font, monospace;
+ }
+ </style>
+ <span id=target style="position:relative">0123456789</span>
+ )HTML");
+
+ font_resource.Complete(ReadAhemWoff2());
+
+ // The web font swaps in after finishing loading.
+ Compositor().BeginFrame();
+ EXPECT_EQ(250, GetTarget()->OffsetWidth());
+ EXPECT_FALSE(GetTargetFont().ShouldSkipDrawing());
+}
+
+TEST_F(FontDisplayAutoLCPAlignSwapModeTest,
+ FontFaceInMemoryCacheAddedAfterLCPLimit) {
+ SimRequest main_resource("https://example.com", "text/html");
+ SimRequest font_resource("https://example.com/Ahem.woff2", "font/woff2");
+
+ LoadURL("https://example.com");
+ main_resource.Write(R"HTML(
+ <!doctype html>
+ <link rel="preload" as="font" type="font/woff2"
+ href="https://example.com/Ahem.woff2" crossorigin>
+ )HTML");
+
+ font_resource.Complete(ReadAhemWoff2());
+
+ // Wait until we reach the LCP limit, and the relevant timeout fires.
+ test::RunDelayedTasks(base::TimeDelta::FromMilliseconds(
+ features::kAlignFontDisplayAutoTimeoutWithLCPGoalTimeoutParam.Get()));
+
+ main_resource.Complete(R"HTML(
+ <style>
+ @font-face {
+ font-family: custom-font;
+ src: url(https://example.com/Ahem.woff2) format("woff2");
+ }
+ #target {
+ font: 25px/1 custom-font, monospace;
+ }
+ </style>
+ <span id=target style="position:relative">0123456789</span>
+ )HTML");
+
+ // The font face is added after the LCP limit, but it's already preloaded and
+ // available from the memory cache. We'll render with it as it's immediate
+ // available.
+ Compositor().BeginFrame();
+ EXPECT_EQ(250, GetTarget()->OffsetWidth());
+ EXPECT_FALSE(GetTargetFont().ShouldSkipDrawing());
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/font_face.cc b/chromium/third_party/blink/renderer/core/css/font_face.cc
index 1a11168bd2f..54d6631cca8 100644
--- a/chromium/third_party/blink/renderer/core/css/font_face.cc
+++ b/chromium/third_party/blink/renderer/core/css/font_face.cc
@@ -813,8 +813,10 @@ FontDisplay FontFace::GetFontDisplay() const {
}
void FontFace::DidBeginImperativeLoad() {
- if (GetDocument())
- GetDocument()->GetFontPreloadManager().ImperativeFontLoadingStarted(this);
+ if (!DomWindow())
+ return;
+ DomWindow()->document()->GetFontPreloadManager().ImperativeFontLoadingStarted(
+ this);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/font_face_cache_test.cc b/chromium/third_party/blink/renderer/core/css/font_face_cache_test.cc
index 1c05906fd6a..0097034ec4d 100644
--- a/chromium/third_party/blink/renderer/core/css/font_face_cache_test.cc
+++ b/chromium/third_party/blink/renderer/core/css/font_face_cache_test.cc
@@ -65,7 +65,7 @@ void FontFaceCacheTest::AppendTestFaceForCapabilities(const CSSValue& stretch,
CSSFontFamilyValue::Create(kFontNameForTesting);
CSSFontFaceSrcValue* src = CSSFontFaceSrcValue::CreateLocal(
kFontNameForTesting, network::mojom::CSPDisposition::DO_NOT_CHECK,
- OriginClean::kTrue);
+ OriginClean::kTrue, false /* is_ad_related */);
CSSValueList* src_value_list = CSSValueList::CreateCommaSeparated();
src_value_list->Append(*src);
CSSPropertyValue properties[] = {
diff --git a/chromium/third_party/blink/renderer/core/css/font_face_set.cc b/chromium/third_party/blink/renderer/core/css/font_face_set.cc
index c137ca35c91..ce0dd906973 100644
--- a/chromium/third_party/blink/renderer/core/css/font_face_set.cc
+++ b/chromium/third_party/blink/renderer/core/css/font_face_set.cc
@@ -58,7 +58,8 @@ FontFaceSet* FontFaceSet::addForBinding(ScriptState*,
font_selector->GetFontFaceCache()->AddFontFace(font_face, false);
if (font_face->LoadStatus() == FontFace::kLoading)
AddToLoadingFonts(font_face);
- font_selector->FontFaceInvalidated();
+ font_selector->FontFaceInvalidated(
+ FontInvalidationReason::kGeneralInvalidation);
return this;
}
@@ -73,7 +74,8 @@ void FontFaceSet::clearForBinding(ScriptState*, ExceptionState&) {
RemoveFromLoadingFonts(font_face);
}
non_css_connected_faces_.clear();
- font_selector->FontFaceInvalidated();
+ font_selector->FontFaceInvalidated(
+ FontInvalidationReason::kGeneralInvalidation);
}
bool FontFaceSet::deleteForBinding(ScriptState*,
@@ -90,7 +92,8 @@ bool FontFaceSet::deleteForBinding(ScriptState*,
font_selector->GetFontFaceCache()->RemoveFontFace(font_face, false);
if (font_face->LoadStatus() == FontFace::kLoading)
RemoveFromLoadingFonts(font_face);
- font_selector->FontFaceInvalidated();
+ font_selector->FontFaceInvalidated(
+ FontInvalidationReason::kFontFaceDeleted);
return true;
}
return false;
@@ -175,7 +178,7 @@ ScriptPromise FontFaceSet::load(ScriptState* script_state,
}
FontFaceCache* font_face_cache = GetFontSelector()->GetFontFaceCache();
- FontFaceArray faces;
+ FontFaceArray* faces = MakeGarbageCollected<FontFaceArray>();
for (const FontFamily* f = &font.GetFontDescription().Family(); f;
f = f->Next()) {
CSSSegmentedFontFace* segmented_font_face =
diff --git a/chromium/third_party/blink/renderer/core/css/font_face_set.h b/chromium/third_party/blink/renderer/core/css/font_face_set.h
index 17a41e25578..0ed6012f1fa 100644
--- a/chromium/third_party/blink/renderer/core/css/font_face_set.h
+++ b/chromium/third_party/blink/renderer/core/css/font_face_set.h
@@ -128,11 +128,11 @@ class CORE_EXPORT FontFaceSet : public EventTargetWithInlineData,
USING_GARBAGE_COLLECTED_MIXIN(LoadFontPromiseResolver);
public:
- LoadFontPromiseResolver(FontFaceArray faces, ScriptState* script_state)
- : num_loading_(faces.size()),
+ LoadFontPromiseResolver(FontFaceArray* faces, ScriptState* script_state)
+ : num_loading_(faces->size()),
error_occured_(false),
resolver_(MakeGarbageCollected<ScriptPromiseResolver>(script_state)) {
- font_faces_.swap(faces);
+ font_faces_.swap(*faces);
}
void LoadFonts();
diff --git a/chromium/third_party/blink/renderer/core/css/font_face_set_document.cc b/chromium/third_party/blink/renderer/core/css/font_face_set_document.cc
index 21d0ebce61f..97626f2a4e3 100644
--- a/chromium/third_party/blink/renderer/core/css/font_face_set_document.cc
+++ b/chromium/third_party/blink/renderer/core/css/font_face_set_document.cc
@@ -26,13 +26,16 @@
#include "third_party/blink/renderer/core/css/font_face_set_document.h"
#include "base/metrics/histogram_functions.h"
+#include "third_party/blink/public/common/features.h"
#include "third_party/blink/renderer/bindings/core/v8/dictionary.h"
+#include "third_party/blink/renderer/core/css/css_font_face.h"
#include "third_party/blink/renderer/core/css/css_font_selector.h"
#include "third_party/blink/renderer/core/css/css_property_value_set.h"
#include "third_party/blink/renderer/core/css/css_segmented_font_face.h"
#include "third_party/blink/renderer/core/css/font_face_cache.h"
#include "third_party/blink/renderer/core/css/font_face_set_load_event.h"
#include "third_party/blink/renderer/core/css/parser/css_parser.h"
+#include "third_party/blink/renderer/core/css/parser/css_property_parser_helpers.h"
#include "third_party/blink/renderer/core/css/resolver/font_style_resolver.h"
#include "third_party/blink/renderer/core/css/resolver/style_resolver.h"
#include "third_party/blink/renderer/core/css/style_engine.h"
@@ -40,6 +43,7 @@
#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
+#include "third_party/blink/renderer/core/loader/document_loader.h"
#include "third_party/blink/renderer/core/style/computed_style.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
@@ -51,7 +55,10 @@ const char FontFaceSetDocument::kSupplementName[] = "FontFaceSetDocument";
FontFaceSetDocument::FontFaceSetDocument(Document& document)
: FontFaceSet(*document.GetExecutionContext()),
- Supplement<Document>(document) {}
+ Supplement<Document>(document),
+ lcp_limit_timer_(document.GetTaskRunner(TaskType::kInternalLoading),
+ this,
+ &FontFaceSetDocument::LCPLimitReached) {}
FontFaceSetDocument::~FontFaceSetDocument() = default;
@@ -68,25 +75,42 @@ AtomicString FontFaceSetDocument::status() const {
}
void FontFaceSetDocument::DidLayout() {
+ if (!GetExecutionContext())
+ return;
if (GetDocument()->GetFrame()->IsMainFrame() && loading_fonts_.IsEmpty())
- histogram_.Record();
+ font_load_histogram_.Record();
if (!ShouldSignalReady())
return;
HandlePendingEventsAndPromisesSoon();
}
+void FontFaceSetDocument::StartLCPLimitTimerIfNeeded() {
+ // Make sure the timer is started at most once for each document, and only
+ // when the feature is enabled
+ if (!base::FeatureList::IsEnabled(
+ features::kAlignFontDisplayAutoTimeoutWithLCPGoal) ||
+ has_reached_lcp_limit_ || lcp_limit_timer_.IsActive() ||
+ !GetDocument()->Loader()) {
+ return;
+ }
+
+ lcp_limit_timer_.StartOneShot(
+ GetDocument()->Loader()->RemainingTimeToLCPLimit(), FROM_HERE);
+}
+
void FontFaceSetDocument::BeginFontLoading(FontFace* font_face) {
AddToLoadingFonts(font_face);
+ StartLCPLimitTimerIfNeeded();
}
void FontFaceSetDocument::NotifyLoaded(FontFace* font_face) {
- histogram_.UpdateStatus(font_face);
+ font_load_histogram_.UpdateStatus(font_face);
loaded_fonts_.push_back(font_face);
RemoveFromLoadingFonts(font_face);
}
void FontFaceSetDocument::NotifyError(FontFace* font_face) {
- histogram_.UpdateStatus(font_face);
+ font_load_histogram_.UpdateStatus(font_face);
failed_fonts_.push_back(font_face);
RemoveFromLoadingFonts(font_face);
}
@@ -150,7 +174,7 @@ bool FontFaceSetDocument::ResolveFontStyle(const String& font_string,
return false;
String font_value = parsed_style->GetPropertyValue(CSSPropertyID::kFont);
- if (font_value == "inherit" || font_value == "initial")
+ if (css_property_parser_helpers::IsCSSWideKeyword(font_value))
return false;
if (!GetDocument()->documentElement()) {
@@ -186,6 +210,12 @@ bool FontFaceSetDocument::ResolveFontStyle(const String& font_string,
return true;
}
+Document* FontFaceSetDocument::GetDocument() const {
+ if (auto* window = To<LocalDOMWindow>(GetExecutionContext()))
+ return window->document();
+ return nullptr;
+}
+
FontFaceSetDocument* FontFaceSetDocument::From(Document& document) {
FontFaceSetDocument* fonts =
Supplement<Document>::From<FontFaceSetDocument>(document);
@@ -210,6 +240,32 @@ size_t FontFaceSetDocument::ApproximateBlankCharacterCount(Document& document) {
return 0;
}
+void FontFaceSetDocument::AlignTimeoutWithLCPGoal(FontFace* font_face) {
+ bool is_loading = font_face->LoadStatus() == FontFace::kLoading;
+ bool affected = font_face->CssFontFace()->UpdatePeriod();
+ // We only count loading font faces, so that unused fonts are excluded. This
+ // is especially useful when the page uses a font library, where most of the
+ // fonts are unused.
+ if (is_loading && font_face->display() == "auto") {
+ font_display_auto_align_histogram_.SetHasFontDisplayAuto();
+ if (affected)
+ font_display_auto_align_histogram_.CountAffected();
+ }
+}
+
+void FontFaceSetDocument::LCPLimitReached(TimerBase*) {
+ DCHECK(base::FeatureList::IsEnabled(
+ features::kAlignFontDisplayAutoTimeoutWithLCPGoal));
+ if (!GetDocument() || !GetDocument()->IsActive())
+ return;
+ has_reached_lcp_limit_ = true;
+ for (FontFace* font_face : CSSConnectedFontFaceList())
+ AlignTimeoutWithLCPGoal(font_face);
+ for (FontFace* font_face : non_css_connected_faces_)
+ AlignTimeoutWithLCPGoal(font_face);
+ font_display_auto_align_histogram_.Record();
+}
+
void FontFaceSetDocument::Trace(Visitor* visitor) {
Supplement<Document>::Trace(visitor);
FontFaceSet::Trace(visitor);
@@ -231,4 +287,17 @@ void FontFaceSetDocument::FontLoadHistogram::Record() {
}
}
+void FontFaceSetDocument::FontDisplayAutoAlignHistogram::Record() {
+ if (!base::FeatureList::IsEnabled(
+ features::kAlignFontDisplayAutoTimeoutWithLCPGoal)) {
+ return;
+ }
+ if (!has_font_display_auto_ || reported_)
+ return;
+ base::UmaHistogramCounts100(
+ "WebFont.Clients.AlignFontDisplayAuto.FontFacesAffected",
+ affected_count_);
+ reported_ = true;
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/font_face_set_document.h b/chromium/third_party/blink/renderer/core/css/font_face_set_document.h
index 5ee0f4d01da..3e59a7d1486 100644
--- a/chromium/third_party/blink/renderer/core/css/font_face_set_document.h
+++ b/chromium/third_party/blink/renderer/core/css/font_face_set_document.h
@@ -64,6 +64,13 @@ class CORE_EXPORT FontFaceSetDocument final : public FontFaceSet,
void NotifyLoaded(FontFace*) override;
void NotifyError(FontFace*) override;
+ // After flipping the flag to true, all 'font-display: auto' fonts that
+ // haven't finished loading will enter the failure period immediately (except
+ // for those already in the memory cache), so that they don't cause a bad
+ // Largest Contentful Paint (https://wicg.github.io/largest-contentful-paint/)
+ bool HasReachedLCPLimit() const { return has_reached_lcp_limit_; }
+ void LCPLimitReached(TimerBase*);
+
size_t ApproximateBlankCharacterCount() const;
static FontFaceSetDocument* From(Document&);
@@ -83,10 +90,15 @@ class CORE_EXPORT FontFaceSetDocument final : public FontFaceSet,
bool ResolveFontStyle(const String&, Font&) override;
private:
+ Document* GetDocument() const;
+
void FireDoneEventIfPossible() override;
const HeapLinkedHashSet<Member<FontFace>>& CSSConnectedFontFaceList()
const override;
+ void StartLCPLimitTimerIfNeeded();
+ void AlignTimeoutWithLCPGoal(FontFace* font_face);
+
class FontLoadHistogram {
DISALLOW_NEW();
@@ -99,7 +111,28 @@ class CORE_EXPORT FontFaceSetDocument final : public FontFaceSet,
private:
Status status_;
};
- FontLoadHistogram histogram_;
+ FontLoadHistogram font_load_histogram_;
+
+ class FontDisplayAutoAlignHistogram {
+ DISALLOW_NEW();
+
+ public:
+ void SetHasFontDisplayAuto() { has_font_display_auto_ = true; }
+ void CountAffected() { ++affected_count_; }
+
+ void Record();
+
+ private:
+ unsigned affected_count_ = 0;
+ bool has_font_display_auto_ = false;
+ bool reported_ = false;
+ };
+ FontDisplayAutoAlignHistogram font_display_auto_align_histogram_;
+
+ TaskRunnerTimer<FontFaceSetDocument> lcp_limit_timer_;
+
+ bool has_reached_lcp_limit_ = false;
+
DISALLOW_COPY_AND_ASSIGN(FontFaceSetDocument);
};
diff --git a/chromium/third_party/blink/renderer/core/css/font_face_set_worker.cc b/chromium/third_party/blink/renderer/core/css/font_face_set_worker.cc
index 00350f89d2a..83299c5e9fe 100644
--- a/chromium/third_party/blink/renderer/core/css/font_face_set_worker.cc
+++ b/chromium/third_party/blink/renderer/core/css/font_face_set_worker.cc
@@ -12,6 +12,7 @@
#include "third_party/blink/renderer/core/css/font_face_set_load_event.h"
#include "third_party/blink/renderer/core/css/offscreen_font_selector.h"
#include "third_party/blink/renderer/core/css/parser/css_parser.h"
+#include "third_party/blink/renderer/core/css/parser/css_property_parser_helpers.h"
#include "third_party/blink/renderer/core/css/resolver/font_style_resolver.h"
#include "third_party/blink/renderer/core/css/resolver/style_resolver.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
@@ -83,7 +84,7 @@ bool FontFaceSetWorker::ResolveFontStyle(const String& font_string,
return false;
String font_value = parsed_style->GetPropertyValue(CSSPropertyID::kFont);
- if (font_value == "inherit" || font_value == "initial")
+ if (css_property_parser_helpers::IsCSSWideKeyword(font_value))
return false;
FontFamily font_family;
diff --git a/chromium/third_party/blink/renderer/core/css/font_update_invalidation_test.cc b/chromium/third_party/blink/renderer/core/css/font_update_invalidation_test.cc
new file mode 100644
index 00000000000..294eac07ea3
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/css/font_update_invalidation_test.cc
@@ -0,0 +1,141 @@
+// 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/core/css/style_engine.h"
+#include "third_party/blink/renderer/core/dom/element.h"
+#include "third_party/blink/renderer/core/layout/layout_object.h"
+#include "third_party/blink/renderer/core/style/computed_style.h"
+#include "third_party/blink/renderer/core/testing/sim/sim_request.h"
+#include "third_party/blink/renderer/core/testing/sim/sim_test.h"
+#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
+#include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
+
+namespace blink {
+
+// This test suite verifies that after font changes (e.g., font loaded), we do
+// not invalidate the full document's style or layout, but for affected elements
+// only.
+class FontUpdateInvalidationTest
+ : private ScopedCSSReducedFontLoadingInvalidationsForTest,
+ private ScopedCSSReducedFontLoadingLayoutInvalidationsForTest,
+ public SimTest {
+ public:
+ FontUpdateInvalidationTest()
+ : ScopedCSSReducedFontLoadingInvalidationsForTest(true),
+ ScopedCSSReducedFontLoadingLayoutInvalidationsForTest(true) {}
+
+ protected:
+ static Vector<char> ReadAhemWoff2() {
+ return test::ReadFromFile(test::CoreTestDataPath("Ahem.woff2"))
+ ->CopyAs<Vector<char>>();
+ }
+};
+
+TEST_F(FontUpdateInvalidationTest, PartialLayoutInvalidationAfterFontLoading) {
+ SimRequest main_resource("https://example.com", "text/html");
+ SimRequest font_resource("https://example.com/Ahem.woff2", "font/woff2");
+
+ LoadURL("https://example.com");
+ main_resource.Write(R"HTML(
+ <!doctype html>
+ <style>
+ @font-face {
+ font-family: custom-font;
+ src: url(https://example.com/Ahem.woff2) format("woff2");
+ }
+ #target {
+ font: 25px/1 custom-font, monospace;
+ }
+ #reference {
+ font: 25px/1 monospace;
+ }
+ </style>
+ <div><span id=target>0123456789</span></div>
+ <div><span id=reference>0123456789</div>
+ )HTML");
+
+ // First rendering the page with fallback
+ Compositor().BeginFrame();
+
+ Element* target = GetDocument().getElementById("target");
+ Element* reference = GetDocument().getElementById("reference");
+
+ EXPECT_GT(250, target->OffsetWidth());
+ EXPECT_GT(250, reference->OffsetWidth());
+
+ // Finish font loading, and trigger invalidations.
+ font_resource.Complete(ReadAhemWoff2());
+ GetDocument().GetStyleEngine().InvalidateStyleAndLayoutForFontUpdates();
+
+ // No element is marked for style recalc, since no computed style is changed.
+ EXPECT_EQ(kNoStyleChange, target->GetStyleChangeType());
+ EXPECT_EQ(kNoStyleChange, reference->GetStyleChangeType());
+
+ // Only elements that had pending custom fonts are marked for relayout.
+ EXPECT_TRUE(target->GetLayoutObject()->NeedsLayout());
+ EXPECT_FALSE(reference->GetLayoutObject()->NeedsLayout());
+
+ Compositor().BeginFrame();
+ EXPECT_EQ(250, target->OffsetWidth());
+ EXPECT_GT(250, reference->OffsetWidth());
+
+ main_resource.Finish();
+}
+
+TEST_F(FontUpdateInvalidationTest,
+ PartialLayoutInvalidationAfterFontFaceDeletion) {
+ SimRequest main_resource("https://example.com", "text/html");
+ SimRequest font_resource("https://example.com/Ahem.woff2", "font/woff2");
+
+ LoadURL("https://example.com");
+ main_resource.Write(R"HTML(
+ <!doctype html>
+ <script>
+ const face = new FontFace('custom-font',
+ 'url(https://example.com/Ahem.woff2)');
+ face.load();
+ document.fonts.add(face);
+ </script>
+ <style>
+ #target {
+ font: 25px/1 custom-font, monospace;
+ }
+ #reference {
+ font: 25px/1 monospace;
+ }
+ </style>
+ <div><span id=target>0123456789</span></div>
+ <div><span id=reference>0123456789</div>
+ )HTML");
+
+ // First render the page with the custom font
+ font_resource.Complete(ReadAhemWoff2());
+ Compositor().BeginFrame();
+
+ Element* target = GetDocument().getElementById("target");
+ Element* reference = GetDocument().getElementById("reference");
+
+ EXPECT_EQ(250, target->OffsetWidth());
+ EXPECT_GT(250, reference->OffsetWidth());
+
+ // Then delete the custom font, and trigger invalidations
+ main_resource.Write("<script>document.fonts.delete(face);</script>");
+ GetDocument().GetStyleEngine().InvalidateStyleAndLayoutForFontUpdates();
+
+ // No element is marked for style recalc, since no computed style is changed.
+ EXPECT_EQ(kNoStyleChange, target->GetStyleChangeType());
+ EXPECT_EQ(kNoStyleChange, reference->GetStyleChangeType());
+
+ // Only elements using custom fonts are marked for relayout.
+ EXPECT_TRUE(target->GetLayoutObject()->NeedsLayout());
+ EXPECT_FALSE(reference->GetLayoutObject()->NeedsLayout());
+
+ Compositor().BeginFrame();
+ EXPECT_GT(250, target->OffsetWidth());
+ EXPECT_GT(250, reference->OffsetWidth());
+
+ main_resource.Finish();
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/invalidation/pending_invalidations.cc b/chromium/third_party/blink/renderer/core/css/invalidation/pending_invalidations.cc
index 9453376b596..992cc173a61 100644
--- a/chromium/third_party/blink/renderer/core/css/invalidation/pending_invalidations.cc
+++ b/chromium/third_party/blink/renderer/core/css/invalidation/pending_invalidations.cc
@@ -32,11 +32,8 @@ void PendingInvalidations::ScheduleInvalidationSetsForNode(
if (node.GetStyleChangeType() < kSubtreeStyleChange) {
for (auto& invalidation_set : invalidation_lists.descendants) {
if (invalidation_set->WholeSubtreeInvalid()) {
- ContainerNode* subtree_root = &node;
- if (RuntimeEnabledFeatures::FlatTreeStyleRecalcEnabled()) {
- if (auto* shadow_root = DynamicTo<ShadowRoot>(node))
- subtree_root = &shadow_root->host();
- }
+ auto* shadow_root = DynamicTo<ShadowRoot>(node);
+ auto* subtree_root = shadow_root ? &shadow_root->host() : &node;
subtree_root->SetNeedsStyleRecalc(
kSubtreeStyleChange, StyleChangeReasonForTracing::Create(
style_change_reason::kStyleInvalidator));
@@ -109,12 +106,9 @@ void PendingInvalidations::ScheduleSiblingInvalidationsAsDescendants(
scheduling_parent.SetNeedsStyleInvalidation();
- ContainerNode* subtree_root = &scheduling_parent;
- if (RuntimeEnabledFeatures::FlatTreeStyleRecalcEnabled()) {
- subtree_root = DynamicTo<Element>(scheduling_parent);
- if (!subtree_root)
- subtree_root = &To<ShadowRoot>(scheduling_parent).host();
- }
+ Element* subtree_root = DynamicTo<Element>(scheduling_parent);
+ if (!subtree_root)
+ subtree_root = &To<ShadowRoot>(scheduling_parent).host();
for (auto& invalidation_set : invalidation_lists.siblings) {
DescendantInvalidationSet* descendants =
diff --git a/chromium/third_party/blink/renderer/core/css/local_font_face_source.cc b/chromium/third_party/blink/renderer/core/css/local_font_face_source.cc
index 38d08f4d909..c731222a995 100644
--- a/chromium/third_party/blink/renderer/core/css/local_font_face_source.cc
+++ b/chromium/third_party/blink/renderer/core/css/local_font_face_source.cc
@@ -118,7 +118,8 @@ void LocalFontFaceSource::NotifyFontUniqueNameLookupReady() {
PruneTable();
if (face_->FontLoaded(this)) {
- font_selector_->FontFaceInvalidated();
+ font_selector_->FontFaceInvalidated(
+ FontInvalidationReason::kGeneralInvalidation);
}
}
diff --git a/chromium/third_party/blink/renderer/core/css/mathml.css b/chromium/third_party/blink/renderer/core/css/mathml.css
index 5adc7b167ce..68459f4d191 100644
--- a/chromium/third_party/blink/renderer/core/css/mathml.css
+++ b/chromium/third_party/blink/renderer/core/css/mathml.css
@@ -30,6 +30,7 @@
/* By default, we only display the MathML formulas without any formatting other than the one specified by the display attribute. */
math {
display: inline-math;
+ math-superscript-shift-style: display;
}
math[display="block"] {
@@ -46,7 +47,7 @@ math[display="block"] {
outline: auto 1px -webkit-focus-ring-color;
}
-maction, merror, mfrac, mphantom, mrow, mspace, mstyle
+maction, merror, mfrac, mphantom, mrow, mspace, mstyle, msub, msup, msubsup, munder, mover, munderover
{
display: math;
}
@@ -68,3 +69,20 @@ mfrac {
padding-inline-start: 1px;
padding-inline-end: 1px;
}
+
+mfrac > :nth-child(2) {
+ math-superscript-shift-style: inline;
+}
+
+munder > :nth-child(2),
+munderover > :nth-child(2),
+mover[accent="true" i] > :first-child,
+munderover[accent="true" i] > :first-child {
+ math-superscript-shift-style: inline;
+}
+
+/* Token elements */
+mi {
+ text-transform: math-auto;
+}
+
diff --git a/chromium/third_party/blink/renderer/core/css/media_feature_names.json5 b/chromium/third_party/blink/renderer/core/css/media_feature_names.json5
index cd214bc0f89..388a58828e7 100644
--- a/chromium/third_party/blink/renderer/core/css/media_feature_names.json5
+++ b/chromium/third_party/blink/renderer/core/css/media_feature_names.json5
@@ -57,6 +57,7 @@
"resolution",
"-webkit-transform-3d",
"scan",
+ "screen-spanning",
"shape",
],
}
diff --git a/chromium/third_party/blink/renderer/core/css/media_query_evaluator.cc b/chromium/third_party/blink/renderer/core/css/media_query_evaluator.cc
index 1a091ab8789..a2a1cea57e5 100644
--- a/chromium/third_party/blink/renderer/core/css/media_query_evaluator.cc
+++ b/chromium/third_party/blink/renderer/core/css/media_query_evaluator.cc
@@ -32,6 +32,7 @@
#include "third_party/blink/public/common/css/forced_colors.h"
#include "third_party/blink/public/common/css/navigation_controls.h"
#include "third_party/blink/public/common/css/preferred_color_scheme.h"
+#include "third_party/blink/public/common/css/screen_spanning.h"
#include "third_party/blink/public/mojom/manifest/display_mode.mojom-shared.h"
#include "third_party/blink/public/platform/pointer_properties.h"
#include "third_party/blink/public/platform/shape_properties.h"
@@ -901,6 +902,26 @@ static bool NavigationControlsMediaFeatureEval(
value.id == CSSValueID::kBackButton);
}
+static bool ScreenSpanningMediaFeatureEval(const MediaQueryExpValue& value,
+ MediaFeaturePrefix,
+ const MediaValues& media_values) {
+ ScreenSpanning screen_spanning_mode = media_values.GetScreenSpanning();
+
+ if (!value.IsValid())
+ return screen_spanning_mode != ScreenSpanning::kNone;
+
+ // We should not have parsed a valid MediaQueryExpValue if the value is not
+ // an identifier.
+ DCHECK(value.is_id);
+
+ return (screen_spanning_mode == ScreenSpanning::kNone &&
+ value.id == CSSValueID::kNone) ||
+ (screen_spanning_mode == ScreenSpanning::kSingleFoldVertical &&
+ value.id == CSSValueID::kSingleFoldVertical) ||
+ (screen_spanning_mode == ScreenSpanning::kSingleFoldHorizontal &&
+ value.id == CSSValueID::kSingleFoldHorizontal);
+}
+
void MediaQueryEvaluator::Init() {
// Create the table.
g_function_map = new FunctionMap;
diff --git a/chromium/third_party/blink/renderer/core/css/media_query_evaluator_test.cc b/chromium/third_party/blink/renderer/core/css/media_query_evaluator_test.cc
index 998370f4203..bb2e9e00608 100644
--- a/chromium/third_party/blink/renderer/core/css/media_query_evaluator_test.cc
+++ b/chromium/third_party/blink/renderer/core/css/media_query_evaluator_test.cc
@@ -7,6 +7,7 @@
#include <memory>
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/css/forced_colors.h"
+#include "third_party/blink/public/common/css/screen_spanning.h"
#include "third_party/blink/renderer/core/css/media_list.h"
#include "third_party/blink/renderer/core/css/media_values_cached.h"
#include "third_party/blink/renderer/core/css/media_values_initial_viewport.h"
@@ -199,6 +200,32 @@ MediaQueryEvaluatorTestCase g_navigationcontrols_none_cases[] = {
{nullptr, 0} // Do not remove the terminator line.
};
+MediaQueryEvaluatorTestCase g_screen_spanning_none_cases[] = {
+ {"(screen-spanning)", 0},
+ {"(screen-spanning: single-fold-vertical)", 0},
+ {"(screen-spanning: single-fold-horizontal)", 0},
+ {"(screen-spanning: none)", 1},
+ {"(screen-spanning: 1px)", 0},
+ {"(screen-spanning: 16/9)", 0},
+ {nullptr, 0} // Do not remove the terminator line.
+};
+
+MediaQueryEvaluatorTestCase g_screen_spanning_single_fold_vertical_cases[] = {
+ {"(screen-spanning)", 1},
+ {"(screen-spanning: single-fold-vertical)", 1},
+ {"(screen-spanning: single-fold-horizontal)", 0},
+ {"(screen-spanning: none)", 0},
+ {nullptr, 0} // Do not remove the terminator line.
+};
+
+MediaQueryEvaluatorTestCase g_screen_spanning_single_fold_horizontal_cases[] = {
+ {"(screen-spanning)", 1},
+ {"(screen-spanning: single-fold-vertical)", 0},
+ {"(screen-spanning: single-fold-horizontal)", 1},
+ {"(screen-spanning: none)", 0},
+ {nullptr, 0} // Do not remove the terminator line.
+};
+
void TestMQEvaluator(MediaQueryEvaluatorTestCase* test_cases,
const MediaQueryEvaluator& media_query_evaluator,
CSSParserMode mode) {
@@ -373,4 +400,33 @@ TEST(MediaQueryEvaluatorTest, CachedForcedColors) {
}
}
+TEST(MediaQueryEvaluatorTest, CachedScreenSpanning) {
+ ScopedCSSFoldablesForTest scoped_feature(true);
+
+ MediaValuesCached::MediaValuesCachedData data;
+ {
+ data.screen_spanning = ScreenSpanning::kNone;
+ MediaValues* media_values = MakeGarbageCollected<MediaValuesCached>(data);
+
+ MediaQueryEvaluator media_query_evaluator(*media_values);
+ TestMQEvaluator(g_screen_spanning_none_cases, media_query_evaluator);
+ }
+
+ {
+ data.screen_spanning = ScreenSpanning::kSingleFoldVertical;
+ MediaValues* media_values = MakeGarbageCollected<MediaValuesCached>(data);
+ MediaQueryEvaluator media_query_evaluator(*media_values);
+ TestMQEvaluator(g_screen_spanning_single_fold_vertical_cases,
+ media_query_evaluator);
+ }
+
+ {
+ data.screen_spanning = ScreenSpanning::kSingleFoldHorizontal;
+ MediaValues* media_values = MakeGarbageCollected<MediaValuesCached>(data);
+ MediaQueryEvaluator media_query_evaluator(*media_values);
+ TestMQEvaluator(g_screen_spanning_single_fold_horizontal_cases,
+ media_query_evaluator);
+ }
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/media_query_exp.cc b/chromium/third_party/blink/renderer/core/css/media_query_exp.cc
index 37d0f166736..e3ea62499d7 100644
--- a/chromium/third_party/blink/renderer/core/css/media_query_exp.cc
+++ b/chromium/third_party/blink/renderer/core/css/media_query_exp.cc
@@ -101,6 +101,14 @@ static inline bool FeatureWithValidIdent(const String& media_feature,
}
}
+ if (RuntimeEnabledFeatures::CSSFoldablesEnabled()) {
+ if (media_feature == media_feature_names::kScreenSpanningMediaFeature) {
+ return ident == CSSValueID::kNone ||
+ ident == CSSValueID::kSingleFoldVertical ||
+ ident == CSSValueID::kSingleFoldHorizontal;
+ }
+ }
+
return false;
}
@@ -224,7 +232,9 @@ static inline bool FeatureWithoutValue(
RuntimeEnabledFeatures::MediaQueryNavigationControlsEnabled()) ||
(media_feature == media_feature_names::kOriginTrialTestMediaFeature &&
RuntimeEnabledFeatures::OriginTrialsSampleAPIEnabled(
- execution_context));
+ execution_context)) ||
+ (media_feature == media_feature_names::kScreenSpanningMediaFeature &&
+ RuntimeEnabledFeatures::CSSFoldablesEnabled());
}
bool MediaQueryExp::IsViewportDependent() const {
diff --git a/chromium/third_party/blink/renderer/core/css/media_query_set_test.cc b/chromium/third_party/blink/renderer/core/css/media_query_set_test.cc
index fc00218599b..1ccb196374f 100644
--- a/chromium/third_party/blink/renderer/core/css/media_query_set_test.cc
+++ b/chromium/third_party/blink/renderer/core/css/media_query_set_test.cc
@@ -194,6 +194,7 @@ TEST(MediaQuerySetTest, BehindRuntimeFlag) {
ScopedMediaQueryShapeForTest shape_flag(false);
ScopedForcedColorsForTest forced_colors_flag(false);
ScopedMediaQueryNavigationControlsForTest navigation_controls_flag(false);
+ ScopedCSSFoldablesForTest foldables_flag(false);
// The first string represents the input string, the second string represents
// the output string.
@@ -201,9 +202,11 @@ TEST(MediaQuerySetTest, BehindRuntimeFlag) {
{"(shape)", "not all"},
{"(forced-colors)", "not all"},
{"(navigation-controls)", "not all"},
+ {"(screen-spanning)", "not all"},
{"(shape: rect)", "not all"},
{"(forced-colors: none)", "not all"},
{"(navigation-controls: none)", "not all"},
+ {"(screen-spanning:none)", "not all"},
{nullptr, nullptr} // Do not remove the terminator line.
};
diff --git a/chromium/third_party/blink/renderer/core/css/media_values.cc b/chromium/third_party/blink/renderer/core/css/media_values.cc
index 3ff366de0a8..b7ae26eeb2e 100644
--- a/chromium/third_party/blink/renderer/core/css/media_values.cc
+++ b/chromium/third_party/blink/renderer/core/css/media_values.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/core/css/media_values.h"
+#include "third_party/blink/public/common/css/screen_spanning.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/web_screen_info.h"
#include "third_party/blink/public/platform/web_theme_engine.h"
@@ -21,6 +22,7 @@
#include "third_party/blink/renderer/core/page/chrome_client.h"
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/platform/graphics/color_space_gamut.h"
+#include "third_party/blink/renderer/platform/widget/frame_widget.h"
namespace blink {
@@ -123,18 +125,19 @@ const String MediaValues::CalculateMediaType(LocalFrame* frame) {
return frame->View()->MediaType();
}
-blink::mojom::DisplayMode MediaValues::CalculateDisplayMode(LocalFrame* frame) {
+mojom::blink::DisplayMode MediaValues::CalculateDisplayMode(LocalFrame* frame) {
DCHECK(frame);
+
blink::mojom::DisplayMode mode =
frame->GetPage()->GetSettings().GetDisplayModeOverride();
-
- if (mode != blink::mojom::DisplayMode::kUndefined)
+ if (mode != mojom::blink::DisplayMode::kUndefined)
return mode;
- if (!frame->View())
- return blink::mojom::DisplayMode::kBrowser;
+ FrameWidget* widget = frame->GetWidgetForLocalRoot();
+ if (!widget) // Is null in non-ordinary Pages.
+ return mojom::blink::DisplayMode::kBrowser;
- return frame->View()->DisplayMode();
+ return widget->DisplayMode();
}
bool MediaValues::CalculateThreeDEnabled(LocalFrame* frame) {
@@ -225,6 +228,12 @@ NavigationControls MediaValues::CalculateNavigationControls(LocalFrame* frame) {
return frame->GetSettings()->GetNavigationControls();
}
+ScreenSpanning MediaValues::CalculateScreenSpanning(LocalFrame* frame) {
+ // TODO(dlibby): Retrieve info propagated from the host as to our]
+ // screen-spanning state.
+ return ScreenSpanning::kNone;
+}
+
bool MediaValues::ComputeLengthImpl(double value,
CSSPrimitiveValue::UnitType type,
unsigned default_font_size,
diff --git a/chromium/third_party/blink/renderer/core/css/media_values.h b/chromium/third_party/blink/renderer/core/css/media_values.h
index 9a774e643a6..7098decff8d 100644
--- a/chromium/third_party/blink/renderer/core/css/media_values.h
+++ b/chromium/third_party/blink/renderer/core/css/media_values.h
@@ -22,6 +22,7 @@ enum class ColorSpaceGamut;
enum class PreferredColorScheme;
enum class ForcedColors;
enum class NavigationControls;
+enum class ScreenSpanning;
PreferredColorScheme CSSValueIDToPreferredColorScheme(CSSValueID id);
@@ -86,6 +87,7 @@ class CORE_EXPORT MediaValues : public GarbageCollected<MediaValues> {
virtual bool PrefersReducedMotion() const = 0;
virtual ForcedColors GetForcedColors() const = 0;
virtual NavigationControls GetNavigationControls() const = 0;
+ virtual ScreenSpanning GetScreenSpanning() const = 0;
protected:
static double CalculateViewportWidth(LocalFrame*);
@@ -111,6 +113,7 @@ class CORE_EXPORT MediaValues : public GarbageCollected<MediaValues> {
static bool CalculatePrefersReducedMotion(LocalFrame*);
static ForcedColors CalculateForcedColors();
static NavigationControls CalculateNavigationControls(LocalFrame*);
+ static ScreenSpanning CalculateScreenSpanning(LocalFrame*);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/media_values_cached.cc b/chromium/third_party/blink/renderer/core/css/media_values_cached.cc
index 0f9c299e69f..725271ed49b 100644
--- a/chromium/third_party/blink/renderer/core/css/media_values_cached.cc
+++ b/chromium/third_party/blink/renderer/core/css/media_values_cached.cc
@@ -7,6 +7,7 @@
#include "third_party/blink/public/common/css/forced_colors.h"
#include "third_party/blink/public/common/css/navigation_controls.h"
#include "third_party/blink/public/common/css/preferred_color_scheme.h"
+#include "third_party/blink/public/common/css/screen_spanning.h"
#include "third_party/blink/renderer/core/css/css_primitive_value.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
@@ -37,7 +38,8 @@ MediaValuesCached::MediaValuesCachedData::MediaValuesCachedData()
preferred_color_scheme(PreferredColorScheme::kNoPreference),
prefers_reduced_motion(false),
forced_colors(ForcedColors::kNone),
- navigation_controls(NavigationControls::kNone) {}
+ navigation_controls(NavigationControls::kNone),
+ screen_spanning(ScreenSpanning::kNone) {}
MediaValuesCached::MediaValuesCachedData::MediaValuesCachedData(
Document& document)
@@ -80,6 +82,7 @@ MediaValuesCached::MediaValuesCachedData::MediaValuesCachedData(
prefers_reduced_motion = MediaValues::CalculatePrefersReducedMotion(frame);
forced_colors = MediaValues::CalculateForcedColors();
navigation_controls = MediaValues::CalculateNavigationControls(frame);
+ screen_spanning = MediaValues::CalculateScreenSpanning(frame);
}
}
@@ -210,4 +213,8 @@ NavigationControls MediaValuesCached::GetNavigationControls() const {
return data_.navigation_controls;
}
+ScreenSpanning MediaValuesCached::GetScreenSpanning() const {
+ return data_.screen_spanning;
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/media_values_cached.h b/chromium/third_party/blink/renderer/core/css/media_values_cached.h
index 4a82b2aa96e..cb0a8965258 100644
--- a/chromium/third_party/blink/renderer/core/css/media_values_cached.h
+++ b/chromium/third_party/blink/renderer/core/css/media_values_cached.h
@@ -40,6 +40,7 @@ class CORE_EXPORT MediaValuesCached final : public MediaValues {
bool prefers_reduced_motion;
ForcedColors forced_colors;
NavigationControls navigation_controls;
+ ScreenSpanning screen_spanning;
MediaValuesCachedData();
explicit MediaValuesCachedData(Document&);
@@ -69,6 +70,7 @@ class CORE_EXPORT MediaValuesCached final : public MediaValues {
data.prefers_reduced_motion = prefers_reduced_motion;
data.forced_colors = forced_colors;
data.navigation_controls = navigation_controls;
+ data.screen_spanning = screen_spanning;
return data;
}
};
@@ -109,6 +111,7 @@ class CORE_EXPORT MediaValuesCached final : public MediaValues {
bool PrefersReducedMotion() const override;
ForcedColors GetForcedColors() const override;
NavigationControls GetNavigationControls() const override;
+ ScreenSpanning GetScreenSpanning() const override;
void OverrideViewportDimensions(double width, double height) override;
diff --git a/chromium/third_party/blink/renderer/core/css/media_values_dynamic.cc b/chromium/third_party/blink/renderer/core/css/media_values_dynamic.cc
index 0b80c39984c..1f1a000dc7f 100644
--- a/chromium/third_party/blink/renderer/core/css/media_values_dynamic.cc
+++ b/chromium/third_party/blink/renderer/core/css/media_values_dynamic.cc
@@ -160,6 +160,10 @@ NavigationControls MediaValuesDynamic::GetNavigationControls() const {
return CalculateNavigationControls(frame_);
}
+ScreenSpanning MediaValuesDynamic::GetScreenSpanning() const {
+ return CalculateScreenSpanning(frame_);
+}
+
Document* MediaValuesDynamic::GetDocument() const {
return frame_->GetDocument();
}
diff --git a/chromium/third_party/blink/renderer/core/css/media_values_dynamic.h b/chromium/third_party/blink/renderer/core/css/media_values_dynamic.h
index 779a9fb4b8d..cc1c0f2f8f5 100644
--- a/chromium/third_party/blink/renderer/core/css/media_values_dynamic.h
+++ b/chromium/third_party/blink/renderer/core/css/media_values_dynamic.h
@@ -52,6 +52,7 @@ class CORE_EXPORT MediaValuesDynamic : public MediaValues {
bool PrefersReducedMotion() const override;
ForcedColors GetForcedColors() const override;
NavigationControls GetNavigationControls() const override;
+ ScreenSpanning GetScreenSpanning() const override;
Document* GetDocument() const override;
bool HasValues() const override;
void OverrideViewportDimensions(double width, double height) override;
diff --git a/chromium/third_party/blink/renderer/core/css/offscreen_font_selector.cc b/chromium/third_party/blink/renderer/core/css/offscreen_font_selector.cc
index 2042a1618e6..24a9d2e6242 100644
--- a/chromium/third_party/blink/renderer/core/css/offscreen_font_selector.cc
+++ b/chromium/third_party/blink/renderer/core/css/offscreen_font_selector.cc
@@ -103,7 +103,7 @@ void OffscreenFontSelector::FontCacheInvalidated() {
font_face_cache_.IncrementVersion();
}
-void OffscreenFontSelector::FontFaceInvalidated() {
+void OffscreenFontSelector::FontFaceInvalidated(FontInvalidationReason) {
FontCacheInvalidated();
}
diff --git a/chromium/third_party/blink/renderer/core/css/offscreen_font_selector.h b/chromium/third_party/blink/renderer/core/css/offscreen_font_selector.h
index 0a32bc74468..e22ce48f1ba 100644
--- a/chromium/third_party/blink/renderer/core/css/offscreen_font_selector.h
+++ b/chromium/third_party/blink/renderer/core/css/offscreen_font_selector.h
@@ -55,7 +55,7 @@ class CORE_EXPORT OffscreenFontSelector : public FontSelector {
}
void FontCacheInvalidated() override;
- void FontFaceInvalidated() override;
+ void FontFaceInvalidated(FontInvalidationReason) override;
void UpdateGenericFontFamilySettings(const GenericFontFamilySettings&);
diff --git a/chromium/third_party/blink/renderer/core/css/parser/at_rule_descriptor_parser.cc b/chromium/third_party/blink/renderer/core/css/parser/at_rule_descriptor_parser.cc
index 78f9ce32541..05ff29080e3 100644
--- a/chromium/third_party/blink/renderer/core/css/parser/at_rule_descriptor_parser.cc
+++ b/chromium/third_party/blink/renderer/core/css/parser/at_rule_descriptor_parser.cc
@@ -80,7 +80,8 @@ CSSValue* ConsumeFontFaceSrcURI(CSSParserTokenRange& range,
CSSFontFaceSrcValue* uri_value(CSSFontFaceSrcValue::Create(
url, context.CompleteURL(url), context.GetReferrer(),
context.ShouldCheckContentSecurityPolicy(),
- context.IsOriginClean() ? OriginClean::kTrue : OriginClean::kFalse));
+ context.IsOriginClean() ? OriginClean::kTrue : OriginClean::kFalse,
+ context.IsAdRelated()));
if (range.Peek().FunctionId() != CSSValueID::kFormat)
return uri_value;
@@ -109,7 +110,8 @@ CSSValue* ConsumeFontFaceSrcLocal(CSSParserTokenRange& range,
return nullptr;
return CSSFontFaceSrcValue::CreateLocal(
arg.Value().ToString(), should_check_content_security_policy,
- context.IsOriginClean() ? OriginClean::kTrue : OriginClean::kFalse);
+ context.IsOriginClean() ? OriginClean::kTrue : OriginClean::kFalse,
+ context.IsAdRelated());
}
if (args.Peek().GetType() == kIdentToken) {
String family_name = css_parsing_utils::ConcatenateFamilyName(args);
@@ -117,7 +119,8 @@ CSSValue* ConsumeFontFaceSrcLocal(CSSParserTokenRange& range,
return nullptr;
return CSSFontFaceSrcValue::CreateLocal(
family_name, should_check_content_security_policy,
- context.IsOriginClean() ? OriginClean::kTrue : OriginClean::kFalse);
+ context.IsOriginClean() ? OriginClean::kTrue : OriginClean::kFalse,
+ context.IsAdRelated());
}
return nullptr;
}
diff --git a/chromium/third_party/blink/renderer/core/css/parser/css_parser_context.cc b/chromium/third_party/blink/renderer/core/css/parser/css_parser_context.cc
index 3976f68094f..62ce75ba3d9 100644
--- a/chromium/third_party/blink/renderer/core/css/parser/css_parser_context.cc
+++ b/chromium/third_party/blink/renderer/core/css/parser/css_parser_context.cc
@@ -49,7 +49,9 @@ CSSParserContext::CSSParserContext(const CSSParserContext* other,
other->secure_context_mode_,
other->should_check_content_security_policy_,
use_counter_document,
- other->resource_fetch_restriction_) {}
+ other->resource_fetch_restriction_) {
+ is_ad_related_ = other->is_ad_related_;
+}
CSSParserContext::CSSParserContext(
const CSSParserContext* other,
@@ -71,7 +73,9 @@ CSSParserContext::CSSParserContext(
other->secure_context_mode_,
other->should_check_content_security_policy_,
use_counter_document,
- other->resource_fetch_restriction_) {}
+ other->resource_fetch_restriction_) {
+ is_ad_related_ = other->is_ad_related_;
+}
CSSParserContext::CSSParserContext(CSSParserMode mode,
SecureContextMode secure_context_mode,
@@ -186,6 +190,7 @@ bool CSSParserContext::operator==(const CSSParserContext& other) const {
return base_url_ == other.base_url_ && origin_clean_ == other.origin_clean_ &&
charset_ == other.charset_ && mode_ == other.mode_ &&
match_mode_ == other.match_mode_ && profile_ == other.profile_ &&
+ is_ad_related_ == other.is_ad_related_ &&
is_html_document_ == other.is_html_document_ &&
use_legacy_background_size_shorthand_behavior_ ==
other.use_legacy_background_size_shorthand_behavior_ &&
@@ -263,7 +268,7 @@ const ExecutionContext* CSSParserContext::GetExecutionContext() const {
void CSSParserContext::ReportLayoutAnimationsViolationIfNeeded(
const StyleRuleKeyframe& rule) const {
- if (!document_)
+ if (!document_ || !document_->GetExecutionContext())
return;
for (size_t i = 0; i < rule.Properties().PropertyCount(); ++i) {
const CSSProperty& property = rule.Properties().PropertyAt(i).Property();
diff --git a/chromium/third_party/blink/renderer/core/css/parser/css_parser_context.h b/chromium/third_party/blink/renderer/core/css/parser/css_parser_context.h
index b9d230e1ed3..2dce736a757 100644
--- a/chromium/third_party/blink/renderer/core/css/parser/css_parser_context.h
+++ b/chromium/third_party/blink/renderer/core/css/parser/css_parser_context.h
@@ -87,6 +87,7 @@ class CORE_EXPORT CSSParserContext final
const KURL& BaseURL() const { return base_url_; }
const WTF::TextEncoding& Charset() const { return charset_; }
const Referrer& GetReferrer() const { return referrer_; }
+ bool IsAdRelated() const { return is_ad_related_; }
bool IsHTMLDocument() const { return is_html_document_; }
enum ResourceFetchRestriction ResourceFetchRestriction() const {
return resource_fetch_restriction_;
@@ -108,6 +109,8 @@ class CORE_EXPORT CSSParserContext final
// override this field.
void SetMode(CSSParserMode mode) { mode_ = mode; }
+ void SetIsAdRelated() { is_ad_related_ = true; }
+
KURL CompleteURL(const String& url) const;
SecureContextMode GetSecureContextMode() const {
@@ -170,6 +173,11 @@ class CORE_EXPORT CSSParserContext final
CSSParserMode match_mode_;
SelectorProfile profile_ = kLiveProfile;
Referrer referrer_;
+
+ // Whether the associated stylesheet's ResourceRequest is an ad resource. If
+ // there is no associated ResourceRequest, whether ad script is on the v8 call
+ // stack at stylesheet creation. Not set for presentation attributes.
+ bool is_ad_related_ = false;
bool is_html_document_;
bool use_legacy_background_size_shorthand_behavior_;
SecureContextMode secure_context_mode_;
diff --git a/chromium/third_party/blink/renderer/core/css/parser/css_parser_fast_paths.cc b/chromium/third_party/blink/renderer/core/css/parser/css_parser_fast_paths.cc
index faf3e61ee94..7f761601baa 100644
--- a/chromium/third_party/blink/renderer/core/css/parser/css_parser_fast_paths.cc
+++ b/chromium/third_party/blink/renderer/core/css/parser/css_parser_fast_paths.cc
@@ -12,6 +12,7 @@
#include "third_party/blink/renderer/core/css/css_initial_value.h"
#include "third_party/blink/renderer/core/css/css_numeric_literal_value.h"
#include "third_party/blink/renderer/core/css/css_primitive_value.h"
+#include "third_party/blink/renderer/core/css/css_revert_value.h"
#include "third_party/blink/renderer/core/css/css_unset_value.h"
#include "third_party/blink/renderer/core/css/parser/css_parser_idioms.h"
#include "third_party/blink/renderer/core/css/parser/css_property_parser.h"
@@ -647,6 +648,10 @@ bool CSSParserFastPaths::IsValidKeywordPropertyAndValue(
DCHECK(RuntimeEnabledFeatures::CSSMathStyleEnabled());
return value_id == CSSValueID::kInline ||
value_id == CSSValueID::kDisplay;
+ case CSSPropertyID::kMathSuperscriptShiftStyle:
+ DCHECK(RuntimeEnabledFeatures::CSSMathSuperscriptShiftStyleEnabled());
+ return value_id == CSSValueID::kInline ||
+ value_id == CSSValueID::kDisplay;
case CSSPropertyID::kObjectFit:
return value_id == CSSValueID::kFill ||
value_id == CSSValueID::kContain ||
@@ -684,6 +689,10 @@ bool CSSParserFastPaths::IsValidKeywordPropertyAndValue(
return value_id == CSSValueID::kAuto || value_id == CSSValueID::kAvoid ||
value_id == CSSValueID::kAvoidPage ||
value_id == CSSValueID::kAvoidColumn;
+ case CSSPropertyID::kPageOrientation:
+ return value_id == CSSValueID::kUpright ||
+ value_id == CSSValueID::kRotateLeft ||
+ value_id == CSSValueID::kRotateRight;
case CSSPropertyID::kPointerEvents:
return value_id == CSSValueID::kVisible ||
value_id == CSSValueID::kNone || value_id == CSSValueID::kAll ||
@@ -767,11 +776,12 @@ bool CSSParserFastPaths::IsValidKeywordPropertyAndValue(
value_id == CSSValueID::kOptimizespeed ||
value_id == CSSValueID::kOptimizelegibility ||
value_id == CSSValueID::kGeometricprecision;
- case CSSPropertyID::kTextTransform: // capitalize | uppercase | lowercase |
- // none
+ case CSSPropertyID::kTextTransform:
return (value_id >= CSSValueID::kCapitalize &&
value_id <= CSSValueID::kLowercase) ||
- value_id == CSSValueID::kNone;
+ value_id == CSSValueID::kNone ||
+ (RuntimeEnabledFeatures::CSSMathVariantEnabled() &&
+ value_id == CSSValueID::kMathAuto);
case CSSPropertyID::kUnicodeBidi:
return value_id == CSSValueID::kNormal ||
value_id == CSSValueID::kEmbed ||
@@ -793,7 +803,7 @@ bool CSSParserFastPaths::IsValidKeywordPropertyAndValue(
return (value_id >= CSSValueID::kDrag &&
value_id <= CSSValueID::kNoDrag) ||
value_id == CSSValueID::kNone;
- case CSSPropertyID::kWebkitAppearance:
+ case CSSPropertyID::kAppearance:
return (value_id >= CSSValueID::kCheckbox &&
value_id <= CSSValueID::kTextarea) ||
value_id == CSSValueID::kNone || value_id == CSSValueID::kAuto;
@@ -916,6 +926,8 @@ bool CSSParserFastPaths::IsValidKeywordPropertyAndValue(
value_id == CSSValueID::kVisual;
case CSSPropertyID::kWebkitRubyPosition:
return value_id == CSSValueID::kBefore || value_id == CSSValueID::kAfter;
+ case CSSPropertyID::kRubyPosition:
+ return value_id == CSSValueID::kOver || value_id == CSSValueID::kUnder;
case CSSPropertyID::kWebkitTextCombine:
return value_id == CSSValueID::kNone ||
value_id == CSSValueID::kHorizontal;
@@ -1009,6 +1021,7 @@ bool CSSParserFastPaths::IsKeywordPropertyID(CSSPropertyID property_id) {
case CSSPropertyID::kListStyleType:
case CSSPropertyID::kMaskType:
case CSSPropertyID::kMathStyle:
+ case CSSPropertyID::kMathSuperscriptShiftStyle:
case CSSPropertyID::kObjectFit:
case CSSPropertyID::kOutlineStyle:
case CSSPropertyID::kOverflowAnchor:
@@ -1020,6 +1033,7 @@ bool CSSParserFastPaths::IsKeywordPropertyID(CSSPropertyID property_id) {
case CSSPropertyID::kBreakAfter:
case CSSPropertyID::kBreakBefore:
case CSSPropertyID::kBreakInside:
+ case CSSPropertyID::kPageOrientation:
case CSSPropertyID::kPointerEvents:
case CSSPropertyID::kPosition:
case CSSPropertyID::kResize:
@@ -1028,6 +1042,7 @@ bool CSSParserFastPaths::IsKeywordPropertyID(CSSPropertyID property_id) {
case CSSPropertyID::kOverscrollBehaviorBlock:
case CSSPropertyID::kOverscrollBehaviorX:
case CSSPropertyID::kOverscrollBehaviorY:
+ case CSSPropertyID::kRubyPosition:
case CSSPropertyID::kShapeRendering:
case CSSPropertyID::kSpeak:
case CSSPropertyID::kStrokeLinecap:
@@ -1049,7 +1064,6 @@ bool CSSParserFastPaths::IsKeywordPropertyID(CSSPropertyID property_id) {
case CSSPropertyID::kVectorEffect:
case CSSPropertyID::kVisibility:
case CSSPropertyID::kWebkitAppRegion:
- case CSSPropertyID::kWebkitAppearance:
case CSSPropertyID::kBackfaceVisibility:
case CSSPropertyID::kBorderBlockEndStyle:
case CSSPropertyID::kBorderBlockStartStyle:
@@ -1107,13 +1121,15 @@ static CSSValue* ParseKeywordValue(CSSPropertyID property_id,
DCHECK(!string.IsEmpty());
if (!CSSParserFastPaths::IsKeywordPropertyID(property_id)) {
- // All properties accept the values of "initial," "inherit" and "unset".
+ // All properties accept CSS-wide keywords.
if (!EqualIgnoringASCIICase(string, "initial") &&
!EqualIgnoringASCIICase(string, "inherit") &&
- !EqualIgnoringASCIICase(string, "unset"))
+ !EqualIgnoringASCIICase(string, "unset") &&
+ (!RuntimeEnabledFeatures::CSSRevertEnabled() ||
+ !EqualIgnoringASCIICase(string, "revert")))
return nullptr;
- // Parse initial/inherit/unset shorthands using the CSSPropertyParser.
+ // Parse CSS-wide keyword shorthands using the CSSPropertyParser.
if (shorthandForProperty(property_id).length())
return nullptr;
@@ -1133,6 +1149,10 @@ static CSSValue* ParseKeywordValue(CSSPropertyID property_id,
return CSSInitialValue::Create();
if (value_id == CSSValueID::kUnset)
return cssvalue::CSSUnsetValue::Create();
+ if (RuntimeEnabledFeatures::CSSRevertEnabled() &&
+ value_id == CSSValueID::kRevert) {
+ return cssvalue::CSSRevertValue::Create();
+ }
if (CSSParserFastPaths::IsValidKeywordPropertyAndValue(property_id, value_id,
parser_mode))
return CSSIdentifierValue::Create(value_id);
diff --git a/chromium/third_party/blink/renderer/core/css/parser/css_parser_fast_paths_test.cc b/chromium/third_party/blink/renderer/core/css/parser/css_parser_fast_paths_test.cc
index 5d01a442409..a54b79c4d0f 100644
--- a/chromium/third_party/blink/renderer/core/css/parser/css_parser_fast_paths_test.cc
+++ b/chromium/third_party/blink/renderer/core/css/parser/css_parser_fast_paths_test.cc
@@ -8,6 +8,7 @@
#include "third_party/blink/renderer/core/css/css_color_value.h"
#include "third_party/blink/renderer/core/css/css_identifier_value.h"
#include "third_party/blink/renderer/core/css/css_value_list.h"
+#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
namespace blink {
@@ -53,6 +54,46 @@ TEST(CSSParserFastPathsTest, ParseCSSWideKeywords) {
ASSERT_EQ(nullptr, value);
}
+TEST(CSSParserFastPathsTest, ParseRevert) {
+ // Revert enabled, IsKeywordPropertyID=false
+ {
+ DCHECK(!CSSParserFastPaths::IsKeywordPropertyID(CSSPropertyID::kMarginTop));
+ ScopedCSSRevertForTest scoped_revert(true);
+ CSSValue* value = CSSParserFastPaths::MaybeParseValue(
+ CSSPropertyID::kMarginTop, "revert", kHTMLStandardMode);
+ ASSERT_TRUE(value);
+ EXPECT_TRUE(value->IsRevertValue());
+ }
+
+ // Revert enabled, IsKeywordPropertyID=true
+ {
+ DCHECK(CSSParserFastPaths::IsKeywordPropertyID(CSSPropertyID::kDisplay));
+ ScopedCSSRevertForTest scoped_revert(true);
+ CSSValue* value = CSSParserFastPaths::MaybeParseValue(
+ CSSPropertyID::kDisplay, "revert", kHTMLStandardMode);
+ ASSERT_TRUE(value);
+ EXPECT_TRUE(value->IsRevertValue());
+ }
+
+ // Revert disabled, IsKeywordPropertyID=false
+ {
+ DCHECK(!CSSParserFastPaths::IsKeywordPropertyID(CSSPropertyID::kMarginTop));
+ ScopedCSSRevertForTest scoped_revert(false);
+ CSSValue* value = CSSParserFastPaths::MaybeParseValue(
+ CSSPropertyID::kMarginTop, "revert", kHTMLStandardMode);
+ EXPECT_FALSE(value);
+ }
+
+ // Revert disabled, IsKeywordPropertyID=true
+ {
+ DCHECK(CSSParserFastPaths::IsKeywordPropertyID(CSSPropertyID::kDisplay));
+ ScopedCSSRevertForTest scoped_revert(false);
+ CSSValue* value = CSSParserFastPaths::MaybeParseValue(
+ CSSPropertyID::kDisplay, "revert", kHTMLStandardMode);
+ EXPECT_FALSE(value);
+ }
+}
+
TEST(CSSParserFastPathsTest, ParseTransform) {
CSSValue* value = CSSParserFastPaths::MaybeParseValue(
CSSPropertyID::kTransform, "translate(5.5px, 5px)", kHTMLStandardMode);
diff --git a/chromium/third_party/blink/renderer/core/css/parser/css_parser_impl.cc b/chromium/third_party/blink/renderer/core/css/parser/css_parser_impl.cc
index bf766c0312a..8ea1249ab31 100644
--- a/chromium/third_party/blink/renderer/core/css/parser/css_parser_impl.cc
+++ b/chromium/third_party/blink/renderer/core/css/parser/css_parser_impl.cc
@@ -718,9 +718,8 @@ StyleRuleViewport* CSSParserImpl::ConsumeViewportRule(
const CSSParserTokenRange prelude,
const RangeOffset& prelude_offset,
CSSParserTokenStream& block) {
- // Allow @viewport rules from UA stylesheets even if the feature is disabled.
- if (!RuntimeEnabledFeatures::CSSViewportEnabled() &&
- !IsUASheetBehavior(context_->Mode()))
+ // Allow @viewport rules from UA stylesheets only.
+ if (!IsUASheetBehavior(context_->Mode()))
return nullptr;
if (!prelude.AtEnd())
diff --git a/chromium/third_party/blink/renderer/core/css/parser/css_property_parser.cc b/chromium/third_party/blink/renderer/core/css/parser/css_property_parser.cc
index 1365fb4c828..8fcf3c55272 100644
--- a/chromium/third_party/blink/renderer/core/css/parser/css_property_parser.cc
+++ b/chromium/third_party/blink/renderer/core/css/parser/css_property_parser.cc
@@ -7,6 +7,7 @@
#include "third_party/blink/renderer/core/css/css_inherited_value.h"
#include "third_party/blink/renderer/core/css/css_initial_value.h"
#include "third_party/blink/renderer/core/css/css_pending_substitution_value.h"
+#include "third_party/blink/renderer/core/css/css_revert_value.h"
#include "third_party/blink/renderer/core/css/css_unicode_range_value.h"
#include "third_party/blink/renderer/core/css/css_unset_value.h"
#include "third_party/blink/renderer/core/css/css_variable_reference_value.h"
@@ -45,6 +46,8 @@ const CSSValue* MaybeConsumeCSSWideKeyword(CSSParserTokenRange& range) {
value = CSSInheritedValue::Create();
if (id == CSSValueID::kUnset)
value = cssvalue::CSSUnsetValue::Create();
+ if (RuntimeEnabledFeatures::CSSRevertEnabled() && id == CSSValueID::kRevert)
+ value = cssvalue::CSSRevertValue::Create();
if (value)
range = local_range;
@@ -76,8 +79,7 @@ bool CSSPropertyParser::ParseValue(
bool parse_success;
if (rule_type == StyleRule::kViewport) {
parse_success =
- (RuntimeEnabledFeatures::CSSViewportEnabled() ||
- IsUASheetBehavior(context->Mode())) &&
+ IsUASheetBehavior(context->Mode()) &&
parser.ParseViewportDescriptor(resolved_property, important);
} else if (rule_type == StyleRule::kFontFace) {
parse_success = parser.ParseFontFaceDescriptor(resolved_property);
@@ -120,7 +122,7 @@ bool CSSPropertyParser::ParseValueStart(CSSPropertyID unresolved_property,
CSSParserTokenRange original_range = range_;
CSSPropertyID property_id = resolveCSSPropertyID(unresolved_property);
const CSSProperty& property = CSSProperty::Get(property_id);
- // If a CSSPropertyID is only a known descriptor (@fontface, @viewport), not a
+ // If a CSSPropertyID is only a known descriptor (@fontface, @property), not a
// style property, it will not be a valid declaration.
if (!property.IsProperty())
return false;
@@ -331,8 +333,7 @@ static CSSValue* ConsumeSingleViewportDescriptor(
bool CSSPropertyParser::ParseViewportDescriptor(CSSPropertyID prop_id,
bool important) {
- DCHECK(RuntimeEnabledFeatures::CSSViewportEnabled() ||
- IsUASheetBehavior(context_->Mode()));
+ DCHECK(IsUASheetBehavior(context_->Mode()));
switch (prop_id) {
case CSSPropertyID::kWidth: {
diff --git a/chromium/third_party/blink/renderer/core/css/parser/css_property_parser_helpers.cc b/chromium/third_party/blink/renderer/core/css/parser/css_property_parser_helpers.cc
index c2034ea64b7..cdf2b7aa8fb 100644
--- a/chromium/third_party/blink/renderer/core/css/parser/css_property_parser_helpers.cc
+++ b/chromium/third_party/blink/renderer/core/css/parser/css_property_parser_helpers.cc
@@ -11,7 +11,7 @@
#include "third_party/blink/renderer/core/css/css_image_set_value.h"
#include "third_party/blink/renderer/core/css/css_image_value.h"
#include "third_party/blink/renderer/core/css/css_initial_value.h"
-#include "third_party/blink/renderer/core/css/css_light_dark_color_pair.h"
+#include "third_party/blink/renderer/core/css/css_light_dark_value_pair.h"
#include "third_party/blink/renderer/core/css/css_math_expression_node.h"
#include "third_party/blink/renderer/core/css/css_math_function_value.h"
#include "third_party/blink/renderer/core/css/css_numeric_literal_value.h"
@@ -29,7 +29,9 @@
#include "third_party/blink/renderer/core/css/properties/css_property.h"
#include "third_party/blink/renderer/core/css/properties/longhand.h"
#include "third_party/blink/renderer/core/css/style_color.h"
+#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/frame/web_feature.h"
+#include "third_party/blink/renderer/core/inspector/console_message.h"
#include "third_party/blink/renderer/core/style_property_shorthand.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
#include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
@@ -149,6 +151,29 @@ CSSFunctionValue* ConsumeFilterFunction(CSSParserTokenRange& range,
return filter_value;
}
+template <typename Func, typename... Args>
+CSSLightDarkValuePair* ConsumeInternalLightDark(Func consume_value,
+ CSSParserTokenRange& range,
+ const CSSParserContext& context,
+ Args&&... args) {
+ if (range.Peek().FunctionId() != CSSValueID::kInternalLightDark)
+ return nullptr;
+ if (!isValueAllowedInMode(CSSValueID::kInternalLightDark, context.Mode()))
+ return nullptr;
+ CSSParserTokenRange range_copy = range;
+ CSSParserTokenRange arg_range = ConsumeFunction(range_copy);
+ CSSValue* light_value =
+ consume_value(arg_range, context, std::forward<Args>(args)...);
+ if (!light_value || !ConsumeCommaIncludingWhitespace(arg_range))
+ return nullptr;
+ CSSValue* dark_value =
+ consume_value(arg_range, context, std::forward<Args>(args)...);
+ if (!dark_value || !arg_range.AtEnd())
+ return nullptr;
+ range = range_copy;
+ return MakeGarbageCollected<CSSLightDarkValuePair>(light_value, dark_value);
+}
+
} // namespace
void Complete4Sides(CSSValue* side[4]) {
@@ -468,18 +493,9 @@ CSSPrimitiveValue* ConsumeAlphaValue(CSSParserTokenRange& range,
bool CanConsumeCalcValue(CalculationCategory category,
CSSParserMode css_parser_mode) {
- if (category == kCalcLength || category == kCalcPercent ||
- category == kCalcPercentLength)
- return true;
-
- if (css_parser_mode != kSVGAttributeMode)
- return false;
-
- if (category == kCalcNumber || category == kCalcPercentNumber ||
- category == kCalcLengthNumber || category == kCalcPercentLengthNumber)
- return true;
-
- return false;
+ return category == kCalcLength || category == kCalcPercent ||
+ category == kCalcPercentLength ||
+ (css_parser_mode == kSVGAttributeMode && category == kCalcNumber);
}
CSSPrimitiveValue* ConsumeLengthOrPercent(CSSParserTokenRange& range,
@@ -510,16 +526,7 @@ bool IsNonZeroUserUnitsValue(const CSSPrimitiveValue* value) {
value->GetDoubleValue() != 0;
}
const auto& math_value = To<CSSMathFunctionValue>(*value);
- switch (math_value.Category()) {
- case kCalcNumber:
- return math_value.DoubleValue() != 0;
- case kCalcPercentNumber:
- case kCalcLengthNumber:
- case kCalcPercentLengthNumber:
- return true;
- default:
- return false;
- }
+ return math_value.Category() == kCalcNumber && math_value.DoubleValue() != 0;
}
} // namespace
@@ -659,8 +666,6 @@ CSSCustomIdentValue* ConsumeCustomIdentWithToken(
if (EqualIgnoringASCIICase(token.Value(), "default"))
context.Count(WebFeature::kDefaultInCustomIdent);
- if (EqualIgnoringASCIICase(token.Value(), "revert"))
- context.Count(WebFeature::kRevertInCustomIdent);
return MakeGarbageCollected<CSSCustomIdentValue>(
token.Value().ToAtomicString());
@@ -901,25 +906,6 @@ static bool ParseColorFunction(CSSParserTokenRange& range,
return true;
}
-static CSSLightDarkColorPair* ParseLightDarkColor(
- CSSParserTokenRange& range,
- const CSSParserContext& context) {
- if (range.Peek().FunctionId() != CSSValueID::kInternalLightDarkColor)
- return nullptr;
- if (!isValueAllowedInMode(CSSValueID::kInternalLightDarkColor,
- context.Mode()))
- return nullptr;
- CSSParserContext::ParserModeOverridingScope scope(context, kUASheetMode);
- CSSParserTokenRange args = ConsumeFunction(range);
- CSSValue* light_color = ConsumeColor(args, context);
- if (!light_color || !ConsumeCommaIncludingWhitespace(args))
- return nullptr;
- CSSValue* dark_color = ConsumeColor(args, context);
- if (!dark_color || !args.AtEnd())
- return nullptr;
- return MakeGarbageCollected<CSSLightDarkColorPair>(light_color, dark_color);
-}
-
CSSValue* ConsumeColor(CSSParserTokenRange& range,
const CSSParserContext& context,
bool accept_quirky_colors) {
@@ -933,7 +919,8 @@ CSSValue* ConsumeColor(CSSParserTokenRange& range,
RGBA32 color = Color::kTransparent;
if (!ParseHexColor(range, color, accept_quirky_colors) &&
!ParseColorFunction(range, context, color)) {
- return ParseLightDarkColor(range, context);
+ return ConsumeInternalLightDark(ConsumeColor, range, context,
+ accept_quirky_colors);
}
return cssvalue::CSSColorValue::Create(color);
}
@@ -1795,7 +1782,8 @@ static CSSValue* CreateCSSImageValueWithReferrer(
const CSSParserContext& context) {
CSSValue* image_value = MakeGarbageCollected<CSSImageValue>(
raw_value, context.CompleteURL(raw_value), context.GetReferrer(),
- context.IsOriginClean() ? OriginClean::kTrue : OriginClean::kFalse);
+ context.IsOriginClean() ? OriginClean::kTrue : OriginClean::kFalse,
+ context.IsAdRelated());
return image_value;
}
@@ -1860,6 +1848,7 @@ CSSValue* ConsumeImage(CSSParserTokenRange& range,
IsGeneratedImage(id)) {
return ConsumeGeneratedImage(range, context);
}
+ return ConsumeInternalLightDark(ConsumeImageOrNone, range, context);
}
return nullptr;
}
@@ -1868,7 +1857,9 @@ CSSValue* ConsumeImage(CSSParserTokenRange& range,
bool IsCSSWideKeyword(StringView keyword) {
return EqualIgnoringASCIICase(keyword, "initial") ||
EqualIgnoringASCIICase(keyword, "inherit") ||
- EqualIgnoringASCIICase(keyword, "unset");
+ EqualIgnoringASCIICase(keyword, "unset") ||
+ (RuntimeEnabledFeatures::CSSRevertEnabled() &&
+ EqualIgnoringASCIICase(keyword, "revert"));
}
// https://drafts.csswg.org/css-cascade/#default
@@ -1952,7 +1943,30 @@ void CountKeywordOnlyPropertyUsage(CSSPropertyID property,
if (!context.IsUseCounterRecordingEnabled())
return;
switch (property) {
- case CSSPropertyID::kWebkitAppearance: {
+ case CSSPropertyID::kAppearance:
+ if (value_id == CSSValueID::kInnerSpinButton ||
+ value_id == CSSValueID::kMediaSlider ||
+ value_id == CSSValueID::kMediaSliderthumb ||
+ value_id == CSSValueID::kMediaVolumeSlider ||
+ value_id == CSSValueID::kMediaVolumeSliderthumb ||
+ value_id == CSSValueID::kSliderVertical ||
+ value_id == CSSValueID::kSliderthumbHorizontal ||
+ value_id == CSSValueID::kSliderthumbVertical ||
+ value_id == CSSValueID::kSearchfieldCancelButton) {
+ if (const auto* document = context.GetDocument()) {
+ document->AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>(
+ mojom::blink::ConsoleMessageSource::kOther,
+ mojom::blink::ConsoleMessageLevel::kWarning,
+ String("The keyword '") + getValueName(value_id) +
+ "' specified to an 'appearance' property is not "
+ "standardized. It will be removed in the future."));
+ }
+ }
+ FALLTHROUGH;
+ // This function distinguishes 'appearance' and '-webkit-appearance'
+ // though other property aliases are handles as their aliased properties.
+ // See Appearance::ParseSingleValue().
+ case CSSPropertyID::kAliasWebkitAppearance: {
WebFeature feature;
if (value_id == CSSValueID::kNone) {
feature = WebFeature::kCSSValueAppearanceNone;
diff --git a/chromium/third_party/blink/renderer/core/css/parser/css_property_parser_helpers.h b/chromium/third_party/blink/renderer/core/css/parser/css_property_parser_helpers.h
index 45c628c090a..6c4ea21506f 100644
--- a/chromium/third_party/blink/renderer/core/css/parser/css_property_parser_helpers.h
+++ b/chromium/third_party/blink/renderer/core/css/parser/css_property_parser_helpers.h
@@ -150,7 +150,8 @@ CSSValue* ConsumeImageOrNone(CSSParserTokenRange&, const CSSParserContext&);
CSSValue* ConsumeAxis(CSSParserTokenRange&, const CSSParserContext& context);
-bool IsCSSWideKeyword(StringView);
+// See also css_parsing_utils::IsCSSWideKeyword.
+CORE_EXPORT bool IsCSSWideKeyword(StringView);
bool IsRevertKeyword(StringView);
bool IsDefaultKeyword(StringView);
diff --git a/chromium/third_party/blink/renderer/core/css/parser/css_property_parser_helpers_test.cc b/chromium/third_party/blink/renderer/core/css/parser/css_property_parser_helpers_test.cc
new file mode 100644
index 00000000000..2eb068af368
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/css/parser/css_property_parser_helpers_test.cc
@@ -0,0 +1,25 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/css/parser/css_property_parser_helpers.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+
+namespace blink {
+
+TEST(CSSPropertyParserHelpersTest, ParseRevert) {
+ {
+ ScopedCSSRevertForTest scoped_revert(true);
+ EXPECT_TRUE(css_property_parser_helpers::IsCSSWideKeyword("revert"));
+ }
+
+ {
+ ScopedCSSRevertForTest scoped_revert(false);
+ EXPECT_FALSE(css_property_parser_helpers::IsCSSWideKeyword("revert"));
+ }
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/parser/css_property_parser_test.cc b/chromium/third_party/blink/renderer/core/css/parser/css_property_parser_test.cc
index edd37e2658e..18ae4658dc3 100644
--- a/chromium/third_party/blink/renderer/core/css/parser/css_property_parser_test.cc
+++ b/chromium/third_party/blink/renderer/core/css/parser/css_property_parser_test.cc
@@ -638,20 +638,6 @@ TEST_F(CSSPropertyUseCounterTest, CSSPropertyDefaultAnimationNameUseCount) {
EXPECT_TRUE(IsCounted(feature));
}
-TEST_F(CSSPropertyUseCounterTest, CSSPropertyRevertAnimationNameUseCount) {
- WebFeature feature = WebFeature::kRevertInCustomIdent;
- EXPECT_FALSE(IsCounted(feature));
-
- ParseProperty(CSSPropertyID::kAnimationName, "initial");
- EXPECT_FALSE(IsCounted(feature));
-
- ParseProperty(CSSPropertyID::kAnimationName, "test");
- EXPECT_FALSE(IsCounted(feature));
-
- ParseProperty(CSSPropertyID::kAnimationName, "revert");
- EXPECT_TRUE(IsCounted(feature));
-}
-
TEST_F(CSSPropertyUseCounterTest, CSSPropertyContainStyleUseCount) {
WebFeature feature = WebFeature::kCSSValueContainStyle;
EXPECT_FALSE(IsCounted(feature));
@@ -675,16 +661,18 @@ TEST_F(CSSPropertyUseCounterTest, CSSPropertyFontSizeWebkitXxxLargeUseCount) {
EXPECT_TRUE(IsCounted(feature));
}
-TEST(CSSPropertyParserTest, InternalLightDarkColorAuthor) {
+TEST(CSSPropertyParserTest, InternalLightDarkAuthor) {
auto* context = MakeGarbageCollected<CSSParserContext>(
kHTMLStandardMode, SecureContextMode::kInsecureContext);
- // -internal-light-dark-color() is only valid in UA sheets.
+ // -internal-light-dark() is only valid in UA sheets.
ASSERT_FALSE(CSSParser::ParseSingleValue(
- CSSPropertyID::kColor, "-internal-light-dark-color(#000000, #ffffff)",
+ CSSPropertyID::kColor, "-internal-light-dark(#000000, #ffffff)",
context));
ASSERT_FALSE(CSSParser::ParseSingleValue(
- CSSPropertyID::kColor, "-internal-light-dark-color(red, green)",
- context));
+ CSSPropertyID::kColor, "-internal-light-dark(red, green)", context));
+ ASSERT_FALSE(CSSParser::ParseSingleValue(
+ CSSPropertyID::kBackgroundImage,
+ "-internal-light-dark(url(light.png), url(dark.png))", context));
}
TEST(CSSPropertyParserTest, UAInternalLightDarkColor) {
@@ -695,14 +683,14 @@ TEST(CSSPropertyParserTest, UAInternalLightDarkColor) {
const char* value;
bool valid;
} tests[] = {
- {"-internal-light-dark-color()", false},
- {"-internal-light-dark-color(#feedab)", false},
- {"-internal-light-dark-color(red blue)", false},
- {"-internal-light-dark-color(red,,blue)", false},
- {"-internal-light-dark-color(red, blue)", true},
- {"-internal-light-dark-color(#000000, #ffffff)", true},
- {"-internal-light-dark-color(rgb(0, 0, 0), hsl(180, 75%, 50%))", true},
- {"-internal-light-dark-color(rgba(0, 0, 0, 0.5), hsla(180, 75%, 50%, "
+ {"-internal-light-dark()", false},
+ {"-internal-light-dark(#feedab)", false},
+ {"-internal-light-dark(red blue)", false},
+ {"-internal-light-dark(red,,blue)", false},
+ {"-internal-light-dark(red, blue)", true},
+ {"-internal-light-dark(#000000, #ffffff)", true},
+ {"-internal-light-dark(rgb(0, 0, 0), hsl(180, 75%, 50%))", true},
+ {"-internal-light-dark(rgba(0, 0, 0, 0.5), hsla(180, 75%, 50%, "
"0.7))",
true},
};
@@ -718,11 +706,103 @@ TEST(CSSPropertyParserTest, UAInternalLightDarkColorSerialization) {
auto* ua_context = MakeGarbageCollected<CSSParserContext>(
kUASheetMode, SecureContextMode::kInsecureContext);
const CSSValue* value = CSSParser::ParseSingleValue(
- CSSPropertyID::kColor, "-internal-light-dark-color(red,#aaa)",
- ua_context);
+ CSSPropertyID::kColor, "-internal-light-dark(red,#aaa)", ua_context);
ASSERT_TRUE(value);
- EXPECT_EQ("-internal-light-dark-color(red, rgb(170, 170, 170))",
- value->CssText());
+ EXPECT_EQ("-internal-light-dark(red, rgb(170, 170, 170))", value->CssText());
+}
+
+TEST(CSSPropertyParserTest, UAInternalLightDarkBackgroundImage) {
+ auto* ua_context = MakeGarbageCollected<CSSParserContext>(
+ kUASheetMode, SecureContextMode::kInsecureContext);
+
+ const struct {
+ const char* value;
+ bool valid;
+ } tests[] = {
+ {"-internal-light-dark()", false},
+ {"-internal-light-dark(url(light.png))", false},
+ {"-internal-light-dark(url(light.png) url(dark.png))", false},
+ {"-internal-light-dark(url(light.png),,url(dark.png))", false},
+ {"-internal-light-dark(url(light.png), url(dark.png))", true},
+ {"-internal-light-dark(url(light.png), none)", true},
+ {"-internal-light-dark(none, -webkit-image-set(url(dark.png) 1x))", true},
+ {"-internal-light-dark( none , none )", true},
+ {"-internal-light-dark( url(light.png) , url(dark.png) )", true},
+ };
+
+ for (const auto& test : tests) {
+ EXPECT_EQ(!!CSSParser::ParseSingleValue(CSSPropertyID::kBackgroundImage,
+ test.value, ua_context),
+ test.valid)
+ << test.value;
+ }
+}
+
+namespace {
+
+bool ParseCSSValue(CSSPropertyID property_id,
+ const String& value,
+ const CSSParserContext* context) {
+ CSSTokenizer tokenizer(value);
+ const auto tokens = tokenizer.TokenizeToEOF();
+ const CSSParserTokenRange range(tokens);
+ HeapVector<CSSPropertyValue, 256> parsed_properties;
+ return CSSPropertyParser::ParseValue(property_id, false, range, context,
+ parsed_properties,
+ StyleRule::RuleType::kStyle);
+}
+
+} // namespace
+
+TEST(CSSPropertyParserTest, UAInternalLightDarkBackgroundShorthand) {
+ auto* ua_context = MakeGarbageCollected<CSSParserContext>(
+ kUASheetMode, SecureContextMode::kInsecureContext);
+
+ const struct {
+ const char* value;
+ bool valid;
+ } tests[] = {
+ {"-internal-light-dark()", false},
+ {"-internal-light-dark(url(light.png))", false},
+ {"-internal-light-dark(url(light.png) url(dark.png))", false},
+ {"-internal-light-dark(url(light.png),,url(dark.png))", false},
+ {"-internal-light-dark(url(light.png), url(dark.png))", true},
+ {"-internal-light-dark(url(light.png), none)", true},
+ {"-internal-light-dark(none, -webkit-image-set(url(dark.png) 1x))", true},
+ {"-internal-light-dark( none , none )", true},
+ {"-internal-light-dark( url(light.png) , url(dark.png) )", true},
+ };
+
+ for (const auto& test : tests) {
+ EXPECT_EQ(
+ !!ParseCSSValue(CSSPropertyID::kBackground, test.value, ua_context),
+ test.valid)
+ << test.value;
+ }
+}
+
+TEST(CSSPropertyParserTest, ParseRevert) {
+ auto* context = MakeGarbageCollected<CSSParserContext>(
+ kHTMLStandardMode, SecureContextMode::kInsecureContext);
+
+ String string = " revert";
+ CSSTokenizer tokenizer(string);
+ const auto tokens = tokenizer.TokenizeToEOF();
+
+ {
+ ScopedCSSRevertForTest scoped_revert(true);
+ const CSSValue* value = CSSPropertyParser::ParseSingleValue(
+ CSSPropertyID::kMarginLeft, CSSParserTokenRange(tokens), context);
+ ASSERT_TRUE(value);
+ EXPECT_TRUE(value->IsRevertValue());
+ }
+
+ {
+ ScopedCSSRevertForTest scoped_revert(false);
+ const CSSValue* value = CSSPropertyParser::ParseSingleValue(
+ CSSPropertyID::kMarginLeft, CSSParserTokenRange(tokens), context);
+ EXPECT_FALSE(value);
+ }
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/parser/css_variable_parser.cc b/chromium/third_party/blink/renderer/core/css/parser/css_variable_parser.cc
index 61a8c024183..d95059d9595 100644
--- a/chromium/third_party/blink/renderer/core/css/parser/css_variable_parser.cc
+++ b/chromium/third_party/blink/renderer/core/css/parser/css_variable_parser.cc
@@ -7,6 +7,7 @@
#include "third_party/blink/renderer/core/css/css_custom_property_declaration.h"
#include "third_party/blink/renderer/core/css/css_variable_reference_value.h"
#include "third_party/blink/renderer/core/css/parser/css_parser_token_range.h"
+#include "third_party/blink/renderer/core/css/properties/css_parsing_utils.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
namespace blink {
@@ -114,9 +115,7 @@ CSSValueID ClassifyVariableRange(CSSParserTokenRange range,
range.ConsumeWhitespace();
if (range.Peek().GetType() == kIdentToken) {
CSSValueID id = range.ConsumeIncludingWhitespace().Id();
- if (range.AtEnd() &&
- (id == CSSValueID::kInherit || id == CSSValueID::kInitial ||
- id == CSSValueID::kUnset))
+ if (range.AtEnd() && css_parsing_utils::IsCSSWideKeyword(id))
return id;
}
diff --git a/chromium/third_party/blink/renderer/core/css/properties/README.md b/chromium/third_party/blink/renderer/core/css/properties/README.md
index f7af0220ae6..d0de6e0db1e 100644
--- a/chromium/third_party/blink/renderer/core/css/properties/README.md
+++ b/chromium/third_party/blink/renderer/core/css/properties/README.md
@@ -63,14 +63,15 @@ e.g. ParseShorthand.
### Descriptors
-Descriptors define the characteristics of an at-rule. For example, @viewport is
-an at-rule, and width is a valid descriptor for @viewport. Within the context of
-@viewport, width is a shorthand comprising the min-width and max-width of the
-viewport. From this example we can see that a descriptor is not the same as a
-CSS property with the same name. Sometimes descriptors and CSS properties with
-the same name are handled together, but that should not be taken to mean that
-they are the same thing. Fixing this possible source of confusion is an open
-issue crbug.com/752745.
+Descriptors define the characteristics of an at-rule. For example, @font-face
+is an at-rule, and font-family is a valid descriptor for @font-face. Within the
+context of @font-face, font-family names a web font associated with a url src
+descriptor, but the font-family property is used to select a font among the
+available local fonts or web fonts. From this example we can see that a
+descriptor is not the same as a CSS property with the same name. Sometimes
+descriptors and CSS properties with the same name are handled together, but
+that should not be taken to mean that they are the same thing. Fixing this
+possible source of confusion is an open issue crbug.com/752745.
### Variable
diff --git a/chromium/third_party/blink/renderer/core/css/properties/computed_style_utils.cc b/chromium/third_party/blink/renderer/core/css/properties/computed_style_utils.cc
index b876e57eebd..1346dd54d89 100644
--- a/chromium/third_party/blink/renderer/core/css/properties/computed_style_utils.cc
+++ b/chromium/third_party/blink/renderer/core/css/properties/computed_style_utils.cc
@@ -1738,79 +1738,50 @@ CSSValue* ComputedStyleUtils::ValueForBorderRadiusCorner(
CSSValuePair::kDropIdenticalValues);
}
-CSSValue* ComputedStyleUtils::ValueForMatrixTransform(
- const TransformationMatrix& transform_param,
- const ComputedStyle& style) {
- // Take TransformationMatrix by reference and then copy it because VC++
- // doesn't guarantee alignment of function parameters.
- TransformationMatrix transform = transform_param;
- CSSFunctionValue* transform_value = nullptr;
- transform.Zoom(1 / style.EffectiveZoom());
- if (transform.IsAffine()) {
- transform_value =
- MakeGarbageCollected<CSSFunctionValue>(CSSValueID::kMatrix);
-
- transform_value->Append(*CSSNumericLiteralValue::Create(
- transform.A(), CSSPrimitiveValue::UnitType::kNumber));
- transform_value->Append(*CSSNumericLiteralValue::Create(
- transform.B(), CSSPrimitiveValue::UnitType::kNumber));
- transform_value->Append(*CSSNumericLiteralValue::Create(
- transform.C(), CSSPrimitiveValue::UnitType::kNumber));
- transform_value->Append(*CSSNumericLiteralValue::Create(
- transform.D(), CSSPrimitiveValue::UnitType::kNumber));
- transform_value->Append(*CSSNumericLiteralValue::Create(
- transform.E(), CSSPrimitiveValue::UnitType::kNumber));
- transform_value->Append(*CSSNumericLiteralValue::Create(
- transform.F(), CSSPrimitiveValue::UnitType::kNumber));
+CSSFunctionValue* ComputedStyleUtils::ValueForTransformationMatrix(
+ const TransformationMatrix& matrix,
+ float zoom,
+ bool force_matrix3d) {
+ if (matrix.IsAffine() && !force_matrix3d) {
+ auto* result = MakeGarbageCollected<CSSFunctionValue>(CSSValueID::kMatrix);
+ // CSS matrix values are returned in column-major order.
+ double values[6] = {matrix.A(), matrix.B(), //
+ matrix.C(), matrix.D(), //
+ // E and F are pixel lengths so unzoom
+ matrix.E() / zoom, matrix.F() / zoom};
+ for (double value : values) {
+ result->Append(*CSSNumericLiteralValue::Create(
+ value, CSSPrimitiveValue::UnitType::kNumber));
+ }
+ return result;
} else {
- transform_value =
+ CSSFunctionValue* result =
MakeGarbageCollected<CSSFunctionValue>(CSSValueID::kMatrix3d);
-
- transform_value->Append(*CSSNumericLiteralValue::Create(
- transform.M11(), CSSPrimitiveValue::UnitType::kNumber));
- transform_value->Append(*CSSNumericLiteralValue::Create(
- transform.M12(), CSSPrimitiveValue::UnitType::kNumber));
- transform_value->Append(*CSSNumericLiteralValue::Create(
- transform.M13(), CSSPrimitiveValue::UnitType::kNumber));
- transform_value->Append(*CSSNumericLiteralValue::Create(
- transform.M14(), CSSPrimitiveValue::UnitType::kNumber));
-
- transform_value->Append(*CSSNumericLiteralValue::Create(
- transform.M21(), CSSPrimitiveValue::UnitType::kNumber));
- transform_value->Append(*CSSNumericLiteralValue::Create(
- transform.M22(), CSSPrimitiveValue::UnitType::kNumber));
- transform_value->Append(*CSSNumericLiteralValue::Create(
- transform.M23(), CSSPrimitiveValue::UnitType::kNumber));
- transform_value->Append(*CSSNumericLiteralValue::Create(
- transform.M24(), CSSPrimitiveValue::UnitType::kNumber));
-
- transform_value->Append(*CSSNumericLiteralValue::Create(
- transform.M31(), CSSPrimitiveValue::UnitType::kNumber));
- transform_value->Append(*CSSNumericLiteralValue::Create(
- transform.M32(), CSSPrimitiveValue::UnitType::kNumber));
- transform_value->Append(*CSSNumericLiteralValue::Create(
- transform.M33(), CSSPrimitiveValue::UnitType::kNumber));
- transform_value->Append(*CSSNumericLiteralValue::Create(
- transform.M34(), CSSPrimitiveValue::UnitType::kNumber));
-
- transform_value->Append(*CSSNumericLiteralValue::Create(
- transform.M41(), CSSPrimitiveValue::UnitType::kNumber));
- transform_value->Append(*CSSNumericLiteralValue::Create(
- transform.M42(), CSSPrimitiveValue::UnitType::kNumber));
- transform_value->Append(*CSSNumericLiteralValue::Create(
- transform.M43(), CSSPrimitiveValue::UnitType::kNumber));
- transform_value->Append(*CSSNumericLiteralValue::Create(
- transform.M44(), CSSPrimitiveValue::UnitType::kNumber));
- }
-
- return transform_value;
+ // CSS matrix values are returned in column-major order.
+ double values[16] = {
+ // Note that the transformation matrix operates on (Length^3 * R).
+ // Each column contains 3 scalars followed by a reciprocal length
+ // (with a value in 1/px) which must be unzoomed accordingly.
+ matrix.M11(), matrix.M12(), matrix.M13(), matrix.M14() * zoom,
+ matrix.M21(), matrix.M22(), matrix.M23(), matrix.M24() * zoom,
+ matrix.M31(), matrix.M32(), matrix.M33(), matrix.M34() * zoom,
+ // Last column has 3 pixel lengths and a scalar
+ matrix.M41() / zoom, matrix.M42() / zoom, matrix.M43() / zoom,
+ matrix.M44()};
+ for (double value : values) {
+ result->Append(*CSSNumericLiteralValue::Create(
+ value, CSSPrimitiveValue::UnitType::kNumber));
+ }
+ return result;
+ }
}
// We collapse functions like translateX into translate, since we will reify
// them as a translate anyway.
-CSSValue* ComputedStyleUtils::ValueForTransformOperation(
+CSSFunctionValue* ComputedStyleUtils::ValueForTransformOperation(
const TransformOperation& operation,
- float zoom) {
+ float zoom,
+ FloatSize box_size) {
switch (operation.GetType()) {
case TransformOperation::kScaleX:
case TransformOperation::kScaleY:
@@ -1874,6 +1845,14 @@ CSSValue* ComputedStyleUtils::ValueForTransformOperation(
rotate.Angle(), CSSPrimitiveValue::UnitType::kDegrees));
return result;
}
+ case TransformOperation::kRotateAroundOrigin: {
+ // TODO(https://github.com/w3c/csswg-drafts/issues/5011):
+ // Update this once there is consensus.
+ TransformationMatrix matrix;
+ operation.Apply(matrix, FloatSize(0, 0));
+ return ValueForTransformationMatrix(matrix, zoom,
+ /*force_matrix3d=*/false);
+ }
case TransformOperation::kSkewX: {
const auto& skew = To<SkewTransformOperation>(operation);
auto* result = MakeGarbageCollected<CSSFunctionValue>(CSSValueID::kSkewX);
@@ -1908,49 +1887,41 @@ CSSValue* ComputedStyleUtils::ValueForTransformOperation(
}
case TransformOperation::kMatrix: {
const auto& matrix = To<MatrixTransformOperation>(operation).Matrix();
- auto* result =
- MakeGarbageCollected<CSSFunctionValue>(CSSValueID::kMatrix);
- // CSS matrix values are returned in column-major order.
- double values[6] = {matrix.A(), matrix.B(), //
- matrix.C(), matrix.D(), //
- // E and F are pixel lengths so unzoom
- matrix.E() / zoom, matrix.F() / zoom};
- for (double value : values) {
- result->Append(*CSSNumericLiteralValue::Create(
- value, CSSPrimitiveValue::UnitType::kNumber));
- }
- return result;
+ return ValueForTransformationMatrix(matrix, zoom,
+ /*force_matrix3d=*/false);
}
case TransformOperation::kMatrix3D: {
const auto& matrix = To<Matrix3DTransformOperation>(operation).Matrix();
- CSSFunctionValue* result =
- MakeGarbageCollected<CSSFunctionValue>(CSSValueID::kMatrix3d);
- // CSS matrix values are returned in column-major order.
- double values[16] = {
- // Note that the transformation matrix operates on (Length^3 * R).
- // Each column contains 3 scalars followed by a reciprocal length
- // (with a value in 1/px) which must be unzoomed accordingly.
- matrix.M11(), matrix.M12(), matrix.M13(), matrix.M14() * zoom,
- matrix.M21(), matrix.M22(), matrix.M23(), matrix.M24() * zoom,
- matrix.M31(), matrix.M32(), matrix.M33(), matrix.M34() * zoom,
- // Last column has 3 pixel lengths and a scalar
- matrix.M41() / zoom, matrix.M42() / zoom, matrix.M43() / zoom,
- matrix.M44()};
- for (double value : values) {
- result->Append(*CSSNumericLiteralValue::Create(
- value, CSSPrimitiveValue::UnitType::kNumber));
- }
- return result;
+ // Force matrix3d serialization
+ return ValueForTransformationMatrix(matrix, zoom,
+ /*force_matrix3d=*/true);
}
case TransformOperation::kInterpolated:
- // TODO(816803): The computed value in this case is not fully spec'd
- // See https://github.com/w3c/css-houdini-drafts/issues/425
- return CSSIdentifierValue::Create(CSSValueID::kNone);
- default:
- // The remaining operations are unsupported.
- NOTREACHED();
- return CSSIdentifierValue::Create(CSSValueID::kNone);
+ // TODO(https://github.com/w3c/csswg-drafts/issues/2854):
+ // Deferred interpolations are currently unreperesentable in CSS.
+ // This currently converts the operation to a matrix, using box_size if
+ // provided, 0x0 if not (returning all but the relative translate
+ // portion of the transform). Update this once the spec is updated.
+ TransformationMatrix matrix;
+ operation.Apply(matrix, box_size);
+ return ValueForTransformationMatrix(matrix, zoom,
+ /*force_matrix3d=*/false);
+ }
+}
+
+CSSValue* ComputedStyleUtils::ValueForTransformList(
+ const TransformOperations& transform_list,
+ float zoom,
+ FloatSize box_size) {
+ if (!transform_list.Operations().size())
+ return CSSIdentifierValue::Create(CSSValueID::kNone);
+
+ CSSValueList* components = CSSValueList::CreateSpaceSeparated();
+ for (const auto& operation : transform_list.Operations()) {
+ CSSValue* op_value = ValueForTransformOperation(*operation, zoom, box_size);
+ components->Append(*op_value);
}
+ return components;
}
FloatRect ComputedStyleUtils::ReferenceBoxForTransform(
@@ -1967,7 +1938,18 @@ FloatRect ComputedStyleUtils::ReferenceBoxForTransform(
return FloatRect();
}
-CSSValue* ComputedStyleUtils::ComputedTransform(
+CSSValue* ComputedStyleUtils::ComputedTransformList(
+ const ComputedStyle& style,
+ const LayoutObject* layout_object) {
+ FloatSize box_size(0, 0);
+ if (layout_object)
+ box_size = ReferenceBoxForTransform(*layout_object).Size();
+
+ return ValueForTransformList(style.Transform(), style.EffectiveZoom(),
+ box_size);
+}
+
+CSSValue* ComputedStyleUtils::ResolvedTransform(
const LayoutObject* layout_object,
const ComputedStyle& style) {
if (!layout_object || !style.HasTransform())
@@ -1984,7 +1966,8 @@ CSSValue* ComputedStyleUtils::ComputedTransform(
// FIXME: Need to print out individual functions
// (https://bugs.webkit.org/show_bug.cgi?id=23924)
CSSValueList* list = CSSValueList::CreateSpaceSeparated();
- list->Append(*ValueForMatrixTransform(transform, style));
+ list->Append(*ValueForTransformationMatrix(transform, style.EffectiveZoom(),
+ /*force_matrix3d=*/false));
return list;
}
@@ -2753,4 +2736,27 @@ ComputedStyleUtils::CrossThreadStyleValueFromCSSStyleValue(
}
}
+const CSSValue* ComputedStyleUtils::ComputedPropertyValue(
+ const CSSProperty& property,
+ const ComputedStyle& style,
+ const LayoutObject* layout_object) {
+ switch (property.PropertyID()) {
+ // Computed value is usually relative so that multiple fonts in child
+ // elements work properly, but resolved value is always a pixel length.
+ case CSSPropertyID::kLineHeight:
+ return ComputedStyleUtils::ComputedValueForLineHeight(style);
+
+ // Returns a transform list instead of converting to a (resolved) matrix.
+ case CSSPropertyID::kTransform:
+ return ComputedStyleUtils::ComputedTransformList(style, layout_object);
+
+ // For all other properties, the resolved value is either always the same
+ // as the computed value (most properties), or the same as the computed
+ // value when there is no layout box ('width' and friends).
+ default:
+ return property.CSSValueFromComputedStyle(
+ style, /*layout_object=*/nullptr, false);
+ }
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/computed_style_utils.h b/chromium/third_party/blink/renderer/core/css/properties/computed_style_utils.h
index 51fcb47c59f..790aaf35b3b 100644
--- a/chromium/third_party/blink/renderer/core/css/properties/computed_style_utils.h
+++ b/chromium/third_party/blink/renderer/core/css/properties/computed_style_utils.h
@@ -7,6 +7,7 @@
#include "cc/input/scroll_snap_data.h"
#include "third_party/blink/renderer/core/css/css_border_image_slice_value.h"
+#include "third_party/blink/renderer/core/css/css_function_value.h"
#include "third_party/blink/renderer/core/css/css_identifier_value.h"
#include "third_party/blink/renderer/core/css/css_value_list.h"
#include "third_party/blink/renderer/core/css/css_value_pair.h"
@@ -24,7 +25,7 @@ class ComputedStyle;
class StyleColor;
class StylePropertyShorthand;
-class ComputedStyleUtils {
+class CORE_EXPORT ComputedStyleUtils {
STATIC_ONLY(ComputedStyleUtils);
public:
@@ -146,14 +147,35 @@ class ComputedStyleUtils {
kDontUsePixelSnappedBox,
kUsePixelSnappedBox,
};
- static CSSValue* ValueForMatrixTransform(const TransformationMatrix&,
- const ComputedStyle&);
- static CSSValue* ValueForTransformOperation(const TransformOperation&,
- float zoom);
+
+ // Serializes a TransformationMatrix into a matrix() or matrix3d() transform
+ // function value. If force_matrix3d is true, it will always give a matrix3d
+ // value (for serializing a matrix3d in a transform list), otherwise it
+ // will give a matrix() where possible (for serializing matrix in transform
+ // lists or resolved transformation matrices).
+ static CSSFunctionValue* ValueForTransformationMatrix(
+ const TransformationMatrix&,
+ float zoom,
+ bool force_matrix3d);
+ // Values unreperesentable in CSS will be converted to an equivalent matrix()
+ // value. The box_size parameter is used for deferred, layout-dependent
+ // interpolations and is not needed in the absence of animations.
+ static CSSFunctionValue* ValueForTransformOperation(
+ const TransformOperation&,
+ float zoom,
+ FloatSize box_size = FloatSize(0, 0));
+ // Serialize a transform list.
+ static CSSValue* ValueForTransformList(const TransformOperations&,
+ float zoom,
+ FloatSize box_size = FloatSize(0, 0));
static FloatRect ReferenceBoxForTransform(
const LayoutObject&,
UsePixelSnappedBox = kUsePixelSnappedBox);
- static CSSValue* ComputedTransform(const LayoutObject*, const ComputedStyle&);
+ // The LayoutObject parameter is only used for converting unreperesentable
+ // relative transforms into matrix() values, with a default box size of 0x0.
+ static CSSValue* ComputedTransformList(const ComputedStyle&,
+ const LayoutObject* = nullptr);
+ static CSSValue* ResolvedTransform(const LayoutObject*, const ComputedStyle&);
static CSSValue* CreateTransitionPropertyValue(
const CSSTransitionData::TransitionProperty&);
static CSSValue* ValueForTransitionProperty(const CSSTransitionData*);
@@ -219,6 +241,23 @@ class ComputedStyleUtils {
static CSSValue* ValueForGapLength(const GapLength&, const ComputedStyle&);
static std::unique_ptr<CrossThreadStyleValue>
CrossThreadStyleValueFromCSSStyleValue(CSSStyleValue* style_value);
+
+ // Returns the computed CSSValue of the given property from the style,
+ // which may different than the resolved value returned by
+ // CSSValueFromComputedStyle().
+ // see https://drafts.csswg.org/cssom/#resolved-values
+ //
+ // In most, but not all, cases, the resolved value involves layout-dependent
+ // calculations, and the computed value is used as a fallback when there is
+ // no layout object (display: none, etc). In those cases, this calls
+ // CSSValueFromComputedStyle(layout_object=nullptr), with the exceptions
+ // (transform and line-height currently) having their own logic here.
+ //
+ // The LayoutObject parameter is only used for converting unreperesentable
+ // relative transforms into matrix() values, with a default box size of 0x0.
+ static const CSSValue* ComputedPropertyValue(const CSSProperty&,
+ const ComputedStyle&,
+ const LayoutObject* = nullptr);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/computed_style_utils_test.cc b/chromium/third_party/blink/renderer/core/css/properties/computed_style_utils_test.cc
new file mode 100644
index 00000000000..ff1582a6cbb
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/css/properties/computed_style_utils_test.cc
@@ -0,0 +1,44 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/css/properties/computed_style_utils.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/googletest/src/googletest/include/gtest/gtest.h"
+
+namespace blink {
+
+TEST(ComputedStyleUtilsTest, MatrixForce3D) {
+ TransformationMatrix identity;
+ EXPECT_EQ(ComputedStyleUtils::ValueForTransformationMatrix(identity, 1, false)
+ ->CssText(),
+ "matrix(1, 0, 0, 1, 0, 0)");
+ EXPECT_EQ(ComputedStyleUtils::ValueForTransformationMatrix(identity, 1, true)
+ ->CssText(),
+ "matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1)");
+}
+
+TEST(ComputedStyleUtilsTest, MatrixZoom2D) {
+ TransformationMatrix matrix(1, 2, 3, 4, 5, 6);
+ EXPECT_EQ(ComputedStyleUtils::ValueForTransformationMatrix(matrix, 1, false)
+ ->CssText(),
+ "matrix(1, 2, 3, 4, 5, 6)");
+ matrix.Zoom(2);
+ EXPECT_EQ(ComputedStyleUtils::ValueForTransformationMatrix(matrix, 2, false)
+ ->CssText(),
+ "matrix(1, 2, 3, 4, 5, 6)");
+}
+
+TEST(ComputedStyleUtilsTest, MatrixZoom3D) {
+ TransformationMatrix matrix(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16);
+ EXPECT_EQ(ComputedStyleUtils::ValueForTransformationMatrix(matrix, 1, false)
+ ->CssText(),
+ "matrix3d(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16)");
+ matrix.Zoom(2);
+ EXPECT_EQ(ComputedStyleUtils::ValueForTransformationMatrix(matrix, 2, false)
+ ->CssText(),
+ "matrix3d(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16)");
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/css_bitset.h b/chromium/third_party/blink/renderer/core/css/properties/css_bitset.h
new file mode 100644
index 00000000000..998864c8e6b
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/css/properties/css_bitset.h
@@ -0,0 +1,165 @@
+// 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_CORE_CSS_PROPERTIES_CSS_BITSET_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_PROPERTIES_CSS_BITSET_H_
+
+#include <algorithm>
+#include <cstring>
+#include <initializer_list>
+#include "third_party/blink/renderer/core/css/css_property_names.h"
+
+namespace blink {
+
+// A bitset designed for CSSPropertyIDs.
+//
+// It's different from std::bitset, in that it provides optimized traversal
+// for situations where only a few bits are set (which is the common case for
+// e.g. CSS declarations which apply to an element).
+//
+// The bitset can store a configurable amount of bits for testing purposes,
+// (though not more than numCSSProperties).
+template <size_t kBits>
+class CORE_EXPORT CSSBitsetBase {
+ public:
+ static_assert(
+ kBits <= numCSSProperties,
+ "Bit count must not exceed numCSSProperties, as each bit position must "
+ "be representable as a CSSPropertyID");
+
+ static const size_t kChunks = (kBits + 63) / 64;
+
+ CSSBitsetBase() : chunks_() {}
+ CSSBitsetBase(const CSSBitsetBase<kBits>& o) { *this = o; }
+ CSSBitsetBase(std::initializer_list<CSSPropertyID> list) : chunks_() {
+ for (CSSPropertyID id : list)
+ Set(id);
+ }
+
+ void operator=(const CSSBitsetBase& o) {
+ std::memcpy(chunks_, o.chunks_, sizeof(chunks_));
+ }
+
+ bool operator==(const CSSBitsetBase& o) const {
+ return std::memcmp(chunks_, o.chunks_, sizeof(chunks_)) == 0;
+ }
+ bool operator!=(const CSSBitsetBase& o) const { return !(*this == o); }
+
+ inline void Set(CSSPropertyID id) {
+ size_t bit = static_cast<size_t>(id);
+ DCHECK_LT(bit, kBits);
+ chunks_[bit / 64] |= (1ull << (bit % 64));
+ }
+
+ inline void Or(CSSPropertyID id, bool v) {
+ size_t bit = static_cast<size_t>(id);
+ DCHECK_LT(bit, kBits);
+ chunks_[bit / 64] |= (static_cast<uint64_t>(v) << (bit % 64));
+ }
+
+ inline bool Has(CSSPropertyID id) const {
+ size_t bit = static_cast<size_t>(id);
+ DCHECK_LT(bit, kBits);
+ return chunks_[bit / 64] & (1ull << (bit % 64));
+ }
+
+ inline bool HasAny() const {
+ for (uint64_t chunk : chunks_) {
+ if (chunk)
+ return true;
+ }
+ return false;
+ }
+
+ inline void Reset() { std::memset(chunks_, 0, sizeof(chunks_)); }
+
+ // Yields the CSSPropertyIDs which are set.
+ class Iterator {
+ public:
+ Iterator(const uint64_t* chunks, size_t index)
+ : chunks_(chunks), index_(index), chunk_(ChunkAt(index)) {}
+
+ inline void operator++() {
+ do {
+ ++index_;
+ chunk_ = chunk_ >> 1ull;
+ DCHECK_LE(index_, kBits);
+
+ if (index_ >= kBits)
+ return;
+ if (!chunk_) {
+ // If the chunk is empty, we can fast-forward to the next chunk.
+ size_t next_chunk_index = (index_ - 1) / 64 + 1;
+ index_ = std::min(next_chunk_index * 64, kBits);
+ chunk_ = ChunkAt(index_);
+ }
+ } while (!(chunk_ & 1));
+ }
+
+ inline CSSPropertyID operator*() const {
+ DCHECK_LT(index_, static_cast<size_t>(numCSSProperties));
+ return static_cast<CSSPropertyID>(index_);
+ }
+
+ inline bool operator==(const Iterator& o) const {
+ return index_ == o.index_;
+ }
+ inline bool operator!=(const Iterator& o) const {
+ return index_ != o.index_;
+ }
+
+ private:
+ // For a given index, return the corresponding chunk, down-shifted
+ // such that the given index is the LSB of the chunk.
+ //
+ // In other words, (ChunkAt(index) & 1) is a valid way of checking whether
+ // the bit at 'index' is set.
+ //
+ // If the given index is out of bounds, we don't really have a chunk to
+ // return. This function returns 1, solely to automatically fail the
+ // do-while condition in operator++. (It avoids having special handling of
+ // index > kBits there).
+ uint64_t ChunkAt(size_t index) const {
+ return index < kBits ? chunks_[index / 64] >> (index % 64) : 1ull;
+ }
+
+ const uint64_t* chunks_;
+ // The current bit index this Iterator is pointing to. Note that this is
+ // the "global" index, i.e. it has the range [0, kBits]. (It is not a local
+ // index with range [0, 64]).
+ //
+ // Never exceeds kBits.
+ size_t index_ = 0;
+ // The iterator works by "pre-fetching" the current chunk (corresponding
+ // (to the current index), and down-shifting by one for every iteration.
+ // This allows the iterator to skip the remainder of the chunk when we
+ // shift away the last bit.
+ uint64_t chunk_ = 0;
+ };
+
+ Iterator begin() const { return Iterator(chunks_, FirstIndex()); }
+ Iterator end() const { return Iterator(chunks_, kBits); }
+
+ private:
+ // Find the first index (i.e. first set bit). If no bits are set, returns
+ // kBits.
+ size_t FirstIndex() const {
+ size_t index = 0;
+ // Skip all empty chunks.
+ while (index < kBits && !chunks_[index / 64])
+ index += 64;
+ // Within the non-empty chunk, iterate until we find the set bit.
+ while (index < kBits && !(chunks_[index / 64] & (1ull << (index % 64))))
+ ++index;
+ return std::min(index, kBits);
+ }
+
+ uint64_t chunks_[kChunks];
+};
+
+using CSSBitset = CSSBitsetBase<numCSSProperties>;
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_CSS_PROPERTIES_CSS_BITSET_H_
diff --git a/chromium/third_party/blink/renderer/core/css/properties/css_bitset_test.cc b/chromium/third_party/blink/renderer/core/css/properties/css_bitset_test.cc
new file mode 100644
index 00000000000..020be2fafad
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/css/properties/css_bitset_test.cc
@@ -0,0 +1,311 @@
+// 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/core/css/properties/css_bitset.h"
+#include <bitset>
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace blink {
+
+namespace {
+
+template <size_t kBits>
+std::bitset<kBits> ToStdBitsetUsingHas(const CSSBitsetBase<kBits>& bitset) {
+ std::bitset<kBits> ret;
+ for (size_t i = 0; i < kBits; ++i) {
+ if (bitset.Has(static_cast<CSSPropertyID>(i)))
+ ret.set(i);
+ }
+ return ret;
+}
+
+template <size_t kBits>
+std::bitset<kBits> ToStdBitsetUsingIterator(
+ const CSSBitsetBase<kBits>& bitset) {
+ std::bitset<kBits> ret;
+ for (CSSPropertyID id : bitset) {
+ size_t bit = static_cast<size_t>(id);
+ DCHECK(!ret.test(bit));
+ ret.set(bit);
+ }
+ return ret;
+}
+
+// Creates a CSSBitsetBase with kBits capacity, sets the specified bits via
+// CSSBitsetBase::Set, and then verifies that the correct bits are observed
+// via both CSSBitsetBase::Has, and CSSBitsetBase::begin()/end().
+template <size_t kBits>
+void AssertBitset(const size_t* begin, const size_t* end) {
+ std::bitset<kBits> expected;
+
+ CSSBitsetBase<kBits> actual;
+ EXPECT_FALSE(actual.HasAny());
+
+ for (const size_t* b = begin; b != end; b++) {
+ actual.Set(static_cast<CSSPropertyID>(*b));
+ expected.set(*b);
+ }
+
+ EXPECT_EQ(expected, ToStdBitsetUsingHas(actual));
+ EXPECT_EQ(expected, ToStdBitsetUsingIterator(actual));
+}
+
+template <size_t kBits>
+void AssertBitset(std::initializer_list<size_t> bits) {
+ AssertBitset<kBits>(bits.begin(), bits.end());
+}
+
+} // namespace
+
+TEST(CSSBitsetTest, BaseBitCount0) {
+ static_assert(CSSBitsetBase<0>::kChunks == 0, "Correct chunk count");
+ AssertBitset<0>({});
+}
+
+TEST(CSSBitsetTest, BaseBitCount1) {
+ static_assert(CSSBitsetBase<1>::kChunks == 1u, "Correct chunk count");
+ AssertBitset<1>({});
+ AssertBitset<1>({0});
+}
+
+TEST(CSSBitsetTest, BaseBitCount63) {
+ static_assert(CSSBitsetBase<63>::kChunks == 1u, "Correct chunk count");
+ AssertBitset<63>({});
+ AssertBitset<63>({0});
+ AssertBitset<63>({1});
+ AssertBitset<63>({13});
+ AssertBitset<63>({62});
+
+ AssertBitset<63>({0, 1});
+ AssertBitset<63>({0, 62});
+ AssertBitset<63>({61, 62});
+ AssertBitset<63>({0, 1, 13, 61, 62});
+}
+
+TEST(CSSBitsetTest, BaseBitCount64) {
+ static_assert(CSSBitsetBase<64>::kChunks == 1u, "Correct chunk count");
+ AssertBitset<64>({});
+ AssertBitset<64>({0});
+ AssertBitset<64>({1});
+ AssertBitset<64>({13});
+ AssertBitset<64>({63});
+
+ AssertBitset<64>({0, 1});
+ AssertBitset<64>({0, 63});
+ AssertBitset<64>({62, 63});
+ AssertBitset<64>({0, 1, 13, 62, 63});
+}
+
+TEST(CSSBitsetTest, BaseBitCount65) {
+ static_assert(CSSBitsetBase<65>::kChunks == 2u, "Correct chunk count");
+ AssertBitset<65>({});
+ AssertBitset<65>({0});
+ AssertBitset<65>({1});
+ AssertBitset<65>({13});
+ AssertBitset<65>({63});
+ AssertBitset<65>({64});
+
+ AssertBitset<65>({0, 1});
+ AssertBitset<65>({0, 64});
+ AssertBitset<65>({63, 64});
+ AssertBitset<65>({0, 1, 13, 63, 64});
+}
+
+TEST(CSSBitsetTest, BaseBitCount127) {
+ static_assert(CSSBitsetBase<127>::kChunks == 2u, "Correct chunk count");
+ AssertBitset<127>({});
+ AssertBitset<127>({0});
+ AssertBitset<127>({1});
+ AssertBitset<127>({13});
+ AssertBitset<127>({125});
+ AssertBitset<127>({126});
+
+ AssertBitset<127>({0, 1});
+ AssertBitset<127>({0, 126});
+ AssertBitset<127>({125, 126});
+ AssertBitset<127>({0, 1, 13, 125, 126});
+}
+
+TEST(CSSBitsetTest, BaseBitCount128) {
+ static_assert(CSSBitsetBase<128>::kChunks == 2u, "Correct chunk count");
+ AssertBitset<128>({});
+ AssertBitset<128>({0});
+ AssertBitset<128>({1});
+ AssertBitset<128>({13});
+ AssertBitset<128>({126});
+ AssertBitset<128>({127});
+
+ AssertBitset<128>({0, 1});
+ AssertBitset<128>({0, 127});
+ AssertBitset<128>({126, 127});
+ AssertBitset<128>({0, 1, 13, 126, 127});
+ AssertBitset<128>({0, 1, 13, 63, 64, 65, 126, 127});
+}
+
+TEST(CSSBitsetTest, BaseBitCount129) {
+ static_assert(CSSBitsetBase<129>::kChunks == 3u, "Correct chunk count");
+ AssertBitset<129>({});
+ AssertBitset<129>({0});
+ AssertBitset<129>({1});
+ AssertBitset<129>({13});
+ AssertBitset<129>({127});
+ AssertBitset<129>({128});
+
+ AssertBitset<129>({0, 1});
+ AssertBitset<129>({0, 128});
+ AssertBitset<129>({127, 128});
+ AssertBitset<129>({0, 1, 13, 127, 128});
+ AssertBitset<129>({0, 1, 13, 63, 64, 65, 127, 128});
+}
+
+TEST(CSSBitsetTest, AllBits) {
+ std::vector<size_t> all_bits;
+ for (size_t i = 0; i < numCSSProperties; ++i)
+ all_bits.push_back(i);
+
+ AssertBitset<1>(all_bits.data(), all_bits.data() + 1);
+ AssertBitset<2>(all_bits.data(), all_bits.data() + 2);
+ AssertBitset<63>(all_bits.data(), all_bits.data() + 63);
+ AssertBitset<64>(all_bits.data(), all_bits.data() + 64);
+ AssertBitset<65>(all_bits.data(), all_bits.data() + 65);
+ AssertBitset<127>(all_bits.data(), all_bits.data() + 127);
+ AssertBitset<128>(all_bits.data(), all_bits.data() + 128);
+ AssertBitset<129>(all_bits.data(), all_bits.data() + 129);
+}
+
+TEST(CSSBitsetTest, NoBits) {
+ size_t i = 0;
+ AssertBitset<1>(&i, &i);
+ AssertBitset<2>(&i, &i);
+ AssertBitset<63>(&i, &i);
+ AssertBitset<64>(&i, &i);
+ AssertBitset<65>(&i, &i);
+ AssertBitset<127>(&i, &i);
+ AssertBitset<128>(&i, &i);
+ AssertBitset<129>(&i, &i);
+}
+
+TEST(CSSBitsetTest, SingleBit) {
+ for (size_t i = 0; i < 1; ++i)
+ AssertBitset<1>(&i, &i + 1);
+
+ for (size_t i = 0; i < 2; ++i)
+ AssertBitset<2>(&i, &i + 1);
+
+ for (size_t i = 0; i < 63; ++i)
+ AssertBitset<63>(&i, &i + 1);
+
+ for (size_t i = 0; i < 64; ++i)
+ AssertBitset<64>(&i, &i + 1);
+
+ for (size_t i = 0; i < 65; ++i)
+ AssertBitset<65>(&i, &i + 1);
+
+ for (size_t i = 0; i < 127; ++i)
+ AssertBitset<127>(&i, &i + 1);
+
+ for (size_t i = 0; i < 128; ++i)
+ AssertBitset<128>(&i, &i + 1);
+
+ for (size_t i = 0; i < 129; ++i)
+ AssertBitset<129>(&i, &i + 1);
+}
+
+TEST(CSSBitsetTest, Default) {
+ CSSBitset bitset;
+ for (auto id : CSSPropertyIDList())
+ EXPECT_FALSE(bitset.Has(id));
+ EXPECT_FALSE(bitset.HasAny());
+}
+
+TEST(CSSBitsetTest, SetAndHas) {
+ CSSBitset bitset;
+ EXPECT_FALSE(bitset.Has(CSSPropertyID::kVariable));
+ EXPECT_FALSE(bitset.Has(CSSPropertyID::kWidth));
+ EXPECT_FALSE(bitset.Has(CSSPropertyID::kHeight));
+ bitset.Set(CSSPropertyID::kVariable);
+ bitset.Set(CSSPropertyID::kWidth);
+ bitset.Set(CSSPropertyID::kHeight);
+ EXPECT_TRUE(bitset.Has(CSSPropertyID::kVariable));
+ EXPECT_TRUE(bitset.Has(CSSPropertyID::kWidth));
+ EXPECT_TRUE(bitset.Has(CSSPropertyID::kHeight));
+}
+
+TEST(CSSBitsetTest, Or) {
+ CSSBitset bitset;
+ EXPECT_FALSE(bitset.Has(CSSPropertyID::kWidth));
+ bitset.Or(CSSPropertyID::kWidth, false);
+ EXPECT_FALSE(bitset.Has(CSSPropertyID::kWidth));
+ bitset.Or(CSSPropertyID::kWidth, true);
+ EXPECT_TRUE(bitset.Has(CSSPropertyID::kWidth));
+}
+
+TEST(CSSBitsetTest, HasAny) {
+ CSSBitset bitset;
+ EXPECT_FALSE(bitset.HasAny());
+ bitset.Set(CSSPropertyID::kVariable);
+ EXPECT_TRUE(bitset.HasAny());
+}
+
+TEST(CSSBitsetTest, Reset) {
+ CSSBitset bitset;
+ EXPECT_FALSE(bitset.HasAny());
+ bitset.Set(CSSPropertyID::kHeight);
+ EXPECT_TRUE(bitset.HasAny());
+ EXPECT_TRUE(bitset.Has(CSSPropertyID::kHeight));
+ bitset.Reset();
+ EXPECT_FALSE(bitset.HasAny());
+ EXPECT_FALSE(bitset.Has(CSSPropertyID::kHeight));
+}
+
+TEST(CSSBitsetTest, Iterator) {
+ CSSBitset actual;
+ actual.Set(CSSPropertyID::kHeight);
+ actual.Set(CSSPropertyID::kWidth);
+ actual.Set(CSSPropertyID::kVariable);
+
+ std::bitset<numCSSProperties> expected;
+ expected.set(static_cast<size_t>(CSSPropertyID::kHeight));
+ expected.set(static_cast<size_t>(CSSPropertyID::kWidth));
+ expected.set(static_cast<size_t>(CSSPropertyID::kVariable));
+
+ EXPECT_EQ(expected, ToStdBitsetUsingIterator(actual));
+}
+
+TEST(CSSBitsetTest, Equals) {
+ CSSBitset b1;
+ CSSBitset b2;
+ EXPECT_EQ(b1, b2);
+
+ for (CSSPropertyID id : CSSPropertyIDList()) {
+ b1.Set(id);
+ EXPECT_NE(b1, b2);
+
+ b2.Set(id);
+ EXPECT_EQ(b1, b2);
+ }
+}
+
+TEST(CSSBitsetTest, Copy) {
+ EXPECT_EQ(CSSBitset(), CSSBitset());
+
+ CSSBitset b1;
+ for (CSSPropertyID id : CSSPropertyIDList()) {
+ CSSBitset b2;
+ b1.Set(id);
+ b2.Set(id);
+ EXPECT_EQ(b1, CSSBitset(b1));
+ EXPECT_EQ(b2, CSSBitset(b2));
+ }
+}
+
+TEST(CSSBitsetTest, InitializerList) {
+ for (CSSPropertyID id : CSSPropertyIDList()) {
+ CSSBitset bitset({CSSPropertyID::kColor, id});
+ EXPECT_TRUE(bitset.Has(CSSPropertyID::kColor));
+ EXPECT_TRUE(bitset.Has(id));
+ }
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/css_parsing_utils.cc b/chromium/third_party/blink/renderer/core/css/properties/css_parsing_utils.cc
index 4ede24db6b5..c2e3c3a4d82 100644
--- a/chromium/third_party/blink/renderer/core/css/properties/css_parsing_utils.cc
+++ b/chromium/third_party/blink/renderer/core/css/properties/css_parsing_utils.cc
@@ -458,6 +458,13 @@ bool IsContentPositionOrLeftOrRightKeyword(CSSValueID id) {
return IsContentPositionKeyword(id) || IsLeftOrRightKeyword(id);
}
+bool IsCSSWideKeyword(CSSValueID id) {
+ return id == CSSValueID::kInherit || id == CSSValueID::kInitial ||
+ id == CSSValueID::kUnset ||
+ (RuntimeEnabledFeatures::CSSRevertEnabled() &&
+ (id == CSSValueID::kRevert));
+}
+
CSSValue* ConsumeScrollOffset(CSSParserTokenRange& range,
const CSSParserContext& context) {
range.ConsumeWhitespace();
diff --git a/chromium/third_party/blink/renderer/core/css/properties/css_parsing_utils.h b/chromium/third_party/blink/renderer/core/css/properties/css_parsing_utils.h
index 1ffeb8471f0..6cf2745204c 100644
--- a/chromium/third_party/blink/renderer/core/css/properties/css_parsing_utils.h
+++ b/chromium/third_party/blink/renderer/core/css/properties/css_parsing_utils.h
@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_PROPERTIES_CSS_PARSING_UTILS_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_PROPERTIES_CSS_PARSING_UTILS_H_
+#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/css/css_numeric_literal_value.h"
#include "third_party/blink/renderer/core/css/parser/css_parser_mode.h"
#include "third_party/blink/renderer/core/css/parser/css_parser_token_range.h"
@@ -46,6 +47,7 @@ bool IsSelfPositionKeyword(CSSValueID);
bool IsSelfPositionOrLeftOrRightKeyword(CSSValueID);
bool IsContentPositionKeyword(CSSValueID);
bool IsContentPositionOrLeftOrRightKeyword(CSSValueID);
+CORE_EXPORT bool IsCSSWideKeyword(CSSValueID);
CSSValue* ConsumeScrollOffset(CSSParserTokenRange&, const CSSParserContext&);
CSSValue* ConsumeSelfPositionOverflowPosition(CSSParserTokenRange&,
diff --git a/chromium/third_party/blink/renderer/core/css/properties/css_parsing_utils_test.cc b/chromium/third_party/blink/renderer/core/css/properties/css_parsing_utils_test.cc
index 8ac05ca0a7d..3e768f51ca7 100644
--- a/chromium/third_party/blink/renderer/core/css/properties/css_parsing_utils_test.cc
+++ b/chromium/third_party/blink/renderer/core/css/properties/css_parsing_utils_test.cc
@@ -7,6 +7,7 @@
#include "third_party/blink/renderer/core/html/html_html_element.h"
#include "third_party/blink/renderer/core/testing/dummy_page_holder.h"
#include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
+#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
namespace blink {
@@ -21,4 +22,16 @@ TEST(CSSParsingUtilsTest, BasicShapeUseCount) {
EXPECT_TRUE(document.IsUseCounted(feature));
}
+TEST(CSSParsingUtilsTest, Revert) {
+ {
+ ScopedCSSRevertForTest scoped_revert(true);
+ EXPECT_TRUE(css_parsing_utils::IsCSSWideKeyword(CSSValueID::kRevert));
+ }
+
+ {
+ ScopedCSSRevertForTest scoped_revert(false);
+ EXPECT_FALSE(css_parsing_utils::IsCSSWideKeyword(CSSValueID::kRevert));
+ }
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/css_property.h b/chromium/third_party/blink/renderer/core/css/properties/css_property.h
index 0ecc8b561ea..41d2da7d8ab 100644
--- a/chromium/third_party/blink/renderer/core/css/properties/css_property.h
+++ b/chromium/third_party/blink/renderer/core/css/properties/css_property.h
@@ -25,7 +25,7 @@ class SVGComputedStyle;
class CORE_EXPORT CSSProperty : public CSSUnresolvedProperty {
public:
- using Flags = uint16_t;
+ using Flags = uint32_t;
static const CSSProperty& Get(CSSPropertyID);
@@ -58,6 +58,11 @@ class CORE_EXPORT CSSProperty : public CSSUnresolvedProperty {
bool IsValidForMarker() const { return flags_ & kValidForMarker; }
bool IsSurrogate() const { return flags_ & kSurrogate; }
bool AffectsFont() const { return flags_ & kAffectsFont; }
+ bool IsBackground() const { return flags_ & kBackground; }
+ bool IsBorder() const { return flags_ & kBorder; }
+ bool IsComputedValueComparable() const {
+ return flags_ & kComputedValueComparable;
+ }
bool IsRepeated() const { return repetition_separator_ != '\0'; }
char RepetitionSeparator() const { return repetition_separator_; }
@@ -71,6 +76,13 @@ class CORE_EXPORT CSSProperty : public CSSUnresolvedProperty {
return false;
}
+ virtual bool ComputedValuesEqual(const ComputedStyle&,
+ const ComputedStyle&) const {
+ // May only be called if IsComputedValueComparable() is true.
+ NOTREACHED();
+ return false;
+ }
+
virtual const CSSValue* CSSValueFromComputedStyleInternal(
const ComputedStyle&,
const SVGComputedStyle&,
@@ -131,6 +143,12 @@ class CORE_EXPORT CSSProperty : public CSSUnresolvedProperty {
// inline-size is a surrogate for either width or height.
kSurrogate = 1 << 14,
kAffectsFont = 1 << 15,
+ // If the author specifies any background or border property on an UI
+ // element, the native appearance must be disabled.
+ kBackground = 1 << 16,
+ kBorder = 1 << 17,
+ // Set if ComputedValuesEqual is implemented for the given CSSProperty.
+ kComputedValueComparable = 1 << 18,
};
constexpr CSSProperty(CSSPropertyID property_id,
diff --git a/chromium/third_party/blink/renderer/core/css/properties/css_property_test.cc b/chromium/third_party/blink/renderer/core/css/properties/css_property_test.cc
index 0ea0edf0642..7dca63e71c3 100644
--- a/chromium/third_party/blink/renderer/core/css/properties/css_property_test.cc
+++ b/chromium/third_party/blink/renderer/core/css/properties/css_property_test.cc
@@ -7,13 +7,35 @@
#include "third_party/blink/renderer/core/css/css_property_names.h"
#include "third_party/blink/renderer/core/css/css_test_helpers.h"
#include "third_party/blink/renderer/core/css/properties/css_property_instances.h"
+#include "third_party/blink/renderer/core/css/properties/css_property_ref.h"
+#include "third_party/blink/renderer/core/css/resolver/style_builder.h"
+#include "third_party/blink/renderer/core/css/resolver/style_resolver_state.h"
+#include "third_party/blink/renderer/core/html/html_element.h"
#include "third_party/blink/renderer/core/style/computed_style.h"
#include "third_party/blink/renderer/core/style/data_equivalency.h"
#include "third_party/blink/renderer/core/testing/page_test_base.h"
namespace blink {
-class CSSPropertyTest : public PageTestBase {};
+class CSSPropertyTest : public PageTestBase {
+ public:
+ const CSSValue* Parse(String name, String value) {
+ auto* set = css_test_helpers::ParseDeclarationBlock(name + ":" + value);
+ DCHECK(set);
+ if (set->PropertyCount() != 1)
+ return nullptr;
+ return &set->PropertyAt(0).Value();
+ }
+
+ scoped_refptr<ComputedStyle> ComputedStyleWithValue(
+ const CSSProperty& property,
+ const CSSValue& value) {
+ StyleResolverState state(GetDocument(), *GetDocument().body());
+ state.SetStyle(ComputedStyle::Create());
+ StyleBuilder::ApplyProperty(property, state, value);
+ return state.TakeStyle();
+ }
+};
TEST_F(CSSPropertyTest, VisitedPropertiesAreNotWebExposed) {
for (CSSPropertyID property_id : CSSPropertyIDList()) {
@@ -39,16 +61,15 @@ TEST_F(CSSPropertyTest, GetUnvisitedPropertyFromVisited) {
}
}
-TEST_F(CSSPropertyTest, InternalEffectiveZoomNotWebExposed) {
- const CSSProperty& property = GetCSSPropertyInternalEffectiveZoom();
- EXPECT_FALSE(property.IsWebExposed(GetDocument().GetExecutionContext()));
-}
+TEST_F(CSSPropertyTest, InternalResetEffectiveNotWebExposed) {
+ const CSSPropertyValueSet* ua_set = css_test_helpers::ParseDeclarationBlock(
+ "zoom:-internal-reset-effective", kUASheetMode);
+ const CSSPropertyValueSet* author_set =
+ css_test_helpers::ParseDeclarationBlock("zoom:-internal-reset-effective",
+ kHTMLStandardMode);
-TEST_F(CSSPropertyTest, InternalEffectiveZoomCanBeParsed) {
- const CSSValue* value = css_test_helpers::ParseLonghand(
- GetDocument(), GetCSSPropertyInternalEffectiveZoom(), "1.2");
- ASSERT_TRUE(value);
- EXPECT_EQ("1.2", value->CssText());
+ EXPECT_TRUE(ua_set->HasProperty(CSSPropertyID::kZoom));
+ EXPECT_FALSE(author_set->HasProperty(CSSPropertyID::kZoom));
}
TEST_F(CSSPropertyTest, VisitedPropertiesCanParseValues) {
@@ -102,4 +123,103 @@ TEST_F(CSSPropertyTest, Surrogates) {
WritingMode::kHorizontalTb));
}
+TEST_F(CSSPropertyTest, ComputedValuesEqualsSelf) {
+ scoped_refptr<ComputedStyle> style = ComputedStyle::Create();
+
+ for (CSSPropertyID id : CSSPropertyIDList()) {
+ const CSSProperty& property = CSSProperty::Get(id);
+ if (!property.IsComputedValueComparable())
+ continue;
+ EXPECT_TRUE(property.ComputedValuesEqual(*style, *style));
+ }
+}
+
+namespace {
+
+// Examples must produce unique computed values. For example, it's not
+// allowed to list both 2px and calc(1px + 1px).
+const char* color_examples[] = {"red", "green", "#fef", "#faf", nullptr};
+const char* direction_examples[] = {"ltr", "rtl", nullptr};
+const char* length_or_auto_examples[] = {"auto", "1px", "2px", "5%", nullptr};
+const char* vertical_align_examples[] = {"sub", "super", "1px", "3%", nullptr};
+const char* writing_mode_examples[] = {"horizontal-tb", "vertical-rl", nullptr};
+
+struct ComputedValuesEqualData {
+ const char* name;
+ const char** examples;
+} computed_values_equal_data[] = {
+ {"-webkit-writing-mode", writing_mode_examples},
+ {"border-bottom-color", color_examples},
+ {"border-left-color", color_examples},
+ {"border-right-color", color_examples},
+ {"border-top-color", color_examples},
+ {"bottom", length_or_auto_examples},
+ {"direction", direction_examples},
+ {"left", length_or_auto_examples},
+ {"right", length_or_auto_examples},
+ {"top", length_or_auto_examples},
+ {"vertical-align", vertical_align_examples},
+ {"writing-mode", writing_mode_examples},
+};
+
+} // namespace
+
+TEST_F(CSSPropertyTest, ComparablePropertiesAreListed) {
+ HashSet<String> names;
+ for (const auto& data : computed_values_equal_data)
+ names.insert(data.name);
+
+ for (CSSPropertyID id : CSSPropertyIDList()) {
+ const CSSProperty& property = CSSProperty::Get(id);
+ EXPECT_TRUE(!property.IsComputedValueComparable() ||
+ names.Contains(property.GetPropertyNameString()))
+ << property.GetPropertyNameString() << " missing";
+ }
+}
+
+// This test verifies the correctness of CSSProperty::ComputedValuesEqual for
+// all properties that have the kComputedValueComparable flag.
+class ComputedValuesEqual
+ : public CSSPropertyTest,
+ public testing::WithParamInterface<ComputedValuesEqualData> {};
+
+INSTANTIATE_TEST_SUITE_P(CSSPropertyTest,
+ ComputedValuesEqual,
+ testing::ValuesIn(computed_values_equal_data));
+
+TEST_P(ComputedValuesEqual, Examples) {
+ auto data = GetParam();
+
+ CSSPropertyRef ref(data.name, GetDocument());
+ ASSERT_TRUE(ref.IsValid()) << data.name;
+ const CSSProperty& property = ref.GetProperty();
+ ASSERT_TRUE(property.IsComputedValueComparable()) << data.name;
+
+ // Convert const char* examples to CSSValues.
+ HeapVector<Member<const CSSValue>> values;
+ for (const char** example = data.examples; *example; ++example) {
+ const CSSValue* value = Parse(data.name, *example);
+ ASSERT_TRUE(value) << data.name << ":" << *example;
+ values.push_back(value);
+ }
+
+ for (const CSSValue* value_a : values) {
+ for (const CSSValue* value_b : values) {
+ auto style_a = ComputedStyleWithValue(property, *value_a);
+ auto style_b = ComputedStyleWithValue(property, *value_b);
+ if (value_a == value_b) {
+ EXPECT_TRUE(property.ComputedValuesEqual(*style_a, *style_b))
+ << property.GetPropertyNameString()
+ << ": expected equality between " << value_a->CssText() << " and "
+ << value_b->CssText();
+ } else {
+ EXPECT_FALSE(property.ComputedValuesEqual(*style_a, *style_b))
+ << property.GetPropertyNameString()
+ << ": expected non-equality between " << value_a->CssText()
+ << " and " << value_b->CssText();
+ }
+ }
+ }
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/longhands/custom_property.cc b/chromium/third_party/blink/renderer/core/css/properties/longhands/custom_property.cc
index 8cb1be641d8..74da2844163 100644
--- a/chromium/third_party/blink/renderer/core/css/properties/longhands/custom_property.cc
+++ b/chromium/third_party/blink/renderer/core/css/properties/longhands/custom_property.cc
@@ -15,6 +15,16 @@
namespace blink {
+namespace {
+
+CSSProperty::Flags InheritedFlag(const PropertyRegistration* registration) {
+ if (!registration || registration->Inherits())
+ return CSSProperty::kInherited;
+ return 0;
+}
+
+} // namespace
+
CustomProperty::CustomProperty(const AtomicString& name,
const Document& document)
: CustomProperty(
@@ -27,7 +37,8 @@ CustomProperty::CustomProperty(const AtomicString& name,
CustomProperty::CustomProperty(const AtomicString& name,
const PropertyRegistration* registration)
- : Variable(!registration || registration->Inherits()),
+ : Variable(InheritedFlag(registration) |
+ CSSProperty::kComputedValueComparable),
name_(name),
registration_(registration) {}
@@ -79,6 +90,7 @@ void CustomProperty::ApplyValue(StyleResolverState& state,
const auto& declaration = To<CSSCustomPropertyDeclaration>(value);
+ DCHECK(!value.IsRevertValue());
bool is_inherited_property = IsInherited();
bool initial = declaration.IsInitial(is_inherited_property);
bool inherit = declaration.IsInherit(is_inherited_property);
@@ -152,6 +164,20 @@ const CSSValue* CustomProperty::ParseSingleValue(
}
}
+bool CustomProperty::ComputedValuesEqual(const ComputedStyle& a,
+ const ComputedStyle& b) const {
+ if (registration_) {
+ const CSSValue* a_value = a.GetVariableValue(name_, IsInherited());
+ const CSSValue* b_value = b.GetVariableValue(name_, IsInherited());
+ if (!DataEquivalent(a_value, b_value))
+ return false;
+ }
+
+ CSSVariableData* a_data = a.GetVariableData(name_, IsInherited());
+ CSSVariableData* b_data = b.GetVariableData(name_, IsInherited());
+ return DataEquivalent(a_data, b_data);
+}
+
const CSSValue* CustomProperty::CSSValueFromComputedStyleInternal(
const ComputedStyle& style,
const SVGComputedStyle&,
diff --git a/chromium/third_party/blink/renderer/core/css/properties/longhands/custom_property.h b/chromium/third_party/blink/renderer/core/css/properties/longhands/custom_property.h
index 1e498cd35bc..28b2991c75f 100644
--- a/chromium/third_party/blink/renderer/core/css/properties/longhands/custom_property.h
+++ b/chromium/third_party/blink/renderer/core/css/properties/longhands/custom_property.h
@@ -41,6 +41,9 @@ class CORE_EXPORT CustomProperty : public Variable {
const CSSParserContext&,
const CSSParserLocalContext&) const override;
+ bool ComputedValuesEqual(const ComputedStyle&,
+ const ComputedStyle&) const override;
+
const CSSValue* CSSValueFromComputedStyleInternal(
const ComputedStyle&,
const SVGComputedStyle&,
diff --git a/chromium/third_party/blink/renderer/core/css/properties/longhands/custom_property_test.cc b/chromium/third_party/blink/renderer/core/css/properties/longhands/custom_property_test.cc
index 9819322441e..1b206d574c5 100644
--- a/chromium/third_party/blink/renderer/core/css/properties/longhands/custom_property_test.cc
+++ b/chromium/third_party/blink/renderer/core/css/properties/longhands/custom_property_test.cc
@@ -29,9 +29,13 @@ class CustomPropertyTest : public PageTestBase {
UpdateAllLifecyclePhasesForTest();
}
- const CSSValue* GetComputedValue(const CustomProperty& property) {
+ const ComputedStyle& GetComputedStyle() {
Element* node = GetDocument().getElementById("target");
- return property.CSSValueFromComputedStyle(node->ComputedStyleRef(),
+ return node->ComputedStyleRef();
+ }
+
+ const CSSValue* GetComputedValue(const CustomProperty& property) {
+ return property.CSSValueFromComputedStyle(GetComputedStyle(),
nullptr /* layout_object */,
false /* allow_visited_style */);
}
@@ -82,6 +86,38 @@ TEST_F(CustomPropertyTest, GetPropertyNameAtomicString) {
EXPECT_EQ(AtomicString("--x"), property.GetPropertyNameAtomicString());
}
+TEST_F(CustomPropertyTest, ComputedValuesEqual) {
+ RegisterProperty(GetDocument(), "--y", "<length>", "100px", false);
+
+ CustomProperty x("--x", GetDocument());
+ CustomProperty y("--y", GetDocument());
+
+ SetElementWithStyle("--x:foo;--y:10px");
+ auto style1 = ComputedStyle::Clone(GetComputedStyle());
+
+ SetElementWithStyle("--x:foo;--y:10px");
+ auto style2 = ComputedStyle::Clone(GetComputedStyle());
+
+ SetElementWithStyle("--x:bar;--y:30px");
+ auto style3 = ComputedStyle::Clone(GetComputedStyle());
+
+ ASSERT_TRUE(x.IsComputedValueComparable());
+ EXPECT_TRUE(x.ComputedValuesEqual(*style1, *style1));
+ EXPECT_TRUE(x.ComputedValuesEqual(*style2, *style2));
+ EXPECT_TRUE(x.ComputedValuesEqual(*style1, *style2));
+ EXPECT_TRUE(x.ComputedValuesEqual(*style2, *style1));
+ EXPECT_FALSE(x.ComputedValuesEqual(*style1, *style3));
+ EXPECT_FALSE(x.ComputedValuesEqual(*style2, *style3));
+
+ ASSERT_TRUE(y.IsComputedValueComparable());
+ EXPECT_TRUE(y.ComputedValuesEqual(*style1, *style1));
+ EXPECT_TRUE(y.ComputedValuesEqual(*style2, *style2));
+ EXPECT_TRUE(y.ComputedValuesEqual(*style1, *style2));
+ EXPECT_TRUE(y.ComputedValuesEqual(*style2, *style1));
+ EXPECT_FALSE(y.ComputedValuesEqual(*style1, *style3));
+ EXPECT_FALSE(y.ComputedValuesEqual(*style2, *style3));
+}
+
TEST_F(CustomPropertyTest, ComputedCSSValueUnregistered) {
CustomProperty property("--x", GetDocument());
SetElementWithStyle("--x:foo");
diff --git a/chromium/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc
index 2273c259d3a..a5e40f0e436 100644
--- a/chromium/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc
+++ b/chromium/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc
@@ -25,6 +25,7 @@
#include "third_party/blink/renderer/core/css/css_value_list.h"
#include "third_party/blink/renderer/core/css/css_value_pair.h"
#include "third_party/blink/renderer/core/css/parser/css_parser_context.h"
+#include "third_party/blink/renderer/core/css/parser/css_parser_fast_paths.h"
#include "third_party/blink/renderer/core/css/parser/css_parser_local_context.h"
#include "third_party/blink/renderer/core/css/parser/css_parser_mode.h"
#include "third_party/blink/renderer/core/css/parser/css_parser_token.h"
@@ -2854,29 +2855,6 @@ const CSSValue* ForcedColorAdjust::CSSValueFromComputedStyleInternal(
return CSSIdentifierValue::Create(style.ForcedColorAdjust());
}
-void InternalEffectiveZoom::ApplyInitial(StyleResolverState& state) const {
- auto initial = ComputedStyleInitialValues::InitialInternalEffectiveZoom();
- state.SetEffectiveZoom(initial);
-}
-
-void InternalEffectiveZoom::ApplyInherit(StyleResolverState& state) const {
- state.SetEffectiveZoom(state.ParentStyle()->EffectiveZoom());
-}
-
-void InternalEffectiveZoom::ApplyValue(StyleResolverState& state,
- const CSSValue& value) const {
- state.SetEffectiveZoom(StyleBuilderConverter::ConvertZoom(state, value));
-}
-
-const CSSValue* InternalEffectiveZoom::ParseSingleValue(
- CSSParserTokenRange& range,
- const CSSParserContext& context,
- const CSSParserLocalContext& local_context) const {
- ValueRange value_range = kValueRangeNonNegative;
- return css_property_parser_helpers::ConsumeNumber(range, context,
- value_range);
-}
-
void InternalVisitedColor::ApplyInitial(StyleResolverState& state) const {
if (!RuntimeEnabledFeatures::CSSCascadeEnabled()) {
state.SetCascadedVisitedColorValue(
@@ -4135,6 +4113,14 @@ const CSSValue* MathStyle::CSSValueFromComputedStyleInternal(
return CSSIdentifierValue::Create(style.MathStyle());
}
+const CSSValue* MathSuperscriptShiftStyle::CSSValueFromComputedStyleInternal(
+ const ComputedStyle& style,
+ const SVGComputedStyle&,
+ const LayoutObject*,
+ bool allow_visited_style) const {
+ return CSSIdentifierValue::Create(style.MathSuperscriptShiftStyle());
+}
+
const CSSValue* MaxBlockSize::ParseSingleValue(
CSSParserTokenRange& range,
const CSSParserContext& context,
@@ -5934,21 +5920,21 @@ const CSSValue* StrokeWidth::CSSValueFromComputedStyleInternal(
return CSSValue::Create(svg_style.StrokeWidth().length(), 1);
}
-const CSSValue* SubtreeVisibility::CSSValueFromComputedStyleInternal(
+const CSSValue* ContentVisibility::CSSValueFromComputedStyleInternal(
const ComputedStyle& style,
const SVGComputedStyle&,
const LayoutObject*,
bool allow_visited_style) const {
- return CSSIdentifierValue::Create(style.SubtreeVisibility());
+ return CSSIdentifierValue::Create(style.ContentVisibility());
}
-const CSSValue* SubtreeVisibility::ParseSingleValue(
+const CSSValue* ContentVisibility::ParseSingleValue(
CSSParserTokenRange& range,
const CSSParserContext& context,
const CSSParserLocalContext&) const {
auto id = range.Peek().Id();
if (id == CSSValueID::kHiddenMatchable &&
- !RuntimeEnabledFeatures::CSSSubtreeVisibilityHiddenMatchableEnabled()) {
+ !RuntimeEnabledFeatures::CSSContentVisibilityHiddenMatchableEnabled()) {
return nullptr;
}
if (!css_property_parser_helpers::IdentMatches<
@@ -6106,6 +6092,32 @@ const CSSValue* TextDecorationStyle::CSSValueFromComputedStyleInternal(
style.TextDecorationStyle());
}
+const CSSValue* TextDecorationThickness::ParseSingleValue(
+ CSSParserTokenRange& range,
+ const CSSParserContext& context,
+ const CSSParserLocalContext&) const {
+ DCHECK(RuntimeEnabledFeatures::UnderlineOffsetThicknessEnabled());
+ if (auto* ident =
+ css_property_parser_helpers::ConsumeIdent<CSSValueID::kFromFont,
+ CSSValueID::kAuto>(range)) {
+ return ident;
+ }
+ return css_property_parser_helpers::ConsumeLengthOrPercent(range, context,
+ kValueRangeAll);
+}
+
+const CSSValue* TextDecorationThickness::CSSValueFromComputedStyleInternal(
+ const ComputedStyle& style,
+ const SVGComputedStyle&,
+ const LayoutObject*,
+ bool allow_visited_style) const {
+ if (style.GetTextDecorationThickness().IsFromFont())
+ return CSSIdentifierValue::Create(CSSValueID::kFromFont);
+
+ return ComputedStyleUtils::ZoomAdjustedPixelValueForLength(
+ style.GetTextDecorationThickness().Thickness(), style);
+}
+
const CSSValue* TextIndent::ParseSingleValue(
CSSParserTokenRange& range,
const CSSParserContext& context,
@@ -6229,6 +6241,15 @@ const CSSValue* TextOrientation::CSSValueFromComputedStyleInternal(
return CSSIdentifierValue::Create(style.GetTextOrientation());
}
+void TextOrientation::ApplyInitial(StyleResolverState& state) const {
+ state.SetTextOrientation(
+ ComputedStyleInitialValues::InitialTextOrientation());
+}
+
+void TextOrientation::ApplyInherit(StyleResolverState& state) const {
+ state.SetTextOrientation(state.ParentStyle()->GetTextOrientation());
+}
+
void TextOrientation::ApplyValue(StyleResolverState& state,
const CSSValue& value) const {
state.SetTextOrientation(
@@ -6371,6 +6392,26 @@ const CSSValue* TextUnderlinePosition::CSSValueFromComputedStyleInternal(
return list;
}
+const CSSValue* TextUnderlineOffset::ParseSingleValue(
+ CSSParserTokenRange& range,
+ const CSSParserContext& context,
+ const CSSParserLocalContext&) const {
+ DCHECK(RuntimeEnabledFeatures::UnderlineOffsetThicknessEnabled());
+ if (range.Peek().Id() == CSSValueID::kAuto)
+ return css_property_parser_helpers::ConsumeIdent(range);
+ return css_property_parser_helpers::ConsumeLengthOrPercent(range, context,
+ kValueRangeAll);
+}
+
+const CSSValue* TextUnderlineOffset::CSSValueFromComputedStyleInternal(
+ const ComputedStyle& style,
+ const SVGComputedStyle&,
+ const LayoutObject*,
+ bool allow_visited_style) const {
+ return ComputedStyleUtils::ZoomAdjustedPixelValueForLength(
+ style.TextUnderlineOffset(), style);
+}
+
const CSSValue* Top::ParseSingleValue(
CSSParserTokenRange& range,
const CSSParserContext& context,
@@ -6484,7 +6525,7 @@ const CSSValue* Transform::CSSValueFromComputedStyleInternal(
const SVGComputedStyle&,
const LayoutObject* layout_object,
bool allow_visited_style) const {
- return ComputedStyleUtils::ComputedTransform(layout_object, style);
+ return ComputedStyleUtils::ResolvedTransform(layout_object, style);
}
const CSSValue* TransformOrigin::ParseSingleValue(
@@ -6834,7 +6875,24 @@ void WebkitAppRegion::ApplyValue(StyleResolverState& state,
state.GetDocument().SetHasAnnotatedRegions(true);
}
-const CSSValue* WebkitAppearance::CSSValueFromComputedStyleInternal(
+const CSSValue* Appearance::ParseSingleValue(
+ CSSParserTokenRange& range,
+ const CSSParserContext& context,
+ const CSSParserLocalContext& local_context) const {
+ CSSValueID id = range.Peek().Id();
+ CSSPropertyID property = CSSPropertyID::kAppearance;
+ if (CSSParserFastPaths::IsValidKeywordPropertyAndValue(property, id,
+ context.Mode())) {
+ if (local_context.UseAliasParsing())
+ property = CSSPropertyID::kAliasWebkitAppearance;
+ css_property_parser_helpers::CountKeywordOnlyPropertyUsage(property,
+ context, id);
+ return css_property_parser_helpers::ConsumeIdent(range);
+ }
+ return nullptr;
+}
+
+const CSSValue* Appearance::CSSValueFromComputedStyleInternal(
const ComputedStyle& style,
const SVGComputedStyle&,
const LayoutObject*,
@@ -7409,6 +7467,21 @@ const CSSValue* WebkitRubyPosition::CSSValueFromComputedStyleInternal(
return CSSIdentifierValue::Create(style.GetRubyPosition());
}
+const CSSValue* RubyPosition::CSSValueFromComputedStyleInternal(
+ const ComputedStyle& style,
+ const SVGComputedStyle&,
+ const LayoutObject*,
+ bool allow_visited_style) const {
+ switch (style.GetRubyPosition()) {
+ case blink::RubyPosition::kBefore:
+ return CSSIdentifierValue::Create(CSSValueID::kOver);
+ case blink::RubyPosition::kAfter:
+ return CSSIdentifierValue::Create(CSSValueID::kUnder);
+ }
+ NOTREACHED();
+ return CSSIdentifierValue::Create(CSSValueID::kOver);
+}
+
const CSSValue* WebkitTapHighlightColor::ParseSingleValue(
CSSParserTokenRange& range,
const CSSParserContext& context,
@@ -7822,6 +7895,13 @@ const CSSValue* WebkitWritingMode::CSSValueFromComputedStyleInternal(
return CSSIdentifierValue::Create(style.GetWritingMode());
}
+void WebkitWritingMode::ApplyInitial(StyleResolverState& state) const {
+ state.SetWritingMode(ComputedStyleInitialValues::InitialWritingMode());
+}
+void WebkitWritingMode::ApplyInherit(StyleResolverState& state) const {
+ state.SetWritingMode(state.ParentStyle()->GetWritingMode());
+}
+
void WebkitWritingMode::ApplyValue(StyleResolverState& state,
const CSSValue& value) const {
state.SetWritingMode(
@@ -7913,6 +7993,7 @@ const CSSValue* WillChange::ParseSingleValue(
case CSSValueID::kDefault:
case CSSValueID::kInitial:
case CSSValueID::kInherit:
+ case CSSValueID::kRevert:
return nullptr;
case CSSValueID::kContents:
case CSSValueID::kScrollPosition:
@@ -8024,6 +8105,14 @@ const CSSValue* WritingMode::CSSValueFromComputedStyleInternal(
return CSSIdentifierValue::Create(style.GetWritingMode());
}
+void WritingMode::ApplyInitial(StyleResolverState& state) const {
+ state.SetWritingMode(ComputedStyleInitialValues::InitialWritingMode());
+}
+
+void WritingMode::ApplyInherit(StyleResolverState& state) const {
+ state.SetWritingMode(state.ParentStyle()->GetWritingMode());
+}
+
void WritingMode::ApplyValue(StyleResolverState& state,
const CSSValue& value) const {
state.SetWritingMode(
@@ -8087,8 +8176,10 @@ const CSSValue* Zoom::ParseSingleValue(CSSParserTokenRange& range,
const CSSParserToken& token = range.Peek();
CSSValue* zoom = nullptr;
if (token.GetType() == kIdentToken) {
- zoom =
- css_property_parser_helpers::ConsumeIdent<CSSValueID::kNormal>(range);
+ CSSIdentifierValue* ident = css_property_parser_helpers::ConsumeIdent<
+ CSSValueID::kNormal, CSSValueID::kInternalResetEffective>(range);
+ if (ident && isValueAllowedInMode(ident->GetValueID(), context.Mode()))
+ zoom = ident;
} else {
zoom = css_property_parser_helpers::ConsumePercent(range, context,
kValueRangeNonNegative);
@@ -8126,6 +8217,14 @@ void Zoom::ApplyInherit(StyleResolverState& state) const {
}
void Zoom::ApplyValue(StyleResolverState& state, const CSSValue& value) const {
+ // TODO(crbug.com/976224): Support zoom on foreignObject
+ if (const auto* ident = DynamicTo<CSSIdentifierValue>(value)) {
+ if (ident->GetValueID() == CSSValueID::kInternalResetEffective) {
+ state.SetEffectiveZoom(ComputedStyleInitialValues::InitialZoom());
+ return;
+ }
+ }
+
state.SetZoom(StyleBuilderConverter::ConvertZoom(state, value));
}
diff --git a/chromium/third_party/blink/renderer/core/css/properties/longhands/variable.h b/chromium/third_party/blink/renderer/core/css/properties/longhands/variable.h
index db5c776088c..012dc77a084 100644
--- a/chromium/third_party/blink/renderer/core/css/properties/longhands/variable.h
+++ b/chromium/third_party/blink/renderer/core/css/properties/longhands/variable.h
@@ -33,10 +33,9 @@ class CORE_EXPORT Variable : public Longhand {
static bool IsStaticInstance(const CSSProperty&);
protected:
- constexpr Variable(bool inherited)
+ explicit constexpr Variable(CSSProperty::Flags flags)
: Longhand(CSSPropertyID::kVariable,
- kProperty | (inherited ? kInherited : 0) |
- kValidForFirstLetter | kValidForMarker,
+ kProperty | kValidForFirstLetter | kValidForMarker | flags,
'\0') {}
};
diff --git a/chromium/third_party/blink/renderer/core/css/property_registration.cc b/chromium/third_party/blink/renderer/core/css/property_registration.cc
index 4ac80062d6c..c27045c2d20 100644
--- a/chromium/third_party/blink/renderer/core/css/property_registration.cc
+++ b/chromium/third_party/blink/renderer/core/css/property_registration.cc
@@ -54,7 +54,6 @@ PropertyRegistration::PropertyRegistration(
syntax,
*this)),
referenced_(false) {
- DCHECK(RuntimeEnabledFeatures::CSSVariables2Enabled());
}
static bool ComputationallyIndependent(const CSSValue& value) {
@@ -100,31 +99,25 @@ static scoped_refptr<CSSVariableData> ConvertInitialVariableData(
return To<CSSCustomPropertyDeclaration>(*value).Value();
}
-PropertyRegistration* PropertyRegistration::MaybeCreate(
- Document& document,
- const AtomicString& name,
- StyleRuleProperty& rule) {
- const auto& properties = rule.Properties();
-
- // syntax
- const CSSValue* syntax_value =
- properties.GetPropertyCSSValue(CSSPropertyID::kSyntax);
+void PropertyRegistration::DeclareProperty(Document& document,
+ const AtomicString& name,
+ StyleRuleProperty& rule) {
+ // https://drafts.css-houdini.org/css-properties-values-api-1/#the-syntax-descriptor
+ const CSSValue* syntax_value = rule.GetSyntax();
if (!syntax_value)
- return nullptr;
+ return;
base::Optional<CSSSyntaxDefinition> syntax = ConvertSyntax(*syntax_value);
if (!syntax)
- return nullptr;
+ return;
- // inherits
- const CSSValue* inherits_value =
- properties.GetPropertyCSSValue(CSSPropertyID::kInherits);
+ // https://drafts.css-houdini.org/css-properties-values-api-1/#inherits-descriptor
+ const CSSValue* inherits_value = rule.Inherits();
if (!inherits_value)
- return nullptr;
+ return;
bool inherits = ConvertInherts(*inherits_value);
- // initial-value (optional)
- const CSSValue* initial_value =
- properties.GetPropertyCSSValue(CSSPropertyID::kInitialValue);
+ // https://drafts.css-houdini.org/css-properties-values-api-1/#initial-value-descriptor
+ const CSSValue* initial_value = rule.GetInitialValue();
scoped_refptr<CSSVariableData> initial_variable_data =
ConvertInitialVariableData(initial_value);
@@ -137,9 +130,9 @@ PropertyRegistration* PropertyRegistration::MaybeCreate(
initial = syntax->Parse(initial_variable_data->TokenRange(),
*parser_context, is_animation_tainted);
if (!initial)
- return nullptr;
+ return;
if (!ComputationallyIndependent(*initial))
- return nullptr;
+ return;
initial = &StyleBuilderConverter::ConvertRegisteredPropertyInitialValue(
document, *initial);
initial_variable_data =
@@ -147,8 +140,16 @@ PropertyRegistration* PropertyRegistration::MaybeCreate(
*initial, is_animation_tainted);
}
- return MakeGarbageCollected<PropertyRegistration>(
- name, *syntax, inherits, initial, initial_variable_data);
+ // For non-universal @property rules, the initial value is required for the
+ // the rule to be valid.
+ if (!initial && !syntax->IsUniversal())
+ return;
+
+ document.EnsurePropertyRegistry().DeclareProperty(
+ name, *MakeGarbageCollected<PropertyRegistration>(
+ name, *syntax, inherits, initial, initial_variable_data));
+
+ document.GetStyleEngine().PropertyRegistryChanged();
}
void PropertyRegistration::registerProperty(
@@ -169,8 +170,8 @@ void PropertyRegistration::registerProperty(
}
AtomicString atomic_name(name);
Document* document = To<LocalDOMWindow>(execution_context)->document();
- PropertyRegistry& registry = *document->GetPropertyRegistry();
- if (registry.Registration(atomic_name)) {
+ PropertyRegistry& registry = document->EnsurePropertyRegistry();
+ if (registry.IsInRegisteredPropertySet(atomic_name)) {
exception_state.ThrowDOMException(
DOMExceptionCode::kInvalidModificationError,
"The name provided has already been registered.");
@@ -215,7 +216,7 @@ void PropertyRegistration::registerProperty(
StyleBuilderConverter::ConvertRegisteredPropertyVariableData(
*initial, is_animation_tainted);
} else {
- if (!syntax_definition->IsTokenStream()) {
+ if (!syntax_definition->IsUniversal()) {
exception_state.ThrowDOMException(
DOMExceptionCode::kSyntaxError,
"An initial value must be provided if the syntax is not '*'");
@@ -228,7 +229,12 @@ void PropertyRegistration::registerProperty(
atomic_name, *syntax_definition, property_definition->inherits(),
initial, std::move(initial_variable_data)));
- document->GetStyleEngine().CustomPropertyRegistered();
+ document->GetStyleEngine().PropertyRegistryChanged();
+}
+
+void PropertyRegistration::RemoveDeclaredProperties(Document& document) {
+ document.EnsurePropertyRegistry().RemoveDeclaredProperties();
+ document.GetStyleEngine().PropertyRegistryChanged();
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/property_registration.h b/chromium/third_party/blink/renderer/core/css/property_registration.h
index 7bcdc866b22..d9e33ea0ec8 100644
--- a/chromium/third_party/blink/renderer/core/css/property_registration.h
+++ b/chromium/third_party/blink/renderer/core/css/property_registration.h
@@ -26,14 +26,16 @@ using CSSInterpolationTypes = Vector<std::unique_ptr<CSSInterpolationType>>;
class CORE_EXPORT PropertyRegistration final
: public GarbageCollected<PropertyRegistration> {
public:
- static PropertyRegistration* MaybeCreate(Document&,
- const AtomicString& name,
- StyleRuleProperty&);
+ static void DeclareProperty(Document&,
+ const AtomicString& name,
+ StyleRuleProperty&);
static void registerProperty(ExecutionContext*,
const PropertyDefinition*,
ExceptionState&);
+ static void RemoveDeclaredProperties(Document&);
+
static const PropertyRegistration* From(const ExecutionContext*,
const AtomicString& property_name);
diff --git a/chromium/third_party/blink/renderer/core/css/property_registration.idl b/chromium/third_party/blink/renderer/core/css/property_registration.idl
index 530fdc0d2a1..e315e94f1a9 100644
--- a/chromium/third_party/blink/renderer/core/css/property_registration.idl
+++ b/chromium/third_party/blink/renderer/core/css/property_registration.idl
@@ -6,6 +6,6 @@
[
ImplementedAs=PropertyRegistration
] partial interface CSS {
- [RuntimeEnabled=CSSVariables2, MeasureAs=CSSRegisterProperty, CallWith=ExecutionContext, RaisesException]
+ [MeasureAs=CSSRegisterProperty, CallWith=ExecutionContext, RaisesException]
static void registerProperty(PropertyDefinition definition);
};
diff --git a/chromium/third_party/blink/renderer/core/css/property_registry.cc b/chromium/third_party/blink/renderer/core/css/property_registry.cc
index cfd893a84b3..d075c732751 100644
--- a/chromium/third_party/blink/renderer/core/css/property_registry.cc
+++ b/chromium/third_party/blink/renderer/core/css/property_registry.cc
@@ -8,23 +8,94 @@ namespace blink {
void PropertyRegistry::RegisterProperty(const AtomicString& name,
PropertyRegistration& registration) {
- DCHECK(!Registration(name));
- registrations_.Set(name, &registration);
+ DCHECK(!IsInRegisteredPropertySet(name));
+ registered_properties_.Set(name, &registration);
+ version_++;
+}
+
+void PropertyRegistry::DeclareProperty(const AtomicString& name,
+ PropertyRegistration& registration) {
+ DCHECK(RuntimeEnabledFeatures::CSSVariables2AtPropertyEnabled());
+ declared_properties_.Set(name, &registration);
+ version_++;
+}
+
+void PropertyRegistry::RemoveDeclaredProperties() {
+ declared_properties_.clear();
+ version_++;
}
const PropertyRegistration* PropertyRegistry::Registration(
const AtomicString& name) const {
- return registrations_.at(name);
+ // If a property is registered with both CSS.registerProperty and @property,
+ // the registration from CSS.registerProperty must win.
+ //
+ // https://drafts.css-houdini.org/css-properties-values-api-1/#determining-registration
+ if (const auto* registration = registered_properties_.at(name))
+ return registration;
+ return declared_properties_.at(name);
+}
+
+bool PropertyRegistry::IsEmpty() const {
+ return registered_properties_.IsEmpty() && declared_properties_.IsEmpty();
+}
+
+bool PropertyRegistry::IsInRegisteredPropertySet(
+ const AtomicString& name) const {
+ return registered_properties_.Contains(name);
+}
+
+PropertyRegistry::Iterator::Iterator(
+ const RegistrationMap& registered_properties,
+ const RegistrationMap& declared_properties,
+ MapIterator registered_iterator,
+ MapIterator declared_iterator)
+ : registered_iterator_(registered_iterator),
+ declared_iterator_(declared_iterator),
+ registered_properties_(registered_properties),
+ declared_properties_(declared_properties) {}
+
+// The iterator works by first yielding the CSS.registerProperty-registrations
+// unconditionally (since nothing can override them), and then yield the
+// @property-registrations that aren't masked by conflicting
+// CSS.registerProperty-registrations.
+void PropertyRegistry::Iterator::operator++() {
+ if (registered_iterator_ != registered_properties_.end())
+ ++registered_iterator_;
+ else
+ ++declared_iterator_;
+
+ if (registered_iterator_ == registered_properties_.end()) {
+ while (CurrentDeclaredIteratorIsMasked())
+ ++declared_iterator_;
+ }
+}
+
+PropertyRegistry::RegistrationMap::ValueType
+PropertyRegistry::Iterator::operator*() const {
+ if (registered_iterator_ != registered_properties_.end())
+ return *registered_iterator_;
+ return *declared_iterator_;
+}
+
+bool PropertyRegistry::Iterator::operator==(const Iterator& o) const {
+ return registered_iterator_ == o.registered_iterator_ &&
+ declared_iterator_ == o.declared_iterator_;
+}
+
+bool PropertyRegistry::Iterator::CurrentDeclaredIteratorIsMasked() {
+ return (declared_iterator_ != declared_properties_.end()) &&
+ registered_properties_.Contains(declared_iterator_->key);
}
-PropertyRegistry::RegistrationMap::const_iterator PropertyRegistry::begin()
- const {
- return registrations_.begin();
+PropertyRegistry::Iterator PropertyRegistry::begin() const {
+ return Iterator(registered_properties_, declared_properties_,
+ registered_properties_.begin(), declared_properties_.begin());
}
-PropertyRegistry::RegistrationMap::const_iterator PropertyRegistry::end()
- const {
- return registrations_.end();
+PropertyRegistry::Iterator PropertyRegistry::end() const {
+ return Iterator(registered_properties_, declared_properties_,
+ registered_properties_.end(), declared_properties_.end());
}
void PropertyRegistry::MarkReferenced(const AtomicString& property_name) const {
diff --git a/chromium/third_party/blink/renderer/core/css/property_registry.h b/chromium/third_party/blink/renderer/core/css/property_registry.h
index ad7769a293f..075df780f8f 100644
--- a/chromium/third_party/blink/renderer/core/css/property_registry.h
+++ b/chromium/third_party/blink/renderer/core/css/property_registry.h
@@ -16,20 +16,86 @@ class CORE_EXPORT PropertyRegistry : public GarbageCollected<PropertyRegistry> {
using RegistrationMap =
HeapHashMap<AtomicString, Member<PropertyRegistration>>;
+ // Registers a property (CSS.registerProperty).
void RegisterProperty(const AtomicString&, PropertyRegistration&);
+ // Registers a property (@property).
+ void DeclareProperty(const AtomicString&, PropertyRegistration&);
+
+ // Removes all registrations originating from @property. Has no effect on
+ // properties originating from CSS.registerProperty.
+ void RemoveDeclaredProperties();
+
+ // Returns the registration originating from CSS.registerProperty if present,
+ // otherwise returns the registration originating from @property (which may
+ // be nullptr).
+ //
+ // https://drafts.css-houdini.org/css-properties-values-api-1/#determining-registration
const PropertyRegistration* Registration(const AtomicString&) const;
- size_t RegistrationCount() const { return registrations_.size(); }
- RegistrationMap::const_iterator begin() const;
- RegistrationMap::const_iterator end() const;
+ bool IsEmpty() const;
+
+ // Returns a number that increases by one every time there's a change to the
+ // PropertyRegistry.
+ size_t Version() const { return version_; }
+
+ // Returns true for properties registered with RegisterProperty/
+ // (CSS.registerProperty). Ignores declared properties (@property).
+ //
+ // https://drafts.css-houdini.org/css-properties-values-api-1/#dom-window-registeredpropertyset-slot
+ bool IsInRegisteredPropertySet(const AtomicString&) const;
+
+ // Produces all active registrations.
+ //
+ // This means all registrations originating from CSS.registerProperty,
+ // plus all registration originating from @property that don't conflict
+ // with any CSS.registerProperty-registrations.
+ //
+ // https://drafts.css-houdini.org/css-properties-values-api-1/#determining-registration
+ class CORE_EXPORT Iterator {
+ STACK_ALLOCATED();
+ using MapIterator = RegistrationMap::const_iterator;
+
+ public:
+ Iterator(const RegistrationMap& registered_properties,
+ const RegistrationMap& declared_properties,
+ MapIterator registered_iterator,
+ MapIterator declared_iterator);
+
+ void operator++();
+ RegistrationMap::ValueType operator*() const;
+ bool operator==(const Iterator&) const;
+ bool operator!=(const Iterator& o) const { return !(*this == o); }
+
+ private:
+ // True if declared_iterator_ points to a registration that has already
+ // been emitted by registered_iterator_.
+ bool CurrentDeclaredIteratorIsMasked();
+
+ MapIterator registered_iterator_;
+ MapIterator declared_iterator_;
+ const RegistrationMap& registered_properties_;
+ const RegistrationMap& declared_properties_;
+ };
+
+ Iterator begin() const;
+ Iterator end() const;
- void Trace(Visitor* visitor) { visitor->Trace(registrations_); }
+ void Trace(Visitor* visitor) {
+ visitor->Trace(registered_properties_);
+ visitor->Trace(declared_properties_);
+ }
+ // Whenever a registered custom property is referenced by anything using
+ // var(), it is marked as referenced (globally). This information is used
+ // when determining whether or not a custom property animation can run
+ // on the compositor.
void MarkReferenced(const AtomicString&) const;
bool WasReferenced(const AtomicString&) const;
private:
- RegistrationMap registrations_;
+ RegistrationMap registered_properties_;
+ RegistrationMap declared_properties_;
+ size_t version_ = 0;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/property_registry_test.cc b/chromium/third_party/blink/renderer/core/css/property_registry_test.cc
new file mode 100644
index 00000000000..d70fa3b4d12
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/css/property_registry_test.cc
@@ -0,0 +1,316 @@
+// 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/core/css/property_registry.h"
+#include "third_party/blink/renderer/core/css/css_test_helpers.h"
+#include "third_party/blink/renderer/core/testing/page_test_base.h"
+#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
+#include "third_party/blink/renderer/platform/wtf/vector.h"
+
+namespace blink {
+
+class PropertyRegistryTest : public PageTestBase,
+ private ScopedCSSVariables2AtPropertyForTest {
+ public:
+ PropertyRegistryTest() : ScopedCSSVariables2AtPropertyForTest(true) {}
+
+ PropertyRegistry& Registry() {
+ return GetDocument().EnsurePropertyRegistry();
+ }
+
+ const PropertyRegistration* Registration(AtomicString name) {
+ return Registry().Registration(name);
+ }
+
+ const PropertyRegistration* RegisterProperty(AtomicString name) {
+ auto* registration = css_test_helpers::CreatePropertyRegistration(name);
+ Registry().RegisterProperty(name, *registration);
+ return registration;
+ }
+
+ const PropertyRegistration* DeclareProperty(AtomicString name) {
+ auto* registration = css_test_helpers::CreatePropertyRegistration(name);
+ Registry().DeclareProperty(name, *registration);
+ return registration;
+ }
+
+ HeapVector<Member<const PropertyRegistration>> AllRegistrations() {
+ HeapVector<Member<const PropertyRegistration>> vector;
+ for (auto entry : Registry())
+ vector.push_back(entry.value);
+ return vector;
+ }
+};
+
+TEST_F(PropertyRegistryTest, EnsurePropertyRegistry) {
+ EXPECT_FALSE(GetDocument().GetPropertyRegistry());
+ PropertyRegistry* registry = &GetDocument().EnsurePropertyRegistry();
+ EXPECT_EQ(registry, GetDocument().GetPropertyRegistry());
+}
+
+TEST_F(PropertyRegistryTest, RegisterProperty) {
+ EXPECT_FALSE(Registration("--x"));
+
+ auto* registered = RegisterProperty("--x");
+ EXPECT_EQ(registered, Registration("--x"));
+}
+
+TEST_F(PropertyRegistryTest, DeclareProperty) {
+ EXPECT_FALSE(Registration("--x"));
+
+ auto* declared = DeclareProperty("--x");
+ EXPECT_EQ(declared, Registration("--x"));
+}
+
+TEST_F(PropertyRegistryTest, DeclareThenRegisterProperty) {
+ auto* declared = DeclareProperty("--x");
+ EXPECT_EQ(declared, Registration("--x"));
+
+ auto* registered = RegisterProperty("--x");
+ EXPECT_EQ(registered, Registration("--x"));
+}
+
+TEST_F(PropertyRegistryTest, RegisterThenDeclareProperty) {
+ auto* registered = RegisterProperty("--x");
+ EXPECT_EQ(registered, Registration("--x"));
+
+ DeclareProperty("--x");
+ EXPECT_EQ(registered, Registration("--x"));
+}
+
+TEST_F(PropertyRegistryTest, RegisterAndDeclarePropertyNonOverlapping) {
+ auto* registered = RegisterProperty("--x");
+ EXPECT_EQ(registered, Registration("--x"));
+
+ auto* declared = DeclareProperty("--y");
+ EXPECT_EQ(declared, Registration("--y"));
+ EXPECT_EQ(registered, Registration("--x"));
+}
+
+TEST_F(PropertyRegistryTest, DeclareTwice) {
+ auto* declared1 = DeclareProperty("--x");
+ EXPECT_EQ(declared1, Registration("--x"));
+
+ auto* declared2 = DeclareProperty("--x");
+ EXPECT_EQ(declared2, Registration("--x"));
+}
+
+TEST_F(PropertyRegistryTest, IsInRegisteredPropertySet) {
+ EXPECT_FALSE(Registry().IsInRegisteredPropertySet("--x"));
+
+ RegisterProperty("--x");
+ EXPECT_TRUE(Registry().IsInRegisteredPropertySet("--x"));
+ EXPECT_FALSE(Registry().IsInRegisteredPropertySet("--y"));
+
+ DeclareProperty("--y");
+ EXPECT_TRUE(Registry().IsInRegisteredPropertySet("--x"));
+ EXPECT_FALSE(Registry().IsInRegisteredPropertySet("--y"));
+
+ RegisterProperty("--y");
+ EXPECT_TRUE(Registry().IsInRegisteredPropertySet("--y"));
+ EXPECT_TRUE(Registry().IsInRegisteredPropertySet("--y"));
+}
+
+TEST_F(PropertyRegistryTest, EmptyIterator) {
+ EXPECT_EQ(0u, AllRegistrations().size());
+}
+
+TEST_F(PropertyRegistryTest, IterateSingleRegistration) {
+ auto* reg1 = RegisterProperty("--x");
+ auto registrations = AllRegistrations();
+ EXPECT_EQ(1u, registrations.size());
+ EXPECT_TRUE(registrations.Contains(reg1));
+}
+
+TEST_F(PropertyRegistryTest, IterateDoubleRegistration) {
+ auto* reg1 = RegisterProperty("--x");
+ auto* reg2 = RegisterProperty("--y");
+
+ auto registrations = AllRegistrations();
+ EXPECT_EQ(2u, registrations.size());
+ EXPECT_TRUE(registrations.Contains(reg1));
+ EXPECT_TRUE(registrations.Contains(reg2));
+}
+
+TEST_F(PropertyRegistryTest, IterateSingleDeclaration) {
+ auto* reg1 = DeclareProperty("--x");
+ auto registrations = AllRegistrations();
+ EXPECT_EQ(1u, registrations.size());
+ EXPECT_TRUE(registrations.Contains(reg1));
+}
+
+TEST_F(PropertyRegistryTest, IterateDoubleDeclaration) {
+ auto* reg1 = DeclareProperty("--x");
+ auto* reg2 = DeclareProperty("--y");
+
+ auto registrations = AllRegistrations();
+ EXPECT_EQ(2u, registrations.size());
+ EXPECT_TRUE(registrations.Contains(reg1));
+ EXPECT_TRUE(registrations.Contains(reg2));
+}
+
+TEST_F(PropertyRegistryTest, IterateRegistrationAndDeclaration) {
+ auto* reg1 = RegisterProperty("--x");
+ auto* reg2 = DeclareProperty("--y");
+
+ auto registrations = AllRegistrations();
+ EXPECT_EQ(2u, registrations.size());
+ EXPECT_TRUE(registrations.Contains(reg1));
+ EXPECT_TRUE(registrations.Contains(reg2));
+}
+
+TEST_F(PropertyRegistryTest, IterateRegistrationAndDeclarationConflict) {
+ auto* reg1 = RegisterProperty("--x");
+ auto* reg2 = RegisterProperty("--y");
+ auto* reg3 = DeclareProperty("--y");
+ auto* reg4 = DeclareProperty("--z");
+
+ auto registrations = AllRegistrations();
+ EXPECT_EQ(3u, registrations.size());
+ EXPECT_TRUE(registrations.Contains(reg1));
+ EXPECT_TRUE(registrations.Contains(reg2));
+ EXPECT_FALSE(registrations.Contains(reg3));
+ EXPECT_TRUE(registrations.Contains(reg4));
+}
+
+TEST_F(PropertyRegistryTest, IterateFullOverlapSingle) {
+ auto* reg1 = DeclareProperty("--x");
+ auto* reg2 = RegisterProperty("--x");
+
+ auto registrations = AllRegistrations();
+ EXPECT_EQ(1u, registrations.size());
+ EXPECT_FALSE(registrations.Contains(reg1));
+ EXPECT_TRUE(registrations.Contains(reg2));
+}
+
+TEST_F(PropertyRegistryTest, IterateFullOverlapMulti) {
+ auto* reg1 = DeclareProperty("--x");
+ auto* reg2 = DeclareProperty("--y");
+ auto* reg3 = RegisterProperty("--x");
+ auto* reg4 = RegisterProperty("--y");
+
+ auto registrations = AllRegistrations();
+ EXPECT_EQ(2u, registrations.size());
+ EXPECT_FALSE(registrations.Contains(reg1));
+ EXPECT_FALSE(registrations.Contains(reg2));
+ EXPECT_TRUE(registrations.Contains(reg3));
+ EXPECT_TRUE(registrations.Contains(reg4));
+}
+
+TEST_F(PropertyRegistryTest, IsEmptyUntilRegisterProperty) {
+ EXPECT_TRUE(Registry().IsEmpty());
+ RegisterProperty("--x");
+ EXPECT_FALSE(Registry().IsEmpty());
+}
+
+TEST_F(PropertyRegistryTest, IsEmptyUntilDeclareProperty) {
+ EXPECT_TRUE(Registry().IsEmpty());
+ DeclareProperty("--x");
+ EXPECT_FALSE(Registry().IsEmpty());
+}
+
+TEST_F(PropertyRegistryTest, Version) {
+ EXPECT_EQ(0u, Registry().Version());
+
+ RegisterProperty("--a");
+ EXPECT_EQ(1u, Registry().Version());
+
+ RegisterProperty("--b");
+ EXPECT_EQ(2u, Registry().Version());
+
+ DeclareProperty("--c");
+ EXPECT_EQ(3u, Registry().Version());
+
+ DeclareProperty("--c");
+ EXPECT_EQ(4u, Registry().Version());
+
+ DeclareProperty("--d");
+ EXPECT_EQ(5u, Registry().Version());
+
+ Registry().RemoveDeclaredProperties();
+ EXPECT_EQ(6u, Registry().Version());
+}
+
+TEST_F(PropertyRegistryTest, RemoveDeclaredProperties) {
+ DeclareProperty("--a");
+ DeclareProperty("--b");
+ RegisterProperty("--c");
+ RegisterProperty("--d");
+
+ EXPECT_TRUE(Registration("--a"));
+ EXPECT_TRUE(Registration("--b"));
+ EXPECT_TRUE(Registration("--c"));
+ EXPECT_TRUE(Registration("--d"));
+
+ Registry().RemoveDeclaredProperties();
+
+ EXPECT_FALSE(Registration("--a"));
+ EXPECT_FALSE(Registration("--b"));
+ EXPECT_TRUE(Registration("--c"));
+ EXPECT_TRUE(Registration("--d"));
+}
+
+TEST_F(PropertyRegistryTest, MarkReferencedRegisterProperty) {
+ css_test_helpers::RegisterProperty(GetDocument(), "--x", "<length>", "0px",
+ false);
+
+ UpdateAllLifecyclePhasesForTest();
+ EXPECT_FALSE(Registry().WasReferenced("--x"));
+
+ GetDocument().documentElement()->setInnerHTML(R"HTML(
+ <style>
+ :root {
+ --x: 10px;
+ }
+ div {
+ width: var(--x);
+ }
+ </style>
+ <div id="div">Test</div>
+ )HTML");
+
+ UpdateAllLifecyclePhasesForTest();
+ EXPECT_TRUE(Registry().WasReferenced("--x"));
+}
+
+TEST_F(PropertyRegistryTest, MarkReferencedAtProperty) {
+ UpdateAllLifecyclePhasesForTest();
+ EXPECT_FALSE(Registry().WasReferenced("--x"));
+
+ GetDocument().documentElement()->setInnerHTML(R"HTML(
+ <style>
+ @property --x {
+ syntax: "<length>";
+ inherits: false;
+ initial-value: 0px;
+ }
+ :root {
+ --x: 10px;
+ }
+ div {
+ width: var(--x);
+ }
+ </style>
+ <div id="div">Test</div>
+ )HTML");
+
+ UpdateAllLifecyclePhasesForTest();
+ EXPECT_TRUE(Registry().WasReferenced("--x"));
+
+ css_test_helpers::RegisterProperty(GetDocument(), "--x", "<length>", "1px",
+ false);
+
+ // Check that the registration was successful, and did overwrite the
+ // declaration.
+ ASSERT_TRUE(Registration("--x"));
+ ASSERT_TRUE(Registration("--x")->Initial());
+ EXPECT_EQ("1px", Registration("--x")->Initial()->CssText());
+
+ // --x should still be marked as referenced, even though RegisterProperty
+ // now takes precedence over @property.
+ UpdateAllLifecyclePhasesForTest();
+ EXPECT_TRUE(Registry().WasReferenced("--x"));
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/remote_font_face_source.cc b/chromium/third_party/blink/renderer/core/css/remote_font_face_source.cc
index e00c1c19a0c..7a86d44d611 100644
--- a/chromium/third_party/blink/renderer/core/css/remote_font_face_source.cc
+++ b/chromium/third_party/blink/renderer/core/css/remote_font_face_source.cc
@@ -11,6 +11,7 @@
#include "third_party/blink/public/platform/web_effective_connection_type.h"
#include "third_party/blink/renderer/core/css/css_custom_font_data.h"
#include "third_party/blink/renderer/core/css/css_font_face.h"
+#include "third_party/blink/renderer/core/css/font_face_set_document.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame_client.h"
@@ -29,13 +30,55 @@
namespace blink {
+bool RemoteFontFaceSource::NeedsInterventionToAlignWithLCPGoal() const {
+ DCHECK_EQ(display_, kFontDisplayAuto);
+ if (!base::FeatureList::IsEnabled(
+ features::kAlignFontDisplayAutoTimeoutWithLCPGoal)) {
+ return false;
+ }
+ if (!GetDocument() ||
+ !FontFaceSetDocument::From(*GetDocument())->HasReachedLCPLimit()) {
+ return false;
+ }
+ // If a 'font-display: auto' font hasn't finished loading by the LCP limit, it
+ // should enter the swap or failure period immediately, so that it doesn't
+ // become a source of bad LCP. The only exception is when the font is
+ // immediately available from the memory cache, in which case it can be used
+ // right away without any latency.
+ return !IsLoaded() ||
+ (!FinishedFromMemoryCache() && !finished_before_lcp_limit_);
+}
+
+RemoteFontFaceSource::DisplayPeriod
+RemoteFontFaceSource::ComputeFontDisplayAutoPeriod() const {
+ DCHECK_EQ(display_, kFontDisplayAuto);
+ if (NeedsInterventionToAlignWithLCPGoal()) {
+ using Mode = features::AlignFontDisplayAutoTimeoutWithLCPGoalMode;
+ Mode mode =
+ features::kAlignFontDisplayAutoTimeoutWithLCPGoalModeParam.Get();
+ if (mode == Mode::kToFailurePeriod)
+ return kFailurePeriod;
+ DCHECK_EQ(Mode::kToSwapPeriod, mode);
+ return kSwapPeriod;
+ }
+
+ if (is_intervention_triggered_)
+ return kSwapPeriod;
+
+ switch (phase_) {
+ case kNoLimitExceeded:
+ case kShortLimitExceeded:
+ return kBlockPeriod;
+ case kLongLimitExceeded:
+ return kSwapPeriod;
+ }
+}
+
RemoteFontFaceSource::DisplayPeriod RemoteFontFaceSource::ComputePeriod()
const {
switch (display_) {
case kFontDisplayAuto:
- if (is_intervention_triggered_)
- return kSwapPeriod;
- FALLTHROUGH;
+ return ComputeFontDisplayAutoPeriod();
case kFontDisplayBlock:
switch (phase_) {
case kNoLimitExceeded:
@@ -106,7 +149,8 @@ RemoteFontFaceSource::RemoteFontFaceSource(CSSFontFace* css_font_face,
ReportOptions::kDoNotReport)),
phase_(kNoLimitExceeded),
is_intervention_triggered_(ShouldTriggerWebFontsIntervention()),
- finished_before_document_rendering_begin_(false) {
+ finished_before_document_rendering_begin_(false),
+ finished_before_lcp_limit_(false) {
DCHECK(face_);
period_ = ComputePeriod();
}
@@ -171,9 +215,11 @@ void RemoteFontFaceSource::NotifyFinished(Resource* resource) {
PruneTable();
- if (GetDocument() &&
- !GetDocument()->GetFontPreloadManager().RenderingHasBegun()) {
- finished_before_document_rendering_begin_ = true;
+ if (GetDocument()) {
+ if (!GetDocument()->GetFontPreloadManager().RenderingHasBegun())
+ finished_before_document_rendering_begin_ = true;
+ if (!FontFaceSetDocument::From(*GetDocument())->HasReachedLCPLimit())
+ finished_before_lcp_limit_ = true;
}
if (FinishedFromMemoryCache())
@@ -182,7 +228,8 @@ void RemoteFontFaceSource::NotifyFinished(Resource* resource) {
UpdatePeriod();
if (face_->FontLoaded(this)) {
- font_selector_->FontFaceInvalidated();
+ font_selector_->FontFaceInvalidated(
+ FontInvalidationReason::kFontFaceLoaded);
const scoped_refptr<FontCustomPlatformData> customFontData =
font->GetCustomFontData();
@@ -220,19 +267,23 @@ void RemoteFontFaceSource::SetDisplay(FontDisplay display) {
UpdatePeriod();
}
-void RemoteFontFaceSource::UpdatePeriod() {
+bool RemoteFontFaceSource::UpdatePeriod() {
DisplayPeriod new_period = ComputePeriod();
+ bool changed = new_period != period_;
// Fallback font is invisible iff the font is loading and in the block period.
// Invalidate the font if its fallback visibility has changed.
if (IsLoading() && period_ != new_period &&
(period_ == kBlockPeriod || new_period == kBlockPeriod)) {
PruneTable();
- if (face_->FallbackVisibilityChanged(this))
- font_selector_->FontFaceInvalidated();
+ if (face_->FallbackVisibilityChanged(this)) {
+ font_selector_->FontFaceInvalidated(
+ FontInvalidationReason::kGeneralInvalidation);
+ }
histograms_.RecordFallbackTime();
}
period_ = new_period;
+ return changed;
}
FontDisplay RemoteFontFaceSource::GetFontDisplayWithFeaturePolicyCheck(
diff --git a/chromium/third_party/blink/renderer/core/css/remote_font_face_source.h b/chromium/third_party/blink/renderer/core/css/remote_font_face_source.h
index 5476391da88..eae4e343063 100644
--- a/chromium/third_party/blink/renderer/core/css/remote_font_face_source.h
+++ b/chromium/third_party/blink/renderer/core/css/remote_font_face_source.h
@@ -126,8 +126,11 @@ class RemoteFontFaceSource final : public CSSFontFaceSource,
Document* GetDocument() const;
+ DisplayPeriod ComputeFontDisplayAutoPeriod() const;
+ bool NeedsInterventionToAlignWithLCPGoal() const;
+
DisplayPeriod ComputePeriod() const;
- void UpdatePeriod();
+ bool UpdatePeriod() override;
bool ShouldTriggerWebFontsIntervention();
bool IsLowPriorityLoadingAllowedForRemoteFont() const override;
FontDisplay GetFontDisplayWithFeaturePolicyCheck(FontDisplay,
@@ -147,6 +150,7 @@ class RemoteFontFaceSource final : public CSSFontFaceSource,
FontLoadHistograms histograms_;
bool is_intervention_triggered_;
bool finished_before_document_rendering_begin_;
+ bool finished_before_lcp_limit_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/resolver/cascade_interpolations.h b/chromium/third_party/blink/renderer/core/css/resolver/cascade_interpolations.h
index a2a9fb2c43d..a3a664a1ea4 100644
--- a/chromium/third_party/blink/renderer/core/css/resolver/cascade_interpolations.h
+++ b/chromium/third_party/blink/renderer/core/css/resolver/cascade_interpolations.h
@@ -6,16 +6,48 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_RESOLVER_CASCADE_INTERPOLATIONS_H_
#include "third_party/blink/renderer/core/animation/interpolation.h"
+#include "third_party/blink/renderer/core/animation/property_handle.h"
#include "third_party/blink/renderer/core/css/resolver/cascade_origin.h"
#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
namespace blink {
+// bit: 0-15: CSSPropertyID
+// bit: 16-23: Entry index
+// bit: 24: Presentation attribute bit (inverse)
+//
+// Our tests currently expect css properties to win over presentation
+// attributes. We borrow bit 24 for this purpose, even though it's not really
+// part of the position.
+inline uint32_t EncodeInterpolationPosition(CSSPropertyID id,
+ uint8_t index,
+ bool is_presentation_attribute) {
+ static_assert(kIntLastCSSProperty < std::numeric_limits<uint16_t>::max(),
+ "Enough bits for CSSPropertyID");
+ DCHECK_NE(id, CSSPropertyID::kInvalid);
+ DCHECK_LE(id, lastCSSProperty);
+ return (static_cast<uint32_t>(!is_presentation_attribute) << 24) |
+ (static_cast<uint32_t>(index & 0xFF) << 16) |
+ (static_cast<uint32_t>(id) & 0xFFFF);
+}
+
+inline CSSPropertyID DecodeInterpolationPropertyID(uint32_t position) {
+ return convertToCSSPropertyID(position & 0xFFFF);
+}
+
+inline uint8_t DecodeInterpolationIndex(uint32_t position) {
+ return (position >> 16) & 0xFF;
+}
+
+inline bool DecodeIsPresentationAttribute(uint32_t position) {
+ return (~position >> 24) & 1;
+}
+
class CORE_EXPORT CascadeInterpolations {
STACK_ALLOCATED();
public:
- static constexpr size_t kMaxEntryIndex = std::numeric_limits<uint16_t>::max();
+ static constexpr size_t kMaxEntryIndex = std::numeric_limits<uint8_t>::max();
struct Entry {
DISALLOW_NEW();
diff --git a/chromium/third_party/blink/renderer/core/css/resolver/cascade_interpolations_test.cc b/chromium/third_party/blink/renderer/core/css/resolver/cascade_interpolations_test.cc
index 005809de63e..9af6d156af2 100644
--- a/chromium/third_party/blink/renderer/core/css/resolver/cascade_interpolations_test.cc
+++ b/chromium/third_party/blink/renderer/core/css/resolver/cascade_interpolations_test.cc
@@ -9,7 +9,7 @@
namespace blink {
TEST(CascadeInterpolationsTest, Limit) {
- constexpr size_t max = std::numeric_limits<uint16_t>::max();
+ constexpr size_t max = std::numeric_limits<uint8_t>::max();
static_assert(CascadeInterpolations::kMaxEntryIndex == max,
"Unexpected max. If the limit increased, evaluate whether it "
@@ -43,4 +43,39 @@ TEST(CascadeInterpolationsTest, Reset) {
EXPECT_TRUE(interpolations.IsEmpty());
}
+TEST(CascadeInterpolationsTest, EncodeDecodeInterpolationPropertyID) {
+ for (CSSPropertyID id : CSSPropertyIDList()) {
+ EXPECT_EQ(id, DecodeInterpolationPropertyID(
+ EncodeInterpolationPosition(id, 0u, false)));
+ EXPECT_EQ(id, DecodeInterpolationPropertyID(
+ EncodeInterpolationPosition(id, 255u, false)));
+ EXPECT_EQ(id, DecodeInterpolationPropertyID(
+ EncodeInterpolationPosition(id, 255u, true)));
+ }
+}
+
+TEST(CascadeInterpolationsTest, EncodeDecodeInterpolationIndex) {
+ CSSPropertyID id = lastCSSProperty;
+ for (uint8_t index : Vector<uint8_t>({0u, 1u, 15u, 51u, 254u, 255u})) {
+ EXPECT_EQ(index, DecodeInterpolationIndex(
+ EncodeInterpolationPosition(id, index, false)));
+ }
+}
+
+TEST(CascadeInterpolationsTest, EncodeDecodeIsPresentationAttribute) {
+ CSSPropertyID id = lastCSSProperty;
+ EXPECT_FALSE(DecodeIsPresentationAttribute(
+ EncodeInterpolationPosition(id, 0u, false)));
+ EXPECT_FALSE(DecodeIsPresentationAttribute(
+ EncodeInterpolationPosition(id, 13u, false)));
+ EXPECT_FALSE(DecodeIsPresentationAttribute(
+ EncodeInterpolationPosition(id, 255u, false)));
+ EXPECT_TRUE(
+ DecodeIsPresentationAttribute(EncodeInterpolationPosition(id, 0u, true)));
+ EXPECT_TRUE(DecodeIsPresentationAttribute(
+ EncodeInterpolationPosition(id, 13u, true)));
+ EXPECT_TRUE(DecodeIsPresentationAttribute(
+ EncodeInterpolationPosition(id, 255u, true)));
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/resolver/cascade_map.cc b/chromium/third_party/blink/renderer/core/css/resolver/cascade_map.cc
index bfe2770df21..629115edca6 100644
--- a/chromium/third_party/blink/renderer/core/css/resolver/cascade_map.cc
+++ b/chromium/third_party/blink/renderer/core/css/resolver/cascade_map.cc
@@ -3,43 +3,123 @@
// found in the LICENSE file.
#include "third_party/blink/renderer/core/css/resolver/cascade_map.h"
+#include "third_party/blink/renderer/core/css/properties/css_property.h"
#include "third_party/blink/renderer/core/css/resolver/css_property_priority.h"
namespace blink {
-CascadePriority CascadeMap::At(const CSSPropertyName& name) const {
- if (name.IsCustomProperty())
- return custom_properties_.at(name);
+static_assert(
+ std::is_trivially_destructible<CascadePriority>::value,
+ "~CascadePriority is never called on CascadePriority objects created here");
+
+namespace {
+
+inline void AddCustom(const CSSPropertyName& name,
+ CascadePriority priority,
+ CascadeMap::CustomMap& map) {
+ auto result = map.insert(name, priority);
+ if (result.is_new_entry || result.stored_value->value < priority)
+ result.stored_value->value = priority;
+}
+
+inline void AddNative(CSSPropertyID id,
+ CascadePriority priority,
+ CascadeMap::NativeMap& map) {
+ CascadePriority* p = map.Buffer() + static_cast<size_t>(id);
+ if (!map.Bits().Has(id) || *p < priority) {
+ map.Bits().Set(id);
+ new (p) CascadePriority(priority);
+ }
+}
+
+inline CascadePriority* FindCustom(const CSSPropertyName& name,
+ CascadeMap::CustomMap& map) {
+ auto iter = map.find(name);
+ if (iter != map.end())
+ return &iter->value;
+ return nullptr;
+}
+
+inline CascadePriority* FindNative(const CSSPropertyName& name,
+ CascadeMap::NativeMap& map) {
+ size_t index = static_cast<size_t>(name.Id());
+ DCHECK_LT(index, static_cast<size_t>(numCSSProperties));
+ return map.Bits().Has(name.Id()) ? (map.Buffer() + index) : nullptr;
+}
+
+inline CascadePriority AtCustom(const CSSPropertyName& name,
+ const CascadeMap::CustomMap& map) {
+ return map.at(name);
+}
+
+inline CascadePriority AtNative(const CSSPropertyName& name,
+ const CascadeMap::NativeMap& map) {
size_t index = static_cast<size_t>(name.Id());
DCHECK_LT(index, static_cast<size_t>(numCSSProperties));
- return native_property_bits_.test(index)
- ? reinterpret_cast<const CascadePriority*>(
- native_properties_)[index]
- : CascadePriority();
+ return map.Bits().Has(name.Id()) ? map.Buffer()[index] : CascadePriority();
+}
+
+} // namespace
+
+CascadePriority CascadeMap::At(const CSSPropertyName& name) const {
+ if (name.IsCustomProperty())
+ return AtCustom(name, custom_properties_);
+ return AtNative(name, native_properties_);
+}
+
+CascadePriority CascadeMap::At(const CSSPropertyName& name,
+ CascadeOrigin origin) const {
+ if (name.IsCustomProperty()) {
+ if (origin <= CascadeOrigin::kUserAgent)
+ return CascadePriority();
+ if (origin <= CascadeOrigin::kUser)
+ return AtCustom(name, custom_user_properties_);
+ return AtCustom(name, custom_properties_);
+ }
+
+ if (origin <= CascadeOrigin::kUserAgent)
+ return AtNative(name, native_ua_properties_);
+ if (origin <= CascadeOrigin::kUser)
+ return AtNative(name, native_user_properties_);
+ return AtNative(name, native_properties_);
}
CascadePriority* CascadeMap::Find(const CSSPropertyName& name) {
+ if (name.IsCustomProperty())
+ return FindCustom(name, custom_properties_);
+ return FindNative(name, native_properties_);
+}
+
+CascadePriority* CascadeMap::Find(const CSSPropertyName& name,
+ CascadeOrigin origin) {
if (name.IsCustomProperty()) {
- auto iter = custom_properties_.find(name);
- if (iter != custom_properties_.end())
- return &iter->value;
- return nullptr;
+ if (origin <= CascadeOrigin::kUserAgent)
+ return nullptr;
+ if (origin <= CascadeOrigin::kUser)
+ return FindCustom(name, custom_user_properties_);
+ return FindCustom(name, custom_properties_);
}
- size_t index = static_cast<size_t>(name.Id());
- DCHECK_LT(index, static_cast<size_t>(numCSSProperties));
- if (!native_property_bits_.test(index))
- return nullptr;
- return reinterpret_cast<CascadePriority*>(native_properties_) + index;
+
+ if (origin <= CascadeOrigin::kUserAgent)
+ return FindNative(name, native_ua_properties_);
+ if (origin <= CascadeOrigin::kUser)
+ return FindNative(name, native_user_properties_);
+ return FindNative(name, native_properties_);
}
void CascadeMap::Add(const CSSPropertyName& name, CascadePriority priority) {
+ CascadeOrigin origin = priority.GetOrigin();
+
if (name.IsCustomProperty()) {
- DCHECK_NE(CascadeOrigin::kUserAgent, priority.GetOrigin());
- auto result = custom_properties_.insert(name, priority);
- if (result.is_new_entry || result.stored_value->value < priority)
- result.stored_value->value = priority;
+ DCHECK_NE(CascadeOrigin::kUserAgent, origin);
+ if (origin <= CascadeOrigin::kUser)
+ AddCustom(name, priority, custom_user_properties_);
+ AddCustom(name, priority, custom_properties_);
return;
}
+
+ DCHECK(!CSSProperty::Get(name.Id()).IsSurrogate());
+
CSSPropertyID id = name.Id();
size_t index = static_cast<size_t>(id);
DCHECK_LT(index, static_cast<size_t>(numCSSProperties));
@@ -50,21 +130,23 @@ void CascadeMap::Add(const CSSPropertyName& name, CascadePriority priority) {
"CascadeMap supports at most 63 high-priority properties");
if (HighPriority::PropertyHasPriority(id))
high_priority_ |= (1ull << index);
- CascadePriority* p =
- reinterpret_cast<CascadePriority*>(native_properties_) + index;
- if (!native_property_bits_.test(index) || *p < priority) {
- native_property_bits_.set(index);
- static_assert(
- std::is_trivially_destructible<CascadePriority>::value,
- "~CascadePriority is never called on these CascadePriority objects");
- new (p) CascadePriority(priority);
- }
+ has_important_ |= priority.IsImportant();
+
+ if (origin <= CascadeOrigin::kUserAgent)
+ AddNative(id, priority, native_ua_properties_);
+ if (origin <= CascadeOrigin::kUser)
+ AddNative(id, priority, native_user_properties_);
+ AddNative(id, priority, native_properties_);
}
void CascadeMap::Reset() {
high_priority_ = 0;
- native_property_bits_.reset();
+ has_important_ = false;
+ native_properties_.Bits().Reset();
+ native_ua_properties_.Bits().Reset();
+ native_user_properties_.Bits().Reset();
custom_properties_.clear();
+ custom_user_properties_.clear();
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/resolver/cascade_map.h b/chromium/third_party/blink/renderer/core/css/resolver/cascade_map.h
index 249ebcbc6cf..e9290712a68 100644
--- a/chromium/third_party/blink/renderer/core/css/resolver/cascade_map.h
+++ b/chromium/third_party/blink/renderer/core/css/resolver/cascade_map.h
@@ -5,9 +5,9 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_RESOLVER_CASCADE_MAP_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_RESOLVER_CASCADE_MAP_H_
-#include <bitset>
#include "third_party/blink/renderer/core/css/css_property_name.h"
#include "third_party/blink/renderer/core/css/css_property_names.h"
+#include "third_party/blink/renderer/core/css/properties/css_bitset.h"
#include "third_party/blink/renderer/core/css/resolver/cascade_priority.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
@@ -23,15 +23,19 @@ class CORE_EXPORT CascadeMap {
public:
// Get the CascadePriority for the given CSSPropertyName. If there is no
- // entry for the given name, CascadePriority() is returned.
+ // entry for the given name, CascadePriority() is returned. If a CascadeOrigin
+ // is provided, returns the CascadePriority for that origin.
CascadePriority At(const CSSPropertyName&) const;
+ CascadePriority At(const CSSPropertyName&, CascadeOrigin) const;
// Find the CascadePriority location for a given name, if present. If there
- // is no entry for the given name, nullptr is returned.
+ // is no entry for the given name, nullptr is returned. If a CascadeOrigin
+ // is provided, returns the CascadePriority for that origin.
//
// Note that the returned pointer may accessed to change the stored value.
//
// Note also that calling Add() invalidates the pointer.
CascadePriority* Find(const CSSPropertyName&);
+ CascadePriority* Find(const CSSPropertyName&, CascadeOrigin);
// Adds an an entry to the map if the incoming priority is greater than or
// equal to the current priority for the same name.
void Add(const CSSPropertyName&, CascadePriority);
@@ -39,18 +43,45 @@ class CORE_EXPORT CascadeMap {
// corresponding high_priority_-bit to be set. This provides a fast way to
// check which high-priority properties have been added (if any).
uint64_t HighPriorityBits() const { return high_priority_; }
+ // True if any important declaration has been added.
+ bool HasImportant() const { return has_important_; }
+ const CSSBitset& NativeBitset() const { return native_properties_.Bits(); }
// Remove all properties (both native and custom) from the CascadeMap.
void Reset();
+ class NativeMap {
+ STACK_ALLOCATED();
+
+ public:
+ CSSBitset& Bits() { return bits_; }
+ const CSSBitset& Bits() const { return bits_; }
+
+ CascadePriority* Buffer() {
+ return reinterpret_cast<CascadePriority*>(properties_);
+ }
+ const CascadePriority* Buffer() const {
+ return reinterpret_cast<const CascadePriority*>(properties_);
+ }
+
+ private:
+ // For performance reasons, a char-array is used to prevent construction of
+ // CascadePriority objects. A companion bitset keeps track of which
+ // properties are initialized.
+ CSSBitset bits_;
+ alignas(CascadePriority) char properties_[numCSSProperties *
+ sizeof(CascadePriority)];
+ };
+
+ using CustomMap = HashMap<CSSPropertyName, CascadePriority>;
+
private:
uint64_t high_priority_ = 0;
- // For performance reasons, a char-array is used to prevent construction of
- // CascadePriority objects. A companion std::bitset keeps track of which
- // properties are initialized.
- std::bitset<numCSSProperties> native_property_bits_;
- alignas(CascadePriority) char native_properties_[numCSSProperties *
- sizeof(CascadePriority)];
- HashMap<CSSPropertyName, CascadePriority> custom_properties_;
+ bool has_important_ = false;
+ NativeMap native_properties_;
+ NativeMap native_ua_properties_;
+ NativeMap native_user_properties_;
+ CustomMap custom_properties_;
+ CustomMap custom_user_properties_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/resolver/cascade_map_test.cc b/chromium/third_party/blink/renderer/core/css/resolver/cascade_map_test.cc
index 0266bf95007..6d706cbce58 100644
--- a/chromium/third_party/blink/renderer/core/css/resolver/cascade_map_test.cc
+++ b/chromium/third_party/blink/renderer/core/css/resolver/cascade_map_test.cc
@@ -6,12 +6,22 @@
#include <gtest/gtest.h>
#include "third_party/blink/renderer/core/css/css_property_name.h"
#include "third_party/blink/renderer/core/css/css_property_names.h"
+#include "third_party/blink/renderer/core/css/properties/css_property.h"
#include "third_party/blink/renderer/core/css/resolver/cascade_priority.h"
#include "third_party/blink/renderer/core/css/resolver/css_property_priority.h"
namespace blink {
namespace {
+CascadePriority UaPriority(size_t position) {
+ return CascadePriority(CascadeOrigin::kUserAgent, false, 0, position);
+}
+CascadePriority UserPriority(size_t position) {
+ return CascadePriority(CascadeOrigin::kUser, false, 0, position);
+}
+CascadePriority AuthorPriority(size_t position) {
+ return CascadePriority(CascadeOrigin::kAuthor, false, 0, position);
+}
bool AddTo(CascadeMap& map,
const CSSPropertyName& name,
@@ -175,6 +185,8 @@ TEST(CascadeMapTest, AllHighPriorityBits) {
for (CSSPropertyID id : CSSPropertyIDList()) {
if (CSSPropertyPriorityData<kHighPropertyPriority>::PropertyHasPriority(
id)) {
+ if (CSSProperty::Get(id).IsSurrogate())
+ continue;
map.Add(CSSPropertyName(id), CascadeOrigin::kAuthor);
expected |= (1ull << static_cast<uint64_t>(id));
}
@@ -227,4 +239,53 @@ TEST(CascadeMapTest, ResetHighPrio) {
EXPECT_FALSE(map.HighPriorityBits());
}
+TEST(CascadeMapTest, FindOrigin) {
+ CascadeMap map;
+
+ CSSPropertyName color(CSSPropertyID::kColor);
+ CSSPropertyName display(CSSPropertyID::kDisplay);
+ CSSPropertyName top(CSSPropertyID::kTop);
+ CSSPropertyName left(CSSPropertyID::kLeft);
+ CSSPropertyName right(CSSPropertyID::kRight);
+ CSSPropertyName bottom(CSSPropertyID::kBottom);
+
+ map.Add(color, UaPriority(1));
+ map.Add(display, UaPriority(2));
+ map.Add(top, UaPriority(3));
+ map.Add(left, UaPriority(4));
+ map.Add(right, UaPriority(5));
+
+ map.Add(display, UserPriority(10));
+ map.Add(right, UserPriority(11));
+
+ map.Add(color, AuthorPriority(20));
+ map.Add(display, AuthorPriority(21));
+ map.Add(top, AuthorPriority(22));
+ map.Add(bottom, AuthorPriority(23));
+
+ // Final result of the cascade:
+ EXPECT_EQ(AuthorPriority(20), *map.Find(color));
+ EXPECT_EQ(AuthorPriority(21), *map.Find(display));
+ EXPECT_EQ(AuthorPriority(22), *map.Find(top));
+ EXPECT_EQ(UaPriority(4), *map.Find(left));
+ EXPECT_EQ(UserPriority(11), *map.Find(right));
+ EXPECT_EQ(AuthorPriority(23), *map.Find(bottom));
+
+ // Final result up to and including kUser:
+ EXPECT_EQ(UaPriority(1), *map.Find(color, CascadeOrigin::kUser));
+ EXPECT_EQ(UserPriority(10), *map.Find(display, CascadeOrigin::kUser));
+ EXPECT_EQ(UaPriority(3), *map.Find(top, CascadeOrigin::kUser));
+ EXPECT_EQ(UaPriority(4), *map.Find(left, CascadeOrigin::kUser));
+ EXPECT_EQ(UserPriority(11), *map.Find(right, CascadeOrigin::kUser));
+ EXPECT_FALSE(map.Find(bottom, CascadeOrigin::kUser));
+
+ // Final result up to and including kUserAgent:
+ EXPECT_EQ(UaPriority(1), *map.Find(color, CascadeOrigin::kUserAgent));
+ EXPECT_EQ(UaPriority(2), *map.Find(display, CascadeOrigin::kUserAgent));
+ EXPECT_EQ(UaPriority(3), *map.Find(top, CascadeOrigin::kUserAgent));
+ EXPECT_EQ(UaPriority(4), *map.Find(left, CascadeOrigin::kUserAgent));
+ EXPECT_EQ(UaPriority(5), *map.Find(right, CascadeOrigin::kUserAgent));
+ EXPECT_FALSE(map.Find(bottom, CascadeOrigin::kUserAgent));
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/resolver/cascade_resolver.h b/chromium/third_party/blink/renderer/core/css/resolver/cascade_resolver.h
index 165f6334ab3..d60be0d8662 100644
--- a/chromium/third_party/blink/renderer/core/css/resolver/cascade_resolver.h
+++ b/chromium/third_party/blink/renderer/core/css/resolver/cascade_resolver.h
@@ -5,10 +5,12 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_RESOLVER_CASCADE_RESOLVER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_RESOLVER_CASCADE_RESOLVER_H_
+#include "base/auto_reset.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/css/css_property_name.h"
#include "third_party/blink/renderer/core/css/properties/css_property.h"
#include "third_party/blink/renderer/core/css/resolver/cascade_filter.h"
+#include "third_party/blink/renderer/core/css/resolver/cascade_origin.h"
#include "third_party/blink/renderer/core/css/rule_set.h"
namespace blink {
@@ -16,6 +18,7 @@ namespace blink {
class CascadePriority;
class CSSProperty;
class CSSVariableData;
+class CSSProperty;
namespace cssvalue {
@@ -55,6 +58,14 @@ class CORE_EXPORT CascadeResolver {
// used to skip application of a declaration).
void MarkApplied(CascadePriority*) const;
+ // If the incoming origin is kAuthor, collect flags from 'property'.
+ // AuthorFlags() can then later be used to see which flags have been observed.
+ void CollectAuthorFlags(const CSSProperty& property, CascadeOrigin origin) {
+ author_flags_ |=
+ (origin == CascadeOrigin::kAuthor ? property.GetFlags() : 0);
+ }
+ CSSProperty::Flags AuthorFlags() const { return author_flags_; }
+
// Automatically locks and unlocks the given property. (See
// CascadeResolver::IsLocked).
class CORE_EXPORT AutoLock {
@@ -96,6 +107,7 @@ class CORE_EXPORT CascadeResolver {
wtf_size_t cycle_depth_ = kNotFound;
CascadeFilter filter_;
const uint8_t generation_ = 0;
+ CSSProperty::Flags author_flags_ = 0;
// A very simple cache for CSSPendingSubstitutionValues. We cache only the
// most recently parsed CSSPendingSubstitutionValue, such that consecutive
diff --git a/chromium/third_party/blink/renderer/core/css/resolver/css_property_priority.h b/chromium/third_party/blink/renderer/core/css/resolver/css_property_priority.h
index 6e5676a5756..1e965ec2f22 100644
--- a/chromium/third_party/blink/renderer/core/css/resolver/css_property_priority.h
+++ b/chromium/third_party/blink/renderer/core/css/resolver/css_property_priority.h
@@ -88,7 +88,7 @@ CSSPropertyPriorityData<kHighPropertyPriority>::First() {
template <>
constexpr CSSPropertyID CSSPropertyPriorityData<kHighPropertyPriority>::Last() {
static_assert(static_cast<int>(CSSPropertyID::kZoom) ==
- static_cast<int>(CSSPropertyID::kColor) + 27,
+ static_cast<int>(CSSPropertyID::kColor) + 26,
"CSSPropertyID::kZoom should be the end of the high priority "
"property range");
static_assert(static_cast<int>(CSSPropertyID::kWritingMode) ==
diff --git a/chromium/third_party/blink/renderer/core/css/resolver/css_to_style_map.cc b/chromium/third_party/blink/renderer/core/css/resolver/css_to_style_map.cc
index aadd6656e8e..46c9f87039f 100644
--- a/chromium/third_party/blink/renderer/core/css/resolver/css_to_style_map.cc
+++ b/chromium/third_party/blink/renderer/core/css/resolver/css_to_style_map.cc
@@ -145,7 +145,8 @@ void CSSToStyleMap::MapFillImage(StyleResolverState& state,
CSSPropertyID property = layer->GetType() == EFillLayerType::kBackground
? CSSPropertyID::kBackgroundImage
: CSSPropertyID::kWebkitMaskImage;
- layer->SetImage(state.GetStyleImage(property, value));
+ layer->SetImage(state.GetStyleImage(
+ property, state.ResolveLightDarkPair(CSSProperty::Get(property), value)));
}
void CSSToStyleMap::MapFillRepeatX(StyleResolverState&,
diff --git a/chromium/third_party/blink/renderer/core/css/resolver/css_variable_resolver.cc b/chromium/third_party/blink/renderer/core/css/resolver/css_variable_resolver.cc
index 1ebf7711cdf..8f60d1f9127 100644
--- a/chromium/third_party/blink/renderer/core/css/resolver/css_variable_resolver.cc
+++ b/chromium/third_party/blink/renderer/core/css/resolver/css_variable_resolver.cc
@@ -68,7 +68,6 @@ scoped_refptr<CSSVariableData> CSSVariableResolver::ValueForCustomProperty(
return nullptr;
}
- DCHECK(registry_ || !RuntimeEnabledFeatures::CSSVariables2Enabled());
const PropertyRegistration* registration =
registry_ ? registry_->Registration(name) : nullptr;
@@ -536,6 +535,9 @@ CSSVariableResolver::CSSVariableResolver(const StyleResolverState& state)
: state_(state),
inherited_variables_(state.Style()->InheritedVariables()),
non_inherited_variables_(state.Style()->NonInheritedVariables()),
- registry_(state.GetDocument().GetPropertyRegistry()) {}
+ registry_(state.GetDocument().GetPropertyRegistry()) {
+ DCHECK(!RuntimeEnabledFeatures::CSSCascadeEnabled())
+ << "Use StyleCascade instead";
+}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/resolver/css_variable_resolver_test.cc b/chromium/third_party/blink/renderer/core/css/resolver/css_variable_resolver_test.cc
index a5095306bea..6883487d750 100644
--- a/chromium/third_party/blink/renderer/core/css/resolver/css_variable_resolver_test.cc
+++ b/chromium/third_party/blink/renderer/core/css/resolver/css_variable_resolver_test.cc
@@ -26,6 +26,7 @@
#include "third_party/blink/renderer/core/style/computed_style.h"
#include "third_party/blink/renderer/core/testing/page_test_base.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
+#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
namespace blink {
@@ -43,8 +44,11 @@ static const Color kTestColor = Color(255, 0, 0);
} // namespace
-class CSSVariableResolverTest : public PageTestBase {
+class CSSVariableResolverTest : public PageTestBase,
+ private ScopedCSSCascadeForTest {
public:
+ CSSVariableResolverTest() : ScopedCSSCascadeForTest(false) {}
+
void SetUp() override {
PageTestBase::SetUp();
@@ -308,9 +312,8 @@ TEST_F(CSSVariableResolverTest, NeedsResolutionClearedByResolver) {
MakeGarbageCollected<PropertyRegistration>(
"--prop3", *token_syntax, false, initial_value,
To<CSSVariableReferenceValue>(*initial_value).VariableDataValue());
- ASSERT_TRUE(GetDocument().GetPropertyRegistry());
- GetDocument().GetPropertyRegistry()->RegisterProperty("--prop3",
- *registration);
+ GetDocument().EnsurePropertyRegistry().RegisterProperty("--prop3",
+ *registration);
CustomProperty("--prop1", GetDocument()).ApplyValue(state, *prop1);
CustomProperty("--prop2", GetDocument()).ApplyValue(state, *prop2);
diff --git a/chromium/third_party/blink/renderer/core/css/resolver/element_style_resources.cc b/chromium/third_party/blink/renderer/core/css/resolver/element_style_resources.cc
index 97c4441eea0..0b8172f69d8 100644
--- a/chromium/third_party/blink/renderer/core/css/resolver/element_style_resources.cc
+++ b/chromium/third_party/blink/renderer/core/css/resolver/element_style_resources.cc
@@ -149,11 +149,11 @@ static bool BackgroundLayerMayBeSprite(const FillLayer& background_layer) {
StyleImage* ElementStyleResources::LoadPendingImage(
ComputedStyle* style,
StylePendingImage* pending_image,
- FetchParameters::ImageRequestOptimization image_request_optimization,
+ FetchParameters::ImageRequestBehavior image_request_behavior,
CrossOriginAttributeValue cross_origin) {
if (CSSImageValue* image_value = pending_image->CssImageValue()) {
return image_value->CacheImage(element_->GetDocument(),
- image_request_optimization, cross_origin);
+ image_request_behavior, cross_origin);
}
if (CSSPaintValue* paint_value = pending_image->CssPaintValue()) {
@@ -169,9 +169,9 @@ StyleImage* ElementStyleResources::LoadPendingImage(
}
if (CSSImageSetValue* image_set_value = pending_image->CssImageSetValue()) {
- return image_set_value->CacheImage(
- element_->GetDocument(), device_scale_factor_,
- image_request_optimization, cross_origin);
+ return image_set_value->CacheImage(element_->GetDocument(),
+ device_scale_factor_,
+ image_request_behavior, cross_origin);
}
NOTREACHED();
@@ -204,21 +204,19 @@ void ElementStyleResources::LoadPendingImages(ComputedStyle* style) {
background_layer; background_layer = background_layer->Next()) {
StyleImage* background_image = background_layer->GetImage();
if (background_image && background_image->IsPendingImage()) {
- FetchParameters::ImageRequestOptimization
- image_request_optimization = FetchParameters::kNone;
+ FetchParameters::ImageRequestBehavior image_request_behavior =
+ FetchParameters::kNone;
if (!BackgroundLayerMayBeSprite(*background_layer)) {
if (element_->GetDocument()
.GetFrame()
->GetLazyLoadImageSetting() ==
LocalFrame::LazyLoadImageSetting::kEnabledAutomatic) {
- image_request_optimization = FetchParameters::kDeferImageLoad;
- } else {
- image_request_optimization = FetchParameters::kAllowPlaceholder;
+ image_request_behavior = FetchParameters::kDeferImageLoad;
}
}
StyleImage* new_image =
LoadPendingImage(style, To<StylePendingImage>(background_image),
- image_request_optimization);
+ image_request_behavior);
if (new_image && new_image->IsLazyloadPossiblyDeferred()) {
LazyImageHelper::StartMonitoring(pseudo_element_ ? pseudo_element_
: element_);
@@ -236,9 +234,9 @@ void ElementStyleResources::LoadPendingImages(ComputedStyle* style) {
StyleImage* image = To<ImageContentData>(content_data)->GetImage();
if (image->IsPendingImage()) {
To<ImageContentData>(content_data)
- ->SetImage(
- LoadPendingImage(style, To<StylePendingImage>(image),
- FetchParameters::kAllowPlaceholder));
+ ->SetImage(LoadPendingImage(style,
+ To<StylePendingImage>(image),
+ FetchParameters::kNone));
}
}
}
@@ -250,7 +248,6 @@ void ElementStyleResources::LoadPendingImages(ComputedStyle* style) {
CursorData& current_cursor = cursor_list->at(i);
if (StyleImage* image = current_cursor.GetImage()) {
if (image->IsPendingImage()) {
- // cursor images shouldn't be replaced with placeholders
current_cursor.SetImage(
LoadPendingImage(style, To<StylePendingImage>(image),
FetchParameters::kNone));
@@ -263,7 +260,6 @@ void ElementStyleResources::LoadPendingImages(ComputedStyle* style) {
case CSSPropertyID::kListStyleImage: {
if (style->ListStyleImage() &&
style->ListStyleImage()->IsPendingImage()) {
- // List style images shouldn't be replaced with placeholders
style->SetListStyleImage(LoadPendingImage(
style, To<StylePendingImage>(style->ListStyleImage()),
FetchParameters::kNone));
@@ -273,7 +269,6 @@ void ElementStyleResources::LoadPendingImages(ComputedStyle* style) {
case CSSPropertyID::kBorderImageSource: {
if (style->BorderImageSource() &&
style->BorderImageSource()->IsPendingImage()) {
- // Border images shouldn't be replaced with placeholders
style->SetBorderImageSource(LoadPendingImage(
style, To<StylePendingImage>(style->BorderImageSource()),
FetchParameters::kNone));
@@ -287,7 +282,7 @@ void ElementStyleResources::LoadPendingImages(ComputedStyle* style) {
mask_image.GetImage()->IsPendingImage()) {
StyleImage* loaded_image = LoadPendingImage(
style, To<StylePendingImage>(mask_image.GetImage()),
- FetchParameters::kAllowPlaceholder);
+ FetchParameters::kNone);
reflection->SetMask(NinePieceImage(
loaded_image, mask_image.ImageSlices(), mask_image.Fill(),
mask_image.BorderSlices(), mask_image.Outset(),
@@ -301,7 +296,7 @@ void ElementStyleResources::LoadPendingImages(ComputedStyle* style) {
style->MaskBoxImageSource()->IsPendingImage()) {
style->SetMaskBoxImageSource(LoadPendingImage(
style, To<StylePendingImage>(style->MaskBoxImageSource()),
- FetchParameters::kAllowPlaceholder));
+ FetchParameters::kNone));
}
break;
}
@@ -312,8 +307,7 @@ void ElementStyleResources::LoadPendingImages(ComputedStyle* style) {
mask_layer->GetImage()->IsPendingImage()) {
mask_layer->SetImage(LoadPendingImage(
style, To<StylePendingImage>(mask_layer->GetImage()),
- FetchParameters::kAllowPlaceholder,
- kCrossOriginAttributeAnonymous));
+ FetchParameters::kNone, kCrossOriginAttributeAnonymous));
}
}
break;
@@ -323,8 +317,7 @@ void ElementStyleResources::LoadPendingImages(ComputedStyle* style) {
style->ShapeOutside()->GetImage()->IsPendingImage()) {
style->ShapeOutside()->SetImage(LoadPendingImage(
style, To<StylePendingImage>(style->ShapeOutside()->GetImage()),
- FetchParameters::kAllowPlaceholder,
- kCrossOriginAttributeAnonymous));
+ FetchParameters::kNone, kCrossOriginAttributeAnonymous));
}
break;
default:
diff --git a/chromium/third_party/blink/renderer/core/css/resolver/element_style_resources.h b/chromium/third_party/blink/renderer/core/css/resolver/element_style_resources.h
index d04897105c5..b034c99a5d8 100644
--- a/chromium/third_party/blink/renderer/core/css/resolver/element_style_resources.h
+++ b/chromium/third_party/blink/renderer/core/css/resolver/element_style_resources.h
@@ -85,7 +85,7 @@ class ElementStyleResources {
StyleImage* LoadPendingImage(
ComputedStyle*,
StylePendingImage*,
- FetchParameters::ImageRequestOptimization,
+ FetchParameters::ImageRequestBehavior,
CrossOriginAttributeValue = kCrossOriginAttributeNotSet);
Element* element_;
diff --git a/chromium/third_party/blink/renderer/core/css/resolver/matched_properties_cache.cc b/chromium/third_party/blink/renderer/core/css/resolver/matched_properties_cache.cc
index 08a34b7e55a..5f37a6cce7a 100644
--- a/chromium/third_party/blink/renderer/core/css/resolver/matched_properties_cache.cc
+++ b/chromium/third_party/blink/renderer/core/css/resolver/matched_properties_cache.cc
@@ -31,14 +31,24 @@
#include "third_party/blink/renderer/core/css/resolver/matched_properties_cache.h"
#include "third_party/blink/renderer/core/css/css_property_value_set.h"
+#include "third_party/blink/renderer/core/css/properties/css_property_ref.h"
#include "third_party/blink/renderer/core/css/resolver/style_resolver_state.h"
#include "third_party/blink/renderer/core/style/computed_style.h"
+#include "third_party/blink/renderer/platform/wtf/text/string_hasher.h"
namespace blink {
-void CachedMatchedProperties::Set(const ComputedStyle& style,
- const ComputedStyle& parent_style,
- const MatchedPropertiesVector& properties) {
+static unsigned ComputeMatchedPropertiesHash(const MatchResult& result) {
+ const MatchedPropertiesVector& vector = result.GetMatchedProperties();
+ return StringHasher::HashMemory(vector.data(),
+ sizeof(MatchedProperties) * vector.size());
+}
+
+void CachedMatchedProperties::Set(
+ const ComputedStyle& style,
+ const ComputedStyle& parent_style,
+ const MatchedPropertiesVector& properties,
+ const HashSet<CSSPropertyName>& dependencies) {
for (const auto& new_matched_properties : properties) {
matched_properties.push_back(new_matched_properties.properties);
matched_properties_types.push_back(new_matched_properties.types_);
@@ -49,33 +59,62 @@ void CachedMatchedProperties::Set(const ComputedStyle& style,
// for the substructures and never used as-is.
this->computed_style = ComputedStyle::Clone(style);
this->parent_computed_style = ComputedStyle::Clone(parent_style);
+
+ for (const CSSPropertyName& name : dependencies)
+ this->dependencies.push_back(name);
}
void CachedMatchedProperties::Clear() {
matched_properties.clear();
computed_style = nullptr;
parent_computed_style = nullptr;
+ dependencies.clear();
+}
+
+bool CachedMatchedProperties::DependenciesEqual(
+ const StyleResolverState& state) {
+ if (!state.ParentStyle())
+ return false;
+
+ for (const CSSPropertyName& name : dependencies) {
+ CSSPropertyRef ref(name, state.GetDocument());
+ DCHECK(ref.IsValid());
+ if (!ref.GetProperty().ComputedValuesEqual(*parent_computed_style,
+ *state.ParentStyle())) {
+ return false;
+ }
+ }
+
+ return true;
}
MatchedPropertiesCache::MatchedPropertiesCache() = default;
-const CachedMatchedProperties* MatchedPropertiesCache::Find(
- unsigned hash,
- const StyleResolverState& style_resolver_state,
- const MatchedPropertiesVector& properties) {
- DCHECK(hash);
+MatchedPropertiesCache::Key::Key(const MatchResult& result)
+ : Key(result,
+ result.IsCacheable() ? ComputeMatchedPropertiesHash(result) : 0) {}
- Cache::iterator it = cache_.find(hash);
+MatchedPropertiesCache::Key::Key(const MatchResult& result, unsigned hash)
+ : result_(result), hash_(hash) {}
+
+const CachedMatchedProperties* MatchedPropertiesCache::Find(
+ const Key& key,
+ const StyleResolverState& style_resolver_state) {
+ DCHECK(key.IsValid());
+ DCHECK(key.hash_);
+ Cache::iterator it = cache_.find(key.hash_);
if (it == cache_.end())
return nullptr;
CachedMatchedProperties* cache_item = it->value.Get();
if (!cache_item)
return nullptr;
- if (*cache_item != properties)
+ if (*cache_item != key.result_.GetMatchedProperties())
return nullptr;
if (cache_item->computed_style->InsideLink() !=
style_resolver_state.Style()->InsideLink())
return nullptr;
+ if (!cache_item->DependenciesEqual(style_resolver_state))
+ return nullptr;
return cache_item;
}
@@ -104,12 +143,13 @@ bool CachedMatchedProperties::operator!=(
return !(*this == properties);
}
-void MatchedPropertiesCache::Add(const ComputedStyle& style,
+void MatchedPropertiesCache::Add(const Key& key,
+ const ComputedStyle& style,
const ComputedStyle& parent_style,
- unsigned hash,
- const MatchedPropertiesVector& properties) {
- DCHECK(hash);
- Cache::AddResult add_result = cache_.insert(hash, nullptr);
+ const HashSet<CSSPropertyName>& dependencies) {
+ DCHECK(key.IsValid());
+ DCHECK(key.hash_);
+ Cache::AddResult add_result = cache_.insert(key.hash_, nullptr);
if (add_result.is_new_entry || !add_result.stored_value->value) {
add_result.stored_value->value =
MakeGarbageCollected<CachedMatchedProperties>();
@@ -119,7 +159,8 @@ void MatchedPropertiesCache::Add(const ComputedStyle& style,
if (!add_result.is_new_entry)
cache_item->Clear();
- cache_item->Set(style, parent_style, properties);
+ cache_item->Set(style, parent_style, key.result_.GetMatchedProperties(),
+ dependencies);
}
void MatchedPropertiesCache::Clear() {
@@ -161,6 +202,10 @@ bool MatchedPropertiesCache::IsStyleCacheable(const ComputedStyle& style) {
// cacheable.
if (style.HasVariableReferenceFromNonInheritedProperty())
return false;
+ // -internal-light-dark() values in UA sheets have different computed values
+ // based on the used value of color-scheme.
+ if (style.HasNonInheritedLightDarkValue())
+ return false;
return true;
}
@@ -187,7 +232,7 @@ void MatchedPropertiesCache::Trace(Visitor* visitor) {
}
void MatchedPropertiesCache::RemoveCachedMatchedPropertiesWithDeadEntries(
- const WeakCallbackInfo& info) {
+ const LivenessBroker& info) {
Vector<unsigned> to_remove;
for (const auto& entry_pair : cache_) {
// A nullptr value indicates that the entry is currently being created; see
diff --git a/chromium/third_party/blink/renderer/core/css/resolver/matched_properties_cache.h b/chromium/third_party/blink/renderer/core/css/resolver/matched_properties_cache.h
index fd88d23411b..40a5909f127 100644
--- a/chromium/third_party/blink/renderer/core/css/resolver/matched_properties_cache.h
+++ b/chromium/third_party/blink/renderer/core/css/resolver/matched_properties_cache.h
@@ -39,19 +39,28 @@ class StyleResolverState;
class CachedMatchedProperties final
: public GarbageCollected<CachedMatchedProperties> {
public:
- // Caches data of MachedProperties. See MatchedPropertiesCache::Cache for
+ // Caches data of MatchedProperties. See |MatchedPropertiesCache::Cache| for
// semantics.
+ // We use UntracedMember<> here because WeakMember<> would require using a
+ // HeapHashSet which is slower to iterate.
Vector<UntracedMember<CSSPropertyValueSet>> matched_properties;
Vector<MatchedProperties::Data> matched_properties_types;
scoped_refptr<ComputedStyle> computed_style;
scoped_refptr<ComputedStyle> parent_computed_style;
+ Vector<CSSPropertyName> dependencies;
+
void Set(const ComputedStyle&,
const ComputedStyle& parent_style,
- const MatchedPropertiesVector&);
+ const MatchedPropertiesVector&,
+ const HashSet<CSSPropertyName>& dependencies);
void Clear();
+ // True if the computed value for each dependency is equal for the
+ // cached parent style vs. the incoming parent style.
+ bool DependenciesEqual(const StyleResolverState&);
+
void Trace(Visitor*) {}
bool operator==(const MatchedPropertiesVector& properties);
@@ -65,13 +74,28 @@ class CORE_EXPORT MatchedPropertiesCache {
MatchedPropertiesCache();
~MatchedPropertiesCache() { DCHECK(cache_.IsEmpty()); }
- const CachedMatchedProperties* Find(unsigned hash,
- const StyleResolverState&,
- const MatchedPropertiesVector&);
- void Add(const ComputedStyle&,
+ class CORE_EXPORT Key {
+ STACK_ALLOCATED();
+
+ public:
+ explicit Key(const MatchResult&);
+ bool IsValid() const { return hash_ != 0; }
+
+ private:
+ friend class MatchedPropertiesCache;
+ friend class MatchedPropertiesCacheTestKey;
+
+ Key(const MatchResult&, unsigned hash);
+
+ const MatchResult& result_;
+ unsigned hash_;
+ };
+
+ const CachedMatchedProperties* Find(const Key&, const StyleResolverState&);
+ void Add(const Key&,
+ const ComputedStyle&,
const ComputedStyle& parent_style,
- unsigned hash,
- const MatchedPropertiesVector&);
+ const HashSet<CSSPropertyName>& dependencies);
void Clear();
void ClearViewportDependent();
@@ -91,7 +115,7 @@ class CORE_EXPORT MatchedPropertiesCache {
DefaultHash<unsigned>::Hash,
HashTraits<unsigned>>;
- void RemoveCachedMatchedPropertiesWithDeadEntries(const WeakCallbackInfo&);
+ void RemoveCachedMatchedPropertiesWithDeadEntries(const LivenessBroker&);
Cache cache_;
DISALLOW_COPY_AND_ASSIGN(MatchedPropertiesCache);
diff --git a/chromium/third_party/blink/renderer/core/css/resolver/matched_properties_cache_test.cc b/chromium/third_party/blink/renderer/core/css/resolver/matched_properties_cache_test.cc
new file mode 100644
index 00000000000..496fa2b2c0d
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/css/resolver/matched_properties_cache_test.cc
@@ -0,0 +1,247 @@
+// 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/core/css/resolver/matched_properties_cache.h"
+
+#include "third_party/blink/renderer/core/css/css_property_name.h"
+#include "third_party/blink/renderer/core/css/css_test_helpers.h"
+#include "third_party/blink/renderer/core/css/resolver/style_resolver.h"
+#include "third_party/blink/renderer/core/html/html_element.h"
+#include "third_party/blink/renderer/core/style/computed_style.h"
+#include "third_party/blink/renderer/core/testing/page_test_base.h"
+
+namespace blink {
+
+using css_test_helpers::CreateVariableData;
+
+class MatchedPropertiesCacheTestKey {
+ STACK_ALLOCATED();
+
+ public:
+ explicit MatchedPropertiesCacheTestKey(String block_text, unsigned hash)
+ : key_(ParseBlock(block_text), hash) {
+ DCHECK(key_.IsValid());
+ }
+
+ const MatchedPropertiesCache::Key& InnerKey() const { return key_; }
+
+ private:
+ const MatchResult& ParseBlock(String block_text) {
+ result_.FinishAddingUARules();
+ result_.FinishAddingUserRules();
+ auto* set = css_test_helpers::ParseDeclarationBlock(block_text);
+ result_.AddMatchedProperties(set);
+ result_.FinishAddingAuthorRulesForTreeScope();
+ return result_;
+ }
+
+ MatchResult result_;
+ MatchedPropertiesCache::Key key_;
+};
+
+using TestKey = MatchedPropertiesCacheTestKey;
+
+class MatchedPropertiesCacheTestCache {
+ STACK_ALLOCATED();
+
+ public:
+ explicit MatchedPropertiesCacheTestCache(Document& document)
+ : document_(document) {}
+
+ ~MatchedPropertiesCacheTestCache() {
+ // Required by DCHECK in ~MatchedPropertiesCache.
+ cache_.Clear();
+ }
+
+ void Add(const TestKey& key,
+ const ComputedStyle& style,
+ const ComputedStyle& parent_style,
+ const Vector<String>& dependencies = Vector<String>()) {
+ HashSet<CSSPropertyName> set;
+ for (String name_string : dependencies) {
+ set.insert(
+ *CSSPropertyName::From(document_.GetExecutionContext(), name_string));
+ }
+ cache_.Add(key.InnerKey(), style, parent_style, set);
+ }
+
+ const CachedMatchedProperties* Find(const TestKey& key,
+ const ComputedStyle& style,
+ const ComputedStyle& parent_style) {
+ StyleResolverState state(document_, *document_.body(), &parent_style,
+ &parent_style);
+ state.SetStyle(ComputedStyle::Clone(style));
+ return cache_.Find(key.InnerKey(), state);
+ }
+
+ private:
+ MatchedPropertiesCache cache_;
+ Document& document_;
+};
+
+using TestCache = MatchedPropertiesCacheTestCache;
+
+class MatchedPropertiesCacheTest : public PageTestBase {
+ public:
+ scoped_refptr<ComputedStyle> CreateStyle() {
+ return StyleResolver::InitialStyleForElement(GetDocument());
+ }
+};
+
+TEST_F(MatchedPropertiesCacheTest, Miss) {
+ TestCache cache(GetDocument());
+ TestKey key("color:red", 1);
+
+ auto style = CreateStyle();
+ auto parent = CreateStyle();
+
+ EXPECT_FALSE(cache.Find(key, *style, *parent));
+}
+
+TEST_F(MatchedPropertiesCacheTest, Hit) {
+ TestCache cache(GetDocument());
+ TestKey key("color:red", 1);
+
+ auto style = CreateStyle();
+ auto parent = CreateStyle();
+
+ cache.Add(key, *style, *parent);
+ EXPECT_TRUE(cache.Find(key, *style, *parent));
+}
+
+TEST_F(MatchedPropertiesCacheTest, HitOnlyForAddedEntry) {
+ TestCache cache(GetDocument());
+
+ auto style = CreateStyle();
+ auto parent = CreateStyle();
+
+ TestKey key1("color:red", 1);
+ TestKey key2("display:block", 2);
+
+ cache.Add(key1, *style, *parent);
+
+ EXPECT_TRUE(cache.Find(key1, *style, *parent));
+ EXPECT_FALSE(cache.Find(key2, *style, *parent));
+}
+
+TEST_F(MatchedPropertiesCacheTest, HitWithStandardDependency) {
+ TestCache cache(GetDocument());
+
+ auto style = CreateStyle();
+ auto parent = CreateStyle();
+
+ TestKey key("top:inherit", 1);
+
+ cache.Add(key, *style, *parent, Vector<String>{"top"});
+ EXPECT_TRUE(cache.Find(key, *style, *parent));
+}
+
+TEST_F(MatchedPropertiesCacheTest, MissWithStandardDependency) {
+ TestCache cache(GetDocument());
+
+ auto style = CreateStyle();
+
+ auto parent1 = CreateStyle();
+ parent1->SetTop(Length(1, Length::kFixed));
+
+ auto parent2 = CreateStyle();
+ parent2->SetTop(Length(2, Length::kFixed));
+
+ TestKey key("top:inherit", 1);
+ cache.Add(key, *style, *parent1, Vector<String>{"top"});
+ EXPECT_TRUE(cache.Find(key, *style, *parent1));
+ EXPECT_FALSE(cache.Find(key, *style, *parent2));
+}
+
+TEST_F(MatchedPropertiesCacheTest, HitWithCustomDependency) {
+ TestCache cache(GetDocument());
+
+ auto style = CreateStyle();
+
+ auto parent = CreateStyle();
+ parent->SetVariableData("--x", CreateVariableData("1px"), true);
+
+ TestKey key("top:var(--x)", 1);
+
+ cache.Add(key, *style, *parent, Vector<String>{"--x"});
+ EXPECT_TRUE(cache.Find(key, *style, *parent));
+}
+
+TEST_F(MatchedPropertiesCacheTest, MissWithCustomDependency) {
+ TestCache cache(GetDocument());
+
+ auto style = CreateStyle();
+
+ auto parent1 = CreateStyle();
+ parent1->SetVariableData("--x", CreateVariableData("1px"), true);
+
+ auto parent2 = CreateStyle();
+ parent2->SetVariableData("--x", CreateVariableData("2px"), true);
+
+ TestKey key("top:var(--x)", 1);
+
+ cache.Add(key, *style, *parent1, Vector<String>{"--x"});
+ EXPECT_FALSE(cache.Find(key, *style, *parent2));
+}
+
+TEST_F(MatchedPropertiesCacheTest, HitWithMultipleCustomDependencies) {
+ TestCache cache(GetDocument());
+
+ auto style = CreateStyle();
+
+ auto parent1 = CreateStyle();
+ parent1->SetVariableData("--x", CreateVariableData("1px"), true);
+ parent1->SetVariableData("--y", CreateVariableData("2px"), true);
+ parent1->SetVariableData("--z", CreateVariableData("3px"), true);
+
+ auto parent2 = ComputedStyle::Clone(*parent1);
+ parent2->SetVariableData("--z", CreateVariableData("4px"), true);
+
+ TestKey key("top:var(--x);left:var(--y)", 1);
+
+ // Does not depend on --z, so doesn't matter that --z changed.
+ cache.Add(key, *style, *parent1, Vector<String>{"--x", "--y"});
+ EXPECT_TRUE(cache.Find(key, *style, *parent2));
+}
+
+TEST_F(MatchedPropertiesCacheTest, MissWithMultipleCustomDependencies) {
+ TestCache cache(GetDocument());
+
+ auto style = CreateStyle();
+
+ auto parent1 = CreateStyle();
+ parent1->SetVariableData("--x", CreateVariableData("1px"), true);
+ parent1->SetVariableData("--y", CreateVariableData("2px"), true);
+
+ auto parent2 = ComputedStyle::Clone(*parent1);
+ parent2->SetVariableData("--y", CreateVariableData("3px"), true);
+
+ TestKey key("top:var(--x);left:var(--y)", 1);
+
+ cache.Add(key, *style, *parent1, Vector<String>{"--x", "--y"});
+ EXPECT_FALSE(cache.Find(key, *style, *parent2));
+}
+
+TEST_F(MatchedPropertiesCacheTest, HitWithMixedDependencies) {
+ TestCache cache(GetDocument());
+
+ auto style = CreateStyle();
+
+ auto parent1 = CreateStyle();
+ parent1->SetVariableData("--x", CreateVariableData("1px"), true);
+ parent1->SetVariableData("--y", CreateVariableData("2px"), true);
+ parent1->SetLeft(Length(3, Length::kFixed));
+ parent1->SetRight(Length(4, Length::kFixed));
+
+ auto parent2 = ComputedStyle::Clone(*parent1);
+ parent2->SetVariableData("--y", CreateVariableData("5px"), true);
+ parent2->SetRight(Length(6, Length::kFixed));
+
+ TestKey key("left:inherit;top:var(--x)", 1);
+
+ cache.Add(key, *style, *parent1, Vector<String>{"left", "--x"});
+ EXPECT_TRUE(cache.Find(key, *style, *parent2));
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/resolver/style_adjuster.cc b/chromium/third_party/blink/renderer/core/css/resolver/style_adjuster.cc
index 49f61afb7c4..fa15f6680c3 100644
--- a/chromium/third_party/blink/renderer/core/css/resolver/style_adjuster.cc
+++ b/chromium/third_party/blink/renderer/core/css/resolver/style_adjuster.cc
@@ -73,10 +73,16 @@ namespace {
TouchAction AdjustTouchActionForElement(TouchAction touch_action,
const ComputedStyle& style,
Element* element) {
+ // if body is the viewport defining element then ScrollsOverflow should
+ // return false as body should have overflow-x/overflow-y set to visible
+ Element* body = element ? element->GetDocument().body() : nullptr;
+ bool is_body_and_viewport =
+ element && element == body &&
+ body == element->GetDocument().ViewportDefiningElement();
bool is_child_document =
element && element == element->GetDocument().documentElement() &&
element->GetDocument().LocalOwner();
- if (style.ScrollsOverflow() || is_child_document)
+ if ((!is_body_and_viewport && style.ScrollsOverflow()) || is_child_document)
return touch_action | TouchAction::kPan;
return touch_action;
}
@@ -566,21 +572,21 @@ static void AdjustEffectiveTouchAction(ComputedStyle& style,
}
}
-static void AdjustStateForSubtreeVisibility(ComputedStyle& style,
+static void AdjustStateForContentVisibility(ComputedStyle& style,
Element* element) {
if (!element)
return;
auto* context = element->GetDisplayLockContext();
// The common case for most elements is that we don't have a context and have
- // the default (visible) subtree-visibility value.
+ // the default (visible) content-visibility value.
if (LIKELY(!context &&
- style.SubtreeVisibility() == ESubtreeVisibility::kVisible)) {
+ style.ContentVisibility() == EContentVisibility::kVisible)) {
return;
}
if (!context)
context = &element->EnsureDisplayLockContext();
- context->SetRequestedState(style.SubtreeVisibility());
+ context->SetRequestedState(style.ContentVisibility());
context->AdjustElementStyle(&style);
}
@@ -642,8 +648,8 @@ void StyleAdjuster::AdjustComputedStyle(StyleResolverState& state,
AdjustStyleForFirstLetter(style);
}
- if (RuntimeEnabledFeatures::CSSSubtreeVisibilityEnabled())
- AdjustStateForSubtreeVisibility(style, element);
+ if (RuntimeEnabledFeatures::CSSContentVisibilityEnabled())
+ AdjustStateForContentVisibility(style, element);
// Make sure our z-index value is only applied if the object is positioned.
if (style.GetPosition() == EPosition::kStatic &&
diff --git a/chromium/third_party/blink/renderer/core/css/resolver/style_builder_converter.cc b/chromium/third_party/blink/renderer/core/css/resolver/style_builder_converter.cc
index b336c49b015..8a34c4c5594 100644
--- a/chromium/third_party/blink/renderer/core/css/resolver/style_builder_converter.cc
+++ b/chromium/third_party/blink/renderer/core/css/resolver/style_builder_converter.cc
@@ -962,20 +962,29 @@ void StyleBuilderConverter::CreateImplicitNamedGridLinesFromGridArea(
float StyleBuilderConverter::ConvertBorderWidth(StyleResolverState& state,
const CSSValue& value) {
+ double result = 0;
if (auto* identifier_value = DynamicTo<CSSIdentifierValue>(value)) {
- CSSValueID value_id = identifier_value->GetValueID();
- if (value_id == CSSValueID::kThin)
- return 1;
- if (value_id == CSSValueID::kMedium)
- return 3;
- if (value_id == CSSValueID::kThick)
- return 5;
- NOTREACHED();
- return 0;
+ switch (identifier_value->GetValueID()) {
+ case CSSValueID::kThin:
+ result = 1;
+ break;
+ case CSSValueID::kMedium:
+ result = 3;
+ break;
+ case CSSValueID::kThick:
+ result = 5;
+ break;
+ default:
+ NOTREACHED();
+ break;
+ }
+ result = state.CssToLengthConversionData().ZoomedComputedPixels(
+ result, CSSPrimitiveValue::UnitType::kPixels);
+ } else {
+ const auto& primitive_value = To<CSSPrimitiveValue>(value);
+ result =
+ primitive_value.ComputeLength<float>(state.CssToLengthConversionData());
}
- const auto& primitive_value = To<CSSPrimitiveValue>(value);
- double result =
- primitive_value.ComputeLength<float>(state.CssToLengthConversionData());
double zoomed_result = state.StyleRef().EffectiveZoom() * result;
if (zoomed_result > 0.0 && zoomed_result < 1.0)
return 1.0;
@@ -983,6 +992,11 @@ float StyleBuilderConverter::ConvertBorderWidth(StyleResolverState& state,
defaultMaximumForClamp<float>());
}
+LayoutUnit StyleBuilderConverter::ConvertLayoutUnit(StyleResolverState& state,
+ const CSSValue& value) {
+ return LayoutUnit::Clamp(ConvertComputedLength<float>(state, value));
+}
+
GapLength StyleBuilderConverter::ConvertGapLength(StyleResolverState& state,
const CSSValue& value) {
auto* identifier_value = DynamicTo<CSSIdentifierValue>(value);
@@ -1443,6 +1457,17 @@ SVGPaint StyleBuilderConverter::ConvertSVGPaint(StyleResolverState& state,
return paint;
}
+TextDecorationThickness StyleBuilderConverter::ConvertTextDecorationThickness(
+ StyleResolverState& state,
+ const CSSValue& value) {
+ auto* identifier_value = DynamicTo<CSSIdentifierValue>(value);
+ if (identifier_value &&
+ identifier_value->GetValueID() == CSSValueID::kFromFont)
+ return TextDecorationThickness(identifier_value->GetValueID());
+
+ return TextDecorationThickness(ConvertLengthOrAuto(state, value));
+}
+
TextEmphasisPosition StyleBuilderConverter::ConvertTextTextEmphasisPosition(
StyleResolverState& state,
const CSSValue& value) {
@@ -1507,6 +1532,12 @@ TextUnderlinePosition StyleBuilderConverter::ConvertTextUnderlinePosition(
return flags;
}
+Length StyleBuilderConverter::ConvertTextUnderlineOffset(
+ StyleResolverState& state,
+ const CSSValue& value) {
+ return ConvertLengthOrAuto(state, value);
+}
+
TransformOperations StyleBuilderConverter::ConvertTransformOperations(
StyleResolverState& state,
const CSSValue& value) {
@@ -1834,11 +1865,6 @@ StyleBuilderConverter::ConvertRegisteredPropertyVariableData(
has_root_font_units, absolutized, g_null_atom, WTF::TextEncoding());
}
-const CSSToLengthConversionData&
-StyleBuilderConverter::CssToLengthConversionData(StyleResolverState& state) {
- return state.CssToLengthConversionData();
-}
-
LengthSize StyleBuilderConverter::ConvertIntrinsicSize(
StyleResolverState& state,
const CSSValue& value) {
@@ -1882,4 +1908,19 @@ AtomicString StyleBuilderConverter::ConvertPage(StyleResolverState& state,
return AtomicString();
}
+RubyPosition StyleBuilderConverter::ConvertRubyPosition(
+ StyleResolverState& state,
+ const CSSValue& value) {
+ if (const auto* identifier_value = DynamicTo<CSSIdentifierValue>(value)) {
+ CSSValueID value_id = identifier_value->GetValueID();
+ if (value_id == CSSValueID::kOver)
+ return RubyPosition::kBefore;
+ if (value_id == CSSValueID::kUnder)
+ return RubyPosition::kAfter;
+ return identifier_value->ConvertTo<blink::RubyPosition>();
+ }
+ NOTREACHED();
+ return RubyPosition::kBefore;
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/resolver/style_builder_converter.h b/chromium/third_party/blink/renderer/core/css/resolver/style_builder_converter.h
index d81b23435e1..f0e732e8997 100644
--- a/chromium/third_party/blink/renderer/core/css/resolver/style_builder_converter.h
+++ b/chromium/third_party/blink/renderer/core/css/resolver/style_builder_converter.h
@@ -162,6 +162,7 @@ class StyleBuilderConverter {
template <typename T>
static T ConvertLineWidth(StyleResolverState&, const CSSValue&);
static float ConvertBorderWidth(StyleResolverState&, const CSSValue&);
+ static LayoutUnit ConvertLayoutUnit(StyleResolverState&, const CSSValue&);
static GapLength ConvertGapLength(const StyleResolverState&, const CSSValue&);
static Length ConvertLength(const StyleResolverState&, const CSSValue&);
static UnzoomedLength ConvertUnzoomedLength(const StyleResolverState&,
@@ -204,6 +205,9 @@ class StyleBuilderConverter {
const CSSValue&,
bool for_visited_link = false);
static SVGPaint ConvertSVGPaint(StyleResolverState&, const CSSValue&);
+ static TextDecorationThickness ConvertTextDecorationThickness(
+ StyleResolverState&,
+ const CSSValue&);
static TextEmphasisPosition ConvertTextTextEmphasisPosition(
StyleResolverState&,
const CSSValue&);
@@ -213,6 +217,8 @@ class StyleBuilderConverter {
static TextUnderlinePosition ConvertTextUnderlinePosition(
StyleResolverState& state,
const CSSValue& value);
+ static Length ConvertTextUnderlineOffset(StyleResolverState& state,
+ const CSSValue& value);
static TransformOperations ConvertTransformOperations(StyleResolverState&,
const CSSValue&);
static TransformOrigin ConvertTransformOrigin(StyleResolverState&,
@@ -281,16 +287,15 @@ class StyleBuilderConverter {
static AtomicString ConvertPage(StyleResolverState&, const CSSValue&);
- private:
- static const CSSToLengthConversionData& CssToLengthConversionData(
- StyleResolverState&);
+ static RubyPosition ConvertRubyPosition(StyleResolverState& state,
+ const CSSValue& value);
};
template <typename T>
T StyleBuilderConverter::ConvertComputedLength(StyleResolverState& state,
const CSSValue& value) {
return To<CSSPrimitiveValue>(value).ComputeLength<T>(
- CssToLengthConversionData(state));
+ state.CssToLengthConversionData());
}
template <typename T>
@@ -308,26 +313,34 @@ T StyleBuilderConverter::ConvertFlags(StyleResolverState& state,
template <typename T>
T StyleBuilderConverter::ConvertLineWidth(StyleResolverState& state,
const CSSValue& value) {
+ double result = 0;
if (auto* identifier_value = DynamicTo<CSSIdentifierValue>(value)) {
- CSSValueID value_id = identifier_value->GetValueID();
- if (value_id == CSSValueID::kThin)
- return 1;
- if (value_id == CSSValueID::kMedium)
- return 3;
- if (value_id == CSSValueID::kThick)
- return 5;
- NOTREACHED();
- return 0;
+ switch (identifier_value->GetValueID()) {
+ case CSSValueID::kThin:
+ result = 1;
+ break;
+ case CSSValueID::kMedium:
+ result = 3;
+ break;
+ case CSSValueID::kThick:
+ result = 5;
+ break;
+ default:
+ NOTREACHED();
+ break;
+ }
+ result = state.CssToLengthConversionData().ZoomedComputedPixels(
+ result, CSSPrimitiveValue::UnitType::kPixels);
+ } else {
+ result = To<CSSPrimitiveValue>(value).ComputeLength<double>(
+ state.CssToLengthConversionData());
}
- const auto& primitive_value = To<CSSPrimitiveValue>(value);
- // FIXME: We are moving to use the full page zoom implementation to handle
- // high-dpi. In that case specyfing a border-width of less than 1px would
- // result in a border that is one device pixel thick. With this change that
- // would instead be rounded up to 2 device pixels. Consider clamping it to
- // device pixels or zoom adjusted CSS pixels instead of raw CSS pixels.
- // Reference crbug.com/485650 and crbug.com/382483
- double result =
- primitive_value.ComputeLength<double>(CssToLengthConversionData(state));
+ // TODO(crbug.com/485650, crbug.com/382483): We are moving to use the full
+ // page zoom implementation to handle high-dpi. In that case specyfing a
+ // border-width of less than 1px would result in a border that is one device
+ // pixel thick. With this change that would instead be rounded up to 2
+ // device pixels. Consider clamping it to device pixels or zoom adjusted CSS
+ // pixels instead of raw CSS pixels.
double zoomed_result = state.StyleRef().EffectiveZoom() * result;
if (zoomed_result > 0.0 && zoomed_result < 1.0)
return 1.0;
diff --git a/chromium/third_party/blink/renderer/core/css/resolver/style_builder_test.cc b/chromium/third_party/blink/renderer/core/css/resolver/style_builder_test.cc
new file mode 100644
index 00000000000..c2d3085f5b7
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/css/resolver/style_builder_test.cc
@@ -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.
+
+#include "third_party/blink/renderer/core/css/resolver/style_builder.h"
+#include "third_party/blink/renderer/core/css/css_identifier_value.h"
+#include "third_party/blink/renderer/core/css/css_inherited_value.h"
+#include "third_party/blink/renderer/core/css/css_initial_value.h"
+#include "third_party/blink/renderer/core/css/resolver/style_resolver_state.h"
+#include "third_party/blink/renderer/core/html/html_element.h"
+#include "third_party/blink/renderer/core/style/computed_style.h"
+#include "third_party/blink/renderer/core/testing/page_test_base.h"
+#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
+
+namespace blink {
+
+class StyleBuilderTest : public PageTestBase {};
+
+TEST_F(StyleBuilderTest, WritingModeChangeDirtiesFont) {
+ const CSSProperty* properties[] = {
+ &GetCSSPropertyWritingMode(),
+ &GetCSSPropertyWebkitWritingMode(),
+ };
+
+ HeapVector<Member<const CSSValue>> values = {
+ CSSInitialValue::Create(),
+ CSSInheritedValue::Create(),
+ CSSIdentifierValue::Create(CSSValueID::kHorizontalTb),
+ };
+
+ for (const CSSProperty* property : properties) {
+ for (const CSSValue* value : values) {
+ auto parent_style = ComputedStyle::Create();
+ auto style = ComputedStyle::Create();
+ // This test assumes that initial 'writing-mode' is not 'vertical-lr'.
+ ASSERT_NE(WritingMode::kVerticalLr, style->GetWritingMode());
+ style->SetWritingMode(WritingMode::kVerticalLr);
+
+ StyleResolverState state(GetDocument(), *GetDocument().body(),
+ parent_style.get(), parent_style.get());
+ state.SetStyle(style);
+
+ ASSERT_FALSE(state.GetFontBuilder().FontDirty());
+ StyleBuilder::ApplyProperty(*property, state, *value);
+ EXPECT_TRUE(state.GetFontBuilder().FontDirty());
+ }
+ }
+}
+
+TEST_F(StyleBuilderTest, TextOrientationChangeDirtiesFont) {
+ HeapVector<Member<const CSSValue>> values = {
+ CSSInitialValue::Create(),
+ CSSInheritedValue::Create(),
+ CSSIdentifierValue::Create(CSSValueID::kMixed),
+ };
+
+ for (const CSSValue* value : values) {
+ auto parent_style = ComputedStyle::Create();
+ auto style = ComputedStyle::Create();
+ // This test assumes that initial 'text-orientation' is not 'upright'.
+ ASSERT_NE(ETextOrientation::kUpright, style->GetTextOrientation());
+ style->SetTextOrientation(ETextOrientation::kUpright);
+
+ StyleResolverState state(GetDocument(), *GetDocument().body(),
+ parent_style.get(), parent_style.get());
+ state.SetStyle(style);
+
+ ASSERT_FALSE(state.GetFontBuilder().FontDirty());
+ StyleBuilder::ApplyProperty(GetCSSPropertyTextOrientation(), state, *value);
+ EXPECT_TRUE(state.GetFontBuilder().FontDirty());
+ }
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/resolver/style_cascade.cc b/chromium/third_party/blink/renderer/core/css/resolver/style_cascade.cc
index 1fc9ecbb274..5254cf5a5d1 100644
--- a/chromium/third_party/blink/renderer/core/css/resolver/style_cascade.cc
+++ b/chromium/third_party/blink/renderer/core/css/resolver/style_cascade.cc
@@ -31,8 +31,10 @@
#include "third_party/blink/renderer/core/css/resolver/style_resolver_state.h"
#include "third_party/blink/renderer/core/css/style_engine.h"
#include "third_party/blink/renderer/core/dom/shadow_root.h"
+#include "third_party/blink/renderer/core/frame/web_feature.h"
#include "third_party/blink/renderer/core/style/computed_style.h"
#include "third_party/blink/renderer/core/style_property_shorthand.h"
+#include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
#include "third_party/blink/renderer/platform/wtf/math_extras.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
@@ -55,6 +57,14 @@ bool ConsumeComma(CSSParserTokenRange& range) {
return false;
}
+// TODO(crbug.com/1105782): It is currently unclear how to handle 'revert'
+// at computed-value-time. For now we treat it as 'unset'.
+const CSSValue* TreatRevertAsUnset(const CSSValue* value) {
+ if (value && value->IsRevertValue())
+ return cssvalue::CSSUnsetValue::Create();
+ return value;
+}
+
const CSSValue* Parse(const CSSProperty& property,
CSSParserTokenRange range,
const CSSParserContext* context) {
@@ -62,23 +72,6 @@ const CSSValue* Parse(const CSSProperty& property,
context);
}
-uint32_t EncodeInterpolationPosition(size_t index,
- bool is_presentation_attribute) {
- // Our tests currently expect css properties to win over presentation
- // attributes. Hence, we borrow a bit in the position-uint32_t for this
- // purpose.
- return (static_cast<uint32_t>(!is_presentation_attribute) << 16) |
- static_cast<uint16_t>(index);
-}
-
-size_t DecodeInterpolationIndex(uint32_t position) {
- return position & 0xFFFF;
-}
-
-bool DecodeIsPresentationAttribute(uint32_t position) {
- return (~position >> 16) & 1;
-}
-
const CSSValue* ValueAt(const MatchResult& result, uint32_t position) {
size_t matched_properties_index = DecodeMatchedPropertiesIndex(position);
size_t declaration_index = DecodeDeclarationIndex(position);
@@ -89,10 +82,40 @@ const CSSValue* ValueAt(const MatchResult& result, uint32_t position) {
PropertyHandle ToPropertyHandle(const CSSProperty& property,
CascadePriority priority) {
- if (IsA<CustomProperty>(property))
- return PropertyHandle(property.GetPropertyNameAtomicString());
uint32_t position = priority.GetPosition();
- return PropertyHandle(property, DecodeIsPresentationAttribute(position));
+ CSSPropertyID id = DecodeInterpolationPropertyID(position);
+ if (id == CSSPropertyID::kVariable) {
+ DCHECK(IsA<CustomProperty>(property));
+ return PropertyHandle(property.GetPropertyNameAtomicString());
+ }
+ return PropertyHandle(CSSProperty::Get(id),
+ DecodeIsPresentationAttribute(position));
+}
+
+// https://drafts.csswg.org/css-cascade-4/#default
+CascadeOrigin TargetOriginForRevert(CascadeOrigin origin) {
+ switch (origin) {
+ case CascadeOrigin::kNone:
+ case CascadeOrigin::kTransition:
+ NOTREACHED();
+ return CascadeOrigin::kNone;
+ case CascadeOrigin::kUserAgent:
+ return CascadeOrigin::kNone;
+ case CascadeOrigin::kUser:
+ return CascadeOrigin::kUserAgent;
+ case CascadeOrigin::kAuthor:
+ case CascadeOrigin::kAnimation:
+ return CascadeOrigin::kUser;
+ }
+}
+
+CSSPropertyID UnvisitedID(CSSPropertyID id) {
+ if (id == CSSPropertyID::kVariable)
+ return id;
+ const CSSProperty& property = CSSProperty::Get(id);
+ if (!property.IsVisited())
+ return id;
+ return property.GetUnvisitedProperty()->PropertyID();
}
} // namespace
@@ -114,6 +137,8 @@ void StyleCascade::Apply(CascadeFilter filter) {
CascadeResolver resolver(filter, ++generation_);
+ ApplyCascadeAffecting(resolver);
+
// Affects the computed value of 'color', hence needs to happen before
// high-priority properties.
LookupAndApply(GetCSSPropertyColorScheme(), resolver);
@@ -129,12 +154,27 @@ void StyleCascade::Apply(CascadeFilter filter) {
ApplyMatchResult(resolver);
ApplyInterpolations(resolver);
- if (map_.Find(CSSPropertyName(CSSPropertyID::kWebkitAppearance)) &&
- !resolver.filter_.Rejects(GetCSSPropertyWebkitAppearance()) &&
+ if (map_.Find(CSSPropertyName(CSSPropertyID::kAppearance)) &&
+ !resolver.filter_.Rejects(GetCSSPropertyAppearance()) &&
state_.Style()->HasAppearance()) {
- state_.Style()->SetHasAuthorBackground(HasAuthorBackground());
- state_.Style()->SetHasAuthorBorder(HasAuthorBorder());
+ CSSProperty::Flags flags = resolver.AuthorFlags();
+ state_.Style()->SetHasAuthorBackground(flags & CSSProperty::kBackground);
+ state_.Style()->SetHasAuthorBorder(flags & CSSProperty::kBorder);
+ }
+}
+
+std::unique_ptr<CSSBitset> StyleCascade::GetImportantSet() {
+ AnalyzeIfNeeded();
+ if (!map_.HasImportant())
+ return nullptr;
+ auto set = std::make_unique<CSSBitset>();
+ for (CSSPropertyID id : map_.NativeBitset()) {
+ // We use the unvisited ID because visited/unvisited colors are currently
+ // interpolated together.
+ // TODO(crbug.com/1062217): Interpolate visited colors separately
+ set->Or(UnvisitedID(id), map_.At(CSSPropertyName(id)).IsImportant());
}
+ return set;
}
void StyleCascade::Reset() {
@@ -142,14 +182,17 @@ void StyleCascade::Reset() {
match_result_.Reset();
interpolations_.Reset();
generation_ = 0;
+ depends_on_cascade_affecting_property_ = false;
}
const CSSValue* StyleCascade::Resolve(const CSSPropertyName& name,
const CSSValue& value,
+ CascadeOrigin origin,
CascadeResolver& resolver) {
CSSPropertyRef ref(name, state_.GetDocument());
- const CSSValue* resolved = Resolve(ref.GetProperty(), value, resolver);
+ const CSSValue* resolved =
+ Resolve(ResolveSurrogate(ref.GetProperty()), value, origin, resolver);
DCHECK(resolved);
@@ -166,14 +209,16 @@ void StyleCascade::AnalyzeIfNeeded() {
}
if (needs_interpolations_analyze_) {
AnalyzeInterpolations();
- needs_interpolations_analyze_ = true;
+ needs_interpolations_analyze_ = false;
}
}
void StyleCascade::AnalyzeMatchResult() {
for (auto e : match_result_.Expansions(GetDocument(), CascadeFilter())) {
- for (; !e.AtEnd(); e.Next())
- map_.Add(e.Name(), e.Priority());
+ for (; !e.AtEnd(); e.Next()) {
+ const CSSProperty& property = ResolveSurrogate(e.Property());
+ map_.Add(property.GetCSSPropertyName(), e.Priority());
+ }
}
}
@@ -181,16 +226,16 @@ void StyleCascade::AnalyzeInterpolations() {
const auto& entries = interpolations_.GetEntries();
for (size_t i = 0; i < entries.size(); ++i) {
for (const auto& active_interpolation : *entries[i].map) {
+ auto name = active_interpolation.key.GetCSSPropertyName();
uint32_t position = EncodeInterpolationPosition(
- i, active_interpolation.key.IsPresentationAttribute());
+ name.Id(), i, active_interpolation.key.IsPresentationAttribute());
CascadePriority priority(entries[i].origin, false, 0, position);
- auto name = active_interpolation.key.GetCSSPropertyName();
CSSPropertyRef ref(name, GetDocument());
DCHECK(ref.IsValid());
- const CSSProperty& property = ref.GetProperty();
+ const CSSProperty& property = ResolveSurrogate(ref.GetProperty());
- map_.Add(name, priority);
+ map_.Add(property.GetCSSPropertyName(), priority);
// Since an interpolation for an unvisited property also causes an
// interpolation of the visited property, add the visited property to
@@ -202,6 +247,35 @@ void StyleCascade::AnalyzeInterpolations() {
}
}
+void StyleCascade::Reanalyze() {
+ map_.Reset();
+ generation_ = 0;
+ depends_on_cascade_affecting_property_ = false;
+
+ needs_match_result_analyze_ = true;
+ needs_interpolations_analyze_ = true;
+ AnalyzeIfNeeded();
+}
+
+void StyleCascade::ApplyCascadeAffecting(CascadeResolver& resolver) {
+ // During the initial call to Analyze, we speculatively assume that the
+ // direction/writing-mode inherited from the parent will be the final
+ // direction/writing-mode. If either property ends up with another value,
+ // our assumption was incorrect, and we have to Reanalyze with the correct
+ // values on ComputedStyle.
+ auto direction = state_.Style()->Direction();
+ auto writing_mode = state_.Style()->GetWritingMode();
+
+ LookupAndApply(GetCSSPropertyDirection(), resolver);
+ LookupAndApply(GetCSSPropertyWritingMode(), resolver);
+
+ if (depends_on_cascade_affecting_property_ &&
+ (direction != state_.Style()->Direction() ||
+ writing_mode != state_.Style()->GetWritingMode())) {
+ Reanalyze();
+ }
+}
+
void StyleCascade::ApplyHighPriority(CascadeResolver& resolver) {
uint64_t bits = map_.HighPriorityBits();
@@ -262,16 +336,13 @@ void StyleCascade::ApplyMatchResult(CascadeResolver& resolver) {
for (auto e : match_result_.Expansions(GetDocument(), resolver.filter_)) {
for (; !e.AtEnd(); e.Next()) {
auto priority = CascadePriority(e.Priority(), resolver.generation_);
- CascadePriority* p = map_.Find(e.Name());
+ const CSSProperty& property = ResolveSurrogate(e.Property());
+ CascadePriority* p = map_.Find(property.GetCSSPropertyName());
if (!p || *p >= priority)
continue;
*p = priority;
- const CSSProperty& property = e.Property();
- if (property.IsSurrogate()) {
- ApplySurrogate(property, priority, resolver);
- continue;
- }
- const CSSValue* value = Resolve(property, e.Value(), resolver);
+ CascadeOrigin origin = priority.GetOrigin();
+ const CSSValue* value = Resolve(property, e.Value(), origin, resolver);
StyleBuilder::ApplyProperty(property, state_, *value);
}
}
@@ -291,17 +362,18 @@ void StyleCascade::ApplyInterpolationMap(const ActiveInterpolationsMap& map,
CascadeResolver& resolver) {
for (const auto& entry : map) {
auto name = entry.key.GetCSSPropertyName();
- uint32_t position =
- EncodeInterpolationPosition(index, entry.key.IsPresentationAttribute());
+ uint32_t position = EncodeInterpolationPosition(
+ name.Id(), index, entry.key.IsPresentationAttribute());
CascadePriority priority(origin, false, 0, position);
priority = CascadePriority(priority, resolver.generation_);
CSSPropertyRef ref(name, GetDocument());
- const CSSProperty& property = ref.GetProperty();
- if (resolver.filter_.Rejects(property))
+ if (resolver.filter_.Rejects(ref.GetProperty()))
continue;
- CascadePriority* p = map_.Find(name);
+ const CSSProperty& property = ResolveSurrogate(ref.GetProperty());
+
+ CascadePriority* p = map_.Find(property.GetCSSPropertyName());
if (!p || *p >= priority) {
if (p->IsImportant())
state_.SetHasImportantOverrides();
@@ -309,11 +381,6 @@ void StyleCascade::ApplyInterpolationMap(const ActiveInterpolationsMap& map,
}
*p = priority;
- if (property.IsSurrogate()) {
- ApplySurrogate(property, priority, resolver);
- continue;
- }
-
ApplyInterpolation(property, priority, entry.value, resolver);
}
}
@@ -323,6 +390,8 @@ void StyleCascade::ApplyInterpolation(
CascadePriority priority,
const ActiveInterpolations& interpolations,
CascadeResolver& resolver) {
+ DCHECK(!property.IsSurrogate());
+
const Interpolation& interpolation = *interpolations.front();
if (IsA<InvalidatableInterpolation>(interpolation)) {
CSSInterpolationTypesMap map(state_.GetDocument().GetPropertyRegistry(),
@@ -333,9 +402,6 @@ void StyleCascade::ApplyInterpolation(
To<TransitionInterpolation>(interpolation).Apply(state_);
}
- if (property.AffectsFont())
- state_.SetHasFontAffectingAnimation();
-
// Applying a color property interpolation will also unconditionally apply
// the -internal-visited- counterpart (see CSSColorInterpolationType::
// ApplyStandardPropertyValue). To make sure !important rules in :visited
@@ -357,29 +423,6 @@ void StyleCascade::ApplyInterpolation(
}
}
-void StyleCascade::ApplySurrogate(const CSSProperty& surrogate,
- CascadePriority surrogate_priority,
- CascadeResolver& resolver) {
- DCHECK(surrogate.IsSurrogate());
-
- const CSSProperty& original = SurrogateFor(surrogate);
- CascadePriority* original_priority = map_.Find(original.GetCSSPropertyName());
-
- if (original_priority) {
- if (surrogate_priority < *original_priority) {
- // The original has a higher priority, so skip the surrogate property.
- return;
- }
-
- // The surrogate has a higher priority, so skip the original property.
- // The original might have been applied already, but that doesn't matter,
- // as we're about to overwrite it.
- resolver.MarkApplied(original_priority);
- }
-
- LookupAndApplyValue(surrogate, surrogate_priority, resolver);
-}
-
void StyleCascade::LookupAndApply(const CSSPropertyName& name,
CascadeResolver& resolver) {
CSSPropertyRef ref(name, state_.GetDocument());
@@ -389,6 +432,8 @@ void StyleCascade::LookupAndApply(const CSSPropertyName& name,
void StyleCascade::LookupAndApply(const CSSProperty& property,
CascadeResolver& resolver) {
+ DCHECK(!property.IsSurrogate());
+
CSSPropertyName name = property.GetCSSPropertyName();
DCHECK(!resolver.IsLocked(name));
@@ -402,10 +447,6 @@ void StyleCascade::LookupAndApply(const CSSProperty& property,
if (resolver.filter_.Rejects(property))
return;
- if (property.IsSurrogate()) {
- ApplySurrogate(property, priority, resolver);
- return;
- }
LookupAndApplyValue(property, priority, resolver);
}
@@ -413,6 +454,8 @@ void StyleCascade::LookupAndApply(const CSSProperty& property,
void StyleCascade::LookupAndApplyValue(const CSSProperty& property,
CascadePriority priority,
CascadeResolver& resolver) {
+ DCHECK(!property.IsSurrogate());
+
if (priority.GetOrigin() < CascadeOrigin::kAnimation)
LookupAndApplyDeclaration(property, priority, resolver);
else if (priority.GetOrigin() >= CascadeOrigin::kAnimation)
@@ -422,10 +465,11 @@ void StyleCascade::LookupAndApplyValue(const CSSProperty& property,
void StyleCascade::LookupAndApplyDeclaration(const CSSProperty& property,
CascadePriority priority,
CascadeResolver& resolver) {
+ DCHECK(!property.IsSurrogate());
DCHECK(priority.GetOrigin() < CascadeOrigin::kAnimation);
const CSSValue* value = ValueAt(match_result_, priority.GetPosition());
DCHECK(value);
- value = Resolve(property, *value, resolver);
+ value = Resolve(property, *value, priority.GetOrigin(), resolver);
DCHECK(!value->IsVariableReferenceValue());
DCHECK(!value->IsPendingSubstitutionValue());
StyleBuilder::ApplyProperty(property, state_, *value);
@@ -434,6 +478,8 @@ void StyleCascade::LookupAndApplyDeclaration(const CSSProperty& property,
void StyleCascade::LookupAndApplyInterpolation(const CSSProperty& property,
CascadePriority priority,
CascadeResolver& resolver) {
+ DCHECK(!property.IsSurrogate());
+
// Interpolations for -internal-visited properties are applied via the
// interpolation for the main (unvisited) property, so we don't need to
// apply it twice.
@@ -493,9 +539,14 @@ StyleCascade::TokenSequence::BuildVariableData() {
const CSSValue* StyleCascade::Resolve(const CSSProperty& property,
const CSSValue& value,
+ CascadeOrigin origin,
CascadeResolver& resolver) {
+ DCHECK(!property.IsSurrogate());
+ if (value.IsRevertValue())
+ return ResolveRevert(property, origin, resolver);
+ resolver.CollectAuthorFlags(property, origin);
if (const auto* v = DynamicTo<CSSCustomPropertyDeclaration>(value))
- return ResolveCustomProperty(property, *v, resolver);
+ return ResolveCustomProperty(property, *v, origin, resolver);
if (const auto* v = DynamicTo<CSSVariableReferenceValue>(value))
return ResolveVariableReference(property, *v, resolver);
if (const auto* v = DynamicTo<cssvalue::CSSPendingSubstitutionValue>(value))
@@ -506,13 +557,19 @@ const CSSValue* StyleCascade::Resolve(const CSSProperty& property,
const CSSValue* StyleCascade::ResolveCustomProperty(
const CSSProperty& property,
const CSSCustomPropertyDeclaration& decl,
+ CascadeOrigin origin,
CascadeResolver& resolver) {
- DCHECK(!resolver.IsLocked(property));
- CascadeResolver::AutoLock lock(property, resolver);
+ DCHECK(!property.IsSurrogate());
// TODO(andruud): Don't transport css-wide keywords in this value.
- if (!decl.Value())
+ if (!decl.Value()) {
+ if (decl.IsRevert())
+ return ResolveRevert(property, origin, resolver);
return &decl;
+ }
+
+ DCHECK(!resolver.IsLocked(property));
+ CascadeResolver::AutoLock lock(property, resolver);
scoped_refptr<CSSVariableData> data = decl.Value();
@@ -522,6 +579,8 @@ const CSSValue* StyleCascade::ResolveCustomProperty(
if (HasFontSizeDependency(To<CustomProperty>(property), data.get()))
resolver.DetectCycle(GetCSSPropertyFontSize());
+ state_.Style()->SetHasVariableDeclaration();
+
if (resolver.InCycle())
return CSSInvalidVariableValue::Create();
@@ -539,6 +598,7 @@ const CSSValue* StyleCascade::ResolveVariableReference(
const CSSProperty& property,
const CSSVariableReferenceValue& value,
CascadeResolver& resolver) {
+ DCHECK(!property.IsSurrogate());
DCHECK(!resolver.IsLocked(property));
CascadeResolver::AutoLock lock(property, resolver);
@@ -554,7 +614,7 @@ const CSSValue* StyleCascade::ResolveVariableReference(
if (ResolveTokensInto(data->Tokens(), resolver, sequence)) {
if (const auto* parsed = Parse(property, sequence.TokenRange(), context))
- return parsed;
+ return TreatRevertAsUnset(parsed);
}
return cssvalue::CSSUnsetValue::Create();
@@ -564,6 +624,7 @@ const CSSValue* StyleCascade::ResolvePendingSubstitution(
const CSSProperty& property,
const cssvalue::CSSPendingSubstitutionValue& value,
CascadeResolver& resolver) {
+ DCHECK(!property.IsSurrogate());
DCHECK(!resolver.IsLocked(property));
CascadeResolver::AutoLock lock(property, resolver);
@@ -616,14 +677,41 @@ const CSSValue* StyleCascade::ResolvePendingSubstitution(
const CSSProperty& longhand = CSSProperty::Get(parsed_properties[i].Id());
const CSSValue* parsed = parsed_properties[i].Value();
- if (unvisited_property == &longhand)
- return parsed;
+ // When using var() in a css-logical shorthand (e.g. margin-inline),
+ // the longhands here will also be logical.
+ if (unvisited_property == &ResolveSurrogate(longhand))
+ return TreatRevertAsUnset(parsed);
}
NOTREACHED();
return cssvalue::CSSUnsetValue::Create();
}
+const CSSValue* StyleCascade::ResolveRevert(const CSSProperty& property,
+ CascadeOrigin origin,
+ CascadeResolver& resolver) {
+ GetDocument().CountUse(WebFeature::kCSSKeywordRevert);
+
+ CascadeOrigin target_origin = TargetOriginForRevert(origin);
+
+ switch (target_origin) {
+ case CascadeOrigin::kTransition:
+ case CascadeOrigin::kNone:
+ return cssvalue::CSSUnsetValue::Create();
+ case CascadeOrigin::kUserAgent:
+ case CascadeOrigin::kUser:
+ case CascadeOrigin::kAuthor:
+ case CascadeOrigin::kAnimation: {
+ CascadePriority* p =
+ map_.Find(property.GetCSSPropertyName(), target_origin);
+ if (!p)
+ return cssvalue::CSSUnsetValue::Create();
+ return Resolve(property, *ValueAt(match_result_, p->GetPosition()),
+ target_origin, resolver);
+ }
+ }
+}
+
scoped_refptr<CSSVariableData> StyleCascade::ResolveVariableData(
CSSVariableData* data,
CascadeResolver& resolver) {
@@ -789,66 +877,31 @@ void StyleCascade::MarkIsReferenced(const CustomProperty& property) {
if (!property.IsRegistered())
return;
const AtomicString& name = property.GetPropertyNameAtomicString();
- state_.GetDocument().GetPropertyRegistry()->MarkReferenced(name);
+ state_.GetDocument().EnsurePropertyRegistry().MarkReferenced(name);
}
void StyleCascade::MarkHasVariableReference(const CSSProperty& property) {
if (!property.IsInherited())
state_.Style()->SetHasVariableReferenceFromNonInheritedProperty();
+ state_.Style()->SetHasVariableReference();
}
const Document& StyleCascade::GetDocument() const {
return state_.GetDocument();
}
-const CSSProperty& StyleCascade::SurrogateFor(
- const CSSProperty& surrogate) const {
- DCHECK(surrogate.IsSurrogate());
- const CSSProperty* original = surrogate.SurrogateFor(
+const CSSProperty& StyleCascade::ResolveSurrogate(const CSSProperty& property) {
+ if (!property.IsSurrogate())
+ return property;
+ // This marks the cascade as dependent on cascade-affecting properties
+ // even for simple surrogates like -webkit-writing-mode, but there isn't
+ // currently a flag to distinguish such surrogates from e.g. css-logical
+ // properties.
+ depends_on_cascade_affecting_property_ = true;
+ const CSSProperty* original = property.SurrogateFor(
state_.Style()->Direction(), state_.Style()->GetWritingMode());
DCHECK(original);
return *original;
}
-bool StyleCascade::HasAuthorDeclaration(const CSSProperty& property) const {
- return map_.At(property.GetCSSPropertyName()).GetOrigin() ==
- CascadeOrigin::kAuthor;
-}
-
-bool StyleCascade::HasAuthorBorder() const {
- return HasAuthorDeclaration(GetCSSPropertyBorderBottomColor()) ||
- HasAuthorDeclaration(GetCSSPropertyBorderBottomLeftRadius()) ||
- HasAuthorDeclaration(GetCSSPropertyBorderBottomRightRadius()) ||
- HasAuthorDeclaration(GetCSSPropertyBorderBottomStyle()) ||
- HasAuthorDeclaration(GetCSSPropertyBorderBottomWidth()) ||
- HasAuthorDeclaration(GetCSSPropertyBorderImageOutset()) ||
- HasAuthorDeclaration(GetCSSPropertyBorderImageRepeat()) ||
- HasAuthorDeclaration(GetCSSPropertyBorderImageSlice()) ||
- HasAuthorDeclaration(GetCSSPropertyBorderImageSource()) ||
- HasAuthorDeclaration(GetCSSPropertyBorderImageWidth()) ||
- HasAuthorDeclaration(GetCSSPropertyBorderLeftColor()) ||
- HasAuthorDeclaration(GetCSSPropertyBorderLeftStyle()) ||
- HasAuthorDeclaration(GetCSSPropertyBorderLeftWidth()) ||
- HasAuthorDeclaration(GetCSSPropertyBorderRightColor()) ||
- HasAuthorDeclaration(GetCSSPropertyBorderRightStyle()) ||
- HasAuthorDeclaration(GetCSSPropertyBorderRightWidth()) ||
- HasAuthorDeclaration(GetCSSPropertyBorderTopColor()) ||
- HasAuthorDeclaration(GetCSSPropertyBorderTopLeftRadius()) ||
- HasAuthorDeclaration(GetCSSPropertyBorderTopRightRadius()) ||
- HasAuthorDeclaration(GetCSSPropertyBorderTopStyle()) ||
- HasAuthorDeclaration(GetCSSPropertyBorderTopWidth());
-}
-
-bool StyleCascade::HasAuthorBackground() const {
- return HasAuthorDeclaration(GetCSSPropertyBackgroundAttachment()) ||
- HasAuthorDeclaration(GetCSSPropertyBackgroundBlendMode()) ||
- HasAuthorDeclaration(GetCSSPropertyBackgroundClip()) ||
- HasAuthorDeclaration(GetCSSPropertyBackgroundColor()) ||
- HasAuthorDeclaration(GetCSSPropertyBackgroundImage()) ||
- HasAuthorDeclaration(GetCSSPropertyBackgroundOrigin()) ||
- HasAuthorDeclaration(GetCSSPropertyBackgroundPositionX()) ||
- HasAuthorDeclaration(GetCSSPropertyBackgroundPositionY()) ||
- HasAuthorDeclaration(GetCSSPropertyBackgroundSize());
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/resolver/style_cascade.h b/chromium/third_party/blink/renderer/core/css/resolver/style_cascade.h
index 5b4fe46d901..66636e27dad 100644
--- a/chromium/third_party/blink/renderer/core/css/resolver/style_cascade.h
+++ b/chromium/third_party/blink/renderer/core/css/resolver/style_cascade.h
@@ -11,6 +11,7 @@
#include "third_party/blink/renderer/core/css/css_property_value.h"
#include "third_party/blink/renderer/core/css/parser/css_parser_token.h"
#include "third_party/blink/renderer/core/css/parser/css_parser_token_range.h"
+#include "third_party/blink/renderer/core/css/properties/css_bitset.h"
#include "third_party/blink/renderer/core/css/properties/css_property.h"
#include "third_party/blink/renderer/core/css/resolver/cascade_filter.h"
#include "third_party/blink/renderer/core/css/resolver/cascade_interpolations.h"
@@ -87,6 +88,14 @@ class CORE_EXPORT StyleCascade {
// provide a different filter.
void Apply(CascadeFilter = CascadeFilter());
+ // Returns a CSSBitset containing the !important declarations (analyzing
+ // if needed). If there are no !important declarations, returns nullptr.
+ //
+ // Note that this function does not return any set bits for -internal-visited-
+ // properties. Instead, !important -internal-visited-* declarations cause
+ // the corresponding unvisited properties to be set in the return value.
+ std::unique_ptr<CSSBitset> GetImportantSet();
+
// Resets the cascade to its initial state. Note that this does not undo
// any changes already applied to the StyleResolverState/ComputedStyle.
void Reset();
@@ -102,6 +111,7 @@ class CORE_EXPORT StyleCascade {
// See documentation the other Resolve* functions for what resolve means.
const CSSValue* Resolve(const CSSPropertyName&,
const CSSValue&,
+ CascadeOrigin,
CascadeResolver&);
private:
@@ -124,6 +134,16 @@ class CORE_EXPORT StyleCascade {
void AnalyzeMatchResult();
void AnalyzeInterpolations();
+ // Clears the CascadeMap and other state, and analyzes the MatchResult/
+ // interpolations again.
+ void Reanalyze();
+
+ // Some properties are "cascade affecting", in the sense that their computed
+ // value actually affects cascade behavior. For example, css-logical
+ // properties change their cascade behavior depending on the computed value
+ // of direction/writing-mode.
+ void ApplyCascadeAffecting(CascadeResolver&);
+
// Applies kHighPropertyPriority properties.
//
// In theory, it would be possible for each property/value that contains
@@ -154,13 +174,6 @@ class CORE_EXPORT StyleCascade {
CascadePriority,
const ActiveInterpolations&,
CascadeResolver&);
- // Surrogates (such as css-logical properties) require special handling, since
- // both the surrogate and the original property exist in the cascade at the
- // same time. For example, 'inline-size' and 'width' may both exist in the
- // CascadeMap, and the winner must be determined Apply-time, since we don't
- // know which physical property 'inline-size' corresponds to before
- // 'writing-mode' and 'direction' have been applied.
- void ApplySurrogate(const CSSProperty&, CascadePriority, CascadeResolver&);
// Looks up a value with random access, and applies it.
void LookupAndApply(const CSSPropertyName&, CascadeResolver&);
@@ -245,9 +258,11 @@ class CORE_EXPORT StyleCascade {
const CSSValue* Resolve(const CSSProperty&,
const CSSValue&,
+ CascadeOrigin,
CascadeResolver&);
const CSSValue* ResolveCustomProperty(const CSSProperty&,
const CSSCustomPropertyDeclaration&,
+ CascadeOrigin,
CascadeResolver&);
const CSSValue* ResolveVariableReference(const CSSProperty&,
const CSSVariableReferenceValue&,
@@ -255,6 +270,9 @@ class CORE_EXPORT StyleCascade {
const CSSValue* ResolvePendingSubstitution(const CSSProperty&,
const CSSPendingSubstitutionValue&,
CascadeResolver&);
+ const CSSValue* ResolveRevert(const CSSProperty&,
+ CascadeOrigin,
+ CascadeResolver&);
scoped_refptr<CSSVariableData> ResolveVariableData(CSSVariableData*,
CascadeResolver&);
@@ -293,11 +311,7 @@ class CORE_EXPORT StyleCascade {
void MarkHasVariableReference(const CSSProperty&);
const Document& GetDocument() const;
- const CSSProperty& SurrogateFor(const CSSProperty& surrogate) const;
-
- bool HasAuthorDeclaration(const CSSProperty&) const;
- bool HasAuthorBorder() const;
- bool HasAuthorBackground() const;
+ const CSSProperty& ResolveSurrogate(const CSSProperty& surrogate);
StyleResolverState& state_;
MatchResult match_result_;
@@ -344,6 +358,10 @@ class CORE_EXPORT StyleCascade {
bool needs_match_result_analyze_ = false;
bool needs_interpolations_analyze_ = false;
+ // A cascade-affecting property is for example 'direction', since the
+ // computed value of the property affects how e.g. margin-inline-start
+ // (and other css-logical properties) cascade.
+ bool depends_on_cascade_affecting_property_ = false;
DISALLOW_COPY_AND_ASSIGN(StyleCascade);
};
diff --git a/chromium/third_party/blink/renderer/core/css/resolver/style_cascade_test.cc b/chromium/third_party/blink/renderer/core/css/resolver/style_cascade_test.cc
index 87269c3ba0d..9d8bbcdf9bd 100644
--- a/chromium/third_party/blink/renderer/core/css/resolver/style_cascade_test.cc
+++ b/chromium/third_party/blink/renderer/core/css/resolver/style_cascade_test.cc
@@ -50,6 +50,36 @@ using Origin = CascadeOrigin;
using Priority = CascadePriority;
using UnitType = CSSPrimitiveValue::UnitType;
+class TestCascadeResolver {
+ STACK_ALLOCATED();
+
+ public:
+ explicit TestCascadeResolver(Document& document, uint8_t generation = 0)
+ : document_(document), resolver_(CascadeFilter(), generation) {}
+ bool InCycle() const { return resolver_.InCycle(); }
+ bool DetectCycle(String name) {
+ CSSPropertyRef ref(name, document_);
+ DCHECK(ref.IsValid());
+ const CSSProperty& property = ref.GetProperty();
+ return resolver_.DetectCycle(property);
+ }
+ wtf_size_t CycleDepth() const { return resolver_.cycle_depth_; }
+ void MarkApplied(CascadePriority* priority) {
+ resolver_.MarkApplied(priority);
+ }
+ void MarkUnapplied(CascadePriority* priority) {
+ resolver_.MarkUnapplied(priority);
+ }
+ uint8_t GetGeneration() { return resolver_.generation_; }
+ CascadeResolver& InnerResolver() { return resolver_; }
+
+ private:
+ friend class TestCascadeAutoLock;
+
+ Document& document_;
+ CascadeResolver resolver_;
+};
+
class TestCascade {
STACK_ALLOCATED();
@@ -97,6 +127,17 @@ class TestCascade {
cascade_.Apply(filter);
}
+ void ApplySingle(const CSSProperty& property) {
+ EnsureAtLeast(CascadeOrigin::kAuthor);
+ cascade_.AnalyzeIfNeeded();
+ TestCascadeResolver resolver(GetDocument(), ++cascade_.generation_);
+ cascade_.LookupAndApply(property, resolver.InnerResolver());
+ }
+
+ std::unique_ptr<CSSBitset> GetImportantSet() {
+ return cascade_.GetImportantSet();
+ }
+
String ComputedValue(String name) const {
CSSPropertyRef ref(name, GetDocument());
DCHECK(ref.IsValid());
@@ -139,6 +180,16 @@ class TestCascade {
void Reset() { cascade_.Reset(); }
+ bool NeedsMatchResultAnalyze() const {
+ return cascade_.needs_match_result_analyze_;
+ }
+ bool NeedsInterpolationsAnalyze() const {
+ return cascade_.needs_interpolations_analyze_;
+ }
+ bool DependsOnCascadeAffectingProperty() const {
+ return cascade_.depends_on_cascade_affecting_property_;
+ }
+
private:
Document& GetDocument() const { return state_.GetDocument(); }
Element* Body() const { return GetDocument().body(); }
@@ -204,35 +255,6 @@ class TestCascade {
StyleCascade cascade_;
};
-class TestCascadeResolver {
- STACK_ALLOCATED();
-
- public:
- explicit TestCascadeResolver(Document& document, uint8_t generation = 0)
- : document_(document), resolver_(CascadeFilter(), generation) {}
- bool InCycle() const { return resolver_.InCycle(); }
- bool DetectCycle(String name) {
- CSSPropertyRef ref(name, document_);
- DCHECK(ref.IsValid());
- const CSSProperty& property = ref.GetProperty();
- return resolver_.DetectCycle(property);
- }
- wtf_size_t CycleDepth() const { return resolver_.cycle_depth_; }
- void MarkApplied(CascadePriority* priority) {
- resolver_.MarkApplied(priority);
- }
- void MarkUnapplied(CascadePriority* priority) {
- resolver_.MarkUnapplied(priority);
- }
- uint8_t GetGeneration() { return resolver_.generation_; }
-
- private:
- friend class TestCascadeAutoLock;
-
- Document& document_;
- CascadeResolver resolver_;
-};
-
class TestCascadeAutoLock {
STACK_ALLOCATED();
@@ -245,9 +267,12 @@ class TestCascadeAutoLock {
CascadeResolver::AutoLock lock_;
};
-class StyleCascadeTest : public PageTestBase, private ScopedCSSCascadeForTest {
+class StyleCascadeTest : public PageTestBase,
+ private ScopedCSSCascadeForTest,
+ private ScopedCSSRevertForTest {
public:
- StyleCascadeTest() : ScopedCSSCascadeForTest(true) {}
+ StyleCascadeTest()
+ : ScopedCSSCascadeForTest(true), ScopedCSSRevertForTest(true) {}
CSSStyleSheet* CreateSheet(const String& css_text) {
auto* init = MakeGarbageCollected<CSSStyleSheetInit>();
@@ -581,6 +606,17 @@ TEST_F(StyleCascadeTest, ApplyingPendingSubstitutionLast) {
EXPECT_EQ("4px", cascade.ComputedValue("margin-left"));
}
+TEST_F(StyleCascadeTest, PendingSubstitutionInLogicalShorthand) {
+ TestCascade cascade(GetDocument());
+ cascade.Add("margin-inline:var(--x)");
+ cascade.Add("--x:10px 20px");
+ cascade.Add("direction:rtl");
+ cascade.Apply();
+
+ EXPECT_EQ("20px", cascade.ComputedValue("margin-left"));
+ EXPECT_EQ("10px", cascade.ComputedValue("margin-right"));
+}
+
TEST_F(StyleCascadeTest, ResolverDetectCycle) {
TestCascade cascade(GetDocument());
TestCascadeResolver resolver(GetDocument());
@@ -1194,6 +1230,505 @@ TEST_F(StyleCascadeTest, Unset) {
EXPECT_EQ("foo", cascade.ComputedValue("--x"));
}
+TEST_F(StyleCascadeTest, RevertUA) {
+ TestCascade cascade(GetDocument());
+ cascade.Add("display:block", CascadeOrigin::kUserAgent);
+ cascade.Add("display:revert", CascadeOrigin::kUserAgent);
+
+ cascade.Add("display:block", CascadeOrigin::kUser);
+ cascade.Add("display:revert", CascadeOrigin::kUser);
+
+ cascade.Add("display:block", CascadeOrigin::kAuthor);
+ cascade.Add("display:revert", CascadeOrigin::kAuthor);
+
+ cascade.Apply();
+
+ EXPECT_EQ("inline", cascade.ComputedValue("display"));
+}
+
+TEST_F(StyleCascadeTest, RevertStandardProperty) {
+ TestCascade cascade(GetDocument());
+ cascade.Add("left:10px", CascadeOrigin::kUserAgent);
+ cascade.Add("right:10px", CascadeOrigin::kUserAgent);
+
+ cascade.Add("right:20px", CascadeOrigin::kUser);
+ cascade.Add("right:revert", CascadeOrigin::kUser);
+ cascade.Add("top:20px", CascadeOrigin::kUser);
+ cascade.Add("bottom:20px", CascadeOrigin::kUser);
+
+ cascade.Add("bottom:30px", CascadeOrigin::kAuthor);
+ cascade.Add("bottom:revert", CascadeOrigin::kAuthor);
+ cascade.Add("left:30px", CascadeOrigin::kAuthor);
+ cascade.Add("left:revert", CascadeOrigin::kAuthor);
+ cascade.Add("right:revert", CascadeOrigin::kAuthor);
+ cascade.Apply();
+
+ EXPECT_EQ("20px", cascade.ComputedValue("top"));
+ EXPECT_EQ("10px", cascade.ComputedValue("right"));
+ EXPECT_EQ("20px", cascade.ComputedValue("bottom"));
+ EXPECT_EQ("10px", cascade.ComputedValue("left"));
+}
+
+TEST_F(StyleCascadeTest, RevertCustomProperty) {
+ TestCascade cascade(GetDocument());
+ cascade.Add("--x:10px", CascadeOrigin::kUser);
+
+ cascade.Add("--y:fail", CascadeOrigin::kAuthor);
+
+ cascade.Add("--x:revert", CascadeOrigin::kAuthor);
+ cascade.Add("--y:revert", CascadeOrigin::kAuthor);
+
+ cascade.Apply();
+
+ EXPECT_EQ("10px", cascade.ComputedValue("--x"));
+ EXPECT_FALSE(cascade.ComputedValue("--y"));
+}
+
+TEST_F(StyleCascadeTest, RevertChain) {
+ TestCascade cascade(GetDocument());
+ cascade.Add("width:10px", CascadeOrigin::kUserAgent);
+
+ cascade.Add("width:revert", CascadeOrigin::kUser);
+ cascade.Add("--x:revert", CascadeOrigin::kUser);
+
+ cascade.Add("width:revert", CascadeOrigin::kAuthor);
+ cascade.Add("--x:revert", CascadeOrigin::kAuthor);
+ cascade.Apply();
+
+ EXPECT_EQ("10px", cascade.ComputedValue("width"));
+ EXPECT_FALSE(cascade.ComputedValue("--x"));
+}
+
+TEST_F(StyleCascadeTest, RevertFromAuthorToUA) {
+ TestCascade cascade(GetDocument());
+ cascade.Add("width:10px", CascadeOrigin::kUserAgent);
+ cascade.Add("height:10px", CascadeOrigin::kUserAgent);
+
+ cascade.Add("width:20px", CascadeOrigin::kAuthor);
+ cascade.Add("height:20px", CascadeOrigin::kAuthor);
+ cascade.Add("width:revert", CascadeOrigin::kAuthor);
+ cascade.Add("height:revert", CascadeOrigin::kAuthor);
+ cascade.Apply();
+
+ EXPECT_EQ("10px", cascade.ComputedValue("width"));
+ EXPECT_EQ("10px", cascade.ComputedValue("height"));
+}
+
+TEST_F(StyleCascadeTest, RevertInitialFallback) {
+ TestCascade cascade(GetDocument());
+ cascade.Add("width:20px", CascadeOrigin::kAuthor);
+ cascade.Add("width:revert", CascadeOrigin::kAuthor);
+ cascade.Apply();
+
+ EXPECT_EQ("auto", cascade.ComputedValue("width"));
+}
+
+TEST_F(StyleCascadeTest, RevertInheritedFallback) {
+ TestCascade parent(GetDocument());
+ parent.Add("color", "red");
+ parent.Apply();
+
+ TestCascade cascade(GetDocument());
+ cascade.InheritFrom(parent.TakeStyle());
+ EXPECT_EQ("rgb(255, 0, 0)", cascade.ComputedValue("color"));
+
+ cascade.Add("color:black", CascadeOrigin::kAuthor);
+ cascade.Add("color:revert", CascadeOrigin::kAuthor);
+ cascade.Apply();
+ EXPECT_EQ("rgb(255, 0, 0)", cascade.ComputedValue("color"));
+}
+
+TEST_F(StyleCascadeTest, RevertRegistered) {
+ RegisterProperty(GetDocument(), "--x", "<length>", "0px", false);
+
+ TestCascade cascade(GetDocument());
+ cascade.Add("--x:20px", CascadeOrigin::kUser);
+ cascade.Add("--x:100px", CascadeOrigin::kAuthor);
+ cascade.Add("--x:revert", CascadeOrigin::kAuthor);
+ cascade.Apply();
+
+ EXPECT_EQ("20px", cascade.ComputedValue("--x"));
+}
+
+TEST_F(StyleCascadeTest, RevertRegisteredInitialFallback) {
+ RegisterProperty(GetDocument(), "--x", "<length>", "0px", false);
+
+ TestCascade cascade(GetDocument());
+ cascade.Add("--x:20px", CascadeOrigin::kAuthor);
+ cascade.Add("--x:revert", CascadeOrigin::kAuthor);
+ cascade.Apply();
+
+ EXPECT_EQ("0px", cascade.ComputedValue("--x"));
+}
+
+TEST_F(StyleCascadeTest, RevertRegisteredInheritedFallback) {
+ RegisterProperty(GetDocument(), "--x", "<length>", "0px", true);
+
+ TestCascade parent(GetDocument());
+ parent.Add("--x", "1px");
+ parent.Apply();
+
+ TestCascade cascade(GetDocument());
+ cascade.InheritFrom(parent.TakeStyle());
+ EXPECT_EQ("1px", cascade.ComputedValue("--x"));
+
+ cascade.Add("--x:100px", CascadeOrigin::kAuthor);
+ cascade.Add("--x:revert", CascadeOrigin::kAuthor);
+ cascade.Apply();
+ EXPECT_EQ("1px", cascade.ComputedValue("--x"));
+}
+
+TEST_F(StyleCascadeTest, RevertUASurrogate) {
+ TestCascade cascade(GetDocument());
+
+ // User-agent:
+
+ // Only logical:
+ cascade.Add("inline-size:10px", CascadeOrigin::kUserAgent);
+ cascade.Add("min-inline-size:11px", CascadeOrigin::kUserAgent);
+ // Only physical:
+ cascade.Add("height:12px", CascadeOrigin::kUserAgent);
+ cascade.Add("min-height:13px", CascadeOrigin::kUserAgent);
+ // Physical first:
+ cascade.Add("margin-left:14px", CascadeOrigin::kUserAgent);
+ cascade.Add("padding-left:15px", CascadeOrigin::kUserAgent);
+ cascade.Add("margin-inline-start:16px", CascadeOrigin::kUserAgent);
+ cascade.Add("padding-inline-start:17px", CascadeOrigin::kUserAgent);
+ // Logical first:
+ cascade.Add("margin-inline-end:18px", CascadeOrigin::kUserAgent);
+ cascade.Add("padding-inline-end:19px", CascadeOrigin::kUserAgent);
+ cascade.Add("margin-right:20px", CascadeOrigin::kUserAgent);
+ cascade.Add("padding-right:21px", CascadeOrigin::kUserAgent);
+
+ // Author:
+
+ cascade.Add("width:100px", CascadeOrigin::kAuthor);
+ cascade.Add("height:101px", CascadeOrigin::kAuthor);
+ cascade.Add("margin:102px", CascadeOrigin::kAuthor);
+ cascade.Add("padding:103px", CascadeOrigin::kAuthor);
+ cascade.Add("min-width:104px", CascadeOrigin::kAuthor);
+ cascade.Add("min-height:105px", CascadeOrigin::kAuthor);
+ // Revert via physical:
+ cascade.Add("width:revert", CascadeOrigin::kAuthor);
+ cascade.Add("height:revert", CascadeOrigin::kAuthor);
+ cascade.Add("margin-left:revert", CascadeOrigin::kAuthor);
+ cascade.Add("margin-right:revert", CascadeOrigin::kAuthor);
+ // Revert via logical:
+ cascade.Add("min-inline-size:revert", CascadeOrigin::kAuthor);
+ cascade.Add("min-block-size:revert", CascadeOrigin::kAuthor);
+ cascade.Add("padding-inline-start:revert", CascadeOrigin::kAuthor);
+ cascade.Add("padding-inline-end:revert", CascadeOrigin::kAuthor);
+
+ cascade.Apply();
+
+ EXPECT_EQ("10px", cascade.ComputedValue("width"));
+ EXPECT_EQ("12px", cascade.ComputedValue("height"));
+ EXPECT_EQ("11px", cascade.ComputedValue("min-width"));
+ EXPECT_EQ("13px", cascade.ComputedValue("min-height"));
+ EXPECT_EQ("102px", cascade.ComputedValue("margin-top"));
+ EXPECT_EQ("20px", cascade.ComputedValue("margin-right"));
+ EXPECT_EQ("102px", cascade.ComputedValue("margin-bottom"));
+ EXPECT_EQ("16px", cascade.ComputedValue("margin-left"));
+ EXPECT_EQ("103px", cascade.ComputedValue("padding-top"));
+ EXPECT_EQ("21px", cascade.ComputedValue("padding-right"));
+ EXPECT_EQ("103px", cascade.ComputedValue("padding-bottom"));
+ EXPECT_EQ("17px", cascade.ComputedValue("padding-left"));
+
+ EXPECT_EQ("10px", cascade.ComputedValue("inline-size"));
+ EXPECT_EQ("12px", cascade.ComputedValue("block-size"));
+ EXPECT_EQ("11px", cascade.ComputedValue("min-inline-size"));
+ EXPECT_EQ("13px", cascade.ComputedValue("min-block-size"));
+ EXPECT_EQ("102px", cascade.ComputedValue("margin-block-start"));
+ EXPECT_EQ("20px", cascade.ComputedValue("margin-inline-end"));
+ EXPECT_EQ("102px", cascade.ComputedValue("margin-block-end"));
+ EXPECT_EQ("16px", cascade.ComputedValue("margin-inline-start"));
+ EXPECT_EQ("103px", cascade.ComputedValue("padding-block-start"));
+ EXPECT_EQ("21px", cascade.ComputedValue("padding-inline-end"));
+ EXPECT_EQ("103px", cascade.ComputedValue("padding-block-end"));
+ EXPECT_EQ("17px", cascade.ComputedValue("padding-inline-start"));
+}
+
+TEST_F(StyleCascadeTest, RevertWithImportantPhysical) {
+ TestCascade cascade(GetDocument());
+ cascade.Add("inline-size:10px", CascadeOrigin::kUserAgent);
+ cascade.Add("block-size:11px", CascadeOrigin::kUserAgent);
+
+ cascade.Add("width:100px", CascadeOrigin::kAuthor);
+ cascade.Add("height:101px", CascadeOrigin::kAuthor);
+ cascade.Add("width:revert !important", CascadeOrigin::kAuthor);
+ cascade.Add("inline-size:101px", CascadeOrigin::kAuthor);
+ cascade.Add("block-size:102px", CascadeOrigin::kAuthor);
+ cascade.Add("height:revert !important", CascadeOrigin::kAuthor);
+ cascade.Apply();
+
+ EXPECT_EQ("10px", cascade.ComputedValue("width"));
+ EXPECT_EQ("11px", cascade.ComputedValue("height"));
+ EXPECT_EQ("10px", cascade.ComputedValue("inline-size"));
+ EXPECT_EQ("11px", cascade.ComputedValue("block-size"));
+}
+
+TEST_F(StyleCascadeTest, RevertWithImportantLogical) {
+ TestCascade cascade(GetDocument());
+ cascade.Add("inline-size:10px", CascadeOrigin::kUserAgent);
+ cascade.Add("block-size:11px", CascadeOrigin::kUserAgent);
+
+ cascade.Add("inline-size:revert !important", CascadeOrigin::kAuthor);
+ cascade.Add("width:100px", CascadeOrigin::kAuthor);
+ cascade.Add("height:101px", CascadeOrigin::kAuthor);
+ cascade.Add("block-size:revert !important", CascadeOrigin::kAuthor);
+ cascade.Apply();
+
+ EXPECT_EQ("10px", cascade.ComputedValue("width"));
+ EXPECT_EQ("11px", cascade.ComputedValue("height"));
+ EXPECT_EQ("10px", cascade.ComputedValue("inline-size"));
+ EXPECT_EQ("11px", cascade.ComputedValue("block-size"));
+}
+
+TEST_F(StyleCascadeTest, RevertSurrogateChain) {
+ TestCascade cascade(GetDocument());
+
+ cascade.Add("inline-size:revert", CascadeOrigin::kUserAgent);
+ cascade.Add("block-size:10px", CascadeOrigin::kUserAgent);
+ cascade.Add("min-inline-size:11px", CascadeOrigin::kUserAgent);
+ cascade.Add("min-block-size:12px", CascadeOrigin::kUserAgent);
+ cascade.Add("margin-inline:13px", CascadeOrigin::kUserAgent);
+ cascade.Add("margin-block:14px", CascadeOrigin::kUserAgent);
+ cascade.Add("margin-top:revert", CascadeOrigin::kUserAgent);
+ cascade.Add("margin-left:15px", CascadeOrigin::kUserAgent);
+ cascade.Add("margin-bottom:16px", CascadeOrigin::kUserAgent);
+ cascade.Add("margin-block-end:17px", CascadeOrigin::kUserAgent);
+
+ cascade.Add("inline-size:101px", CascadeOrigin::kUser);
+ cascade.Add("block-size:102px", CascadeOrigin::kUser);
+ cascade.Add("width:revert", CascadeOrigin::kUser);
+ cascade.Add("height:revert", CascadeOrigin::kUser);
+ cascade.Add("min-inline-size:103px", CascadeOrigin::kUser);
+ cascade.Add("min-block-size:104px", CascadeOrigin::kUser);
+ cascade.Add("margin:105px", CascadeOrigin::kUser);
+ cascade.Add("margin-block-start:revert", CascadeOrigin::kUser);
+ cascade.Add("margin-inline-start:106px", CascadeOrigin::kUser);
+ cascade.Add("margin-block-end:revert", CascadeOrigin::kUser);
+ cascade.Add("margin-right:107px", CascadeOrigin::kUser);
+
+ cascade.Add("inline-size:revert", CascadeOrigin::kAuthor);
+ cascade.Add("block-size:revert", CascadeOrigin::kAuthor);
+ cascade.Add("min-inline-size:revert", CascadeOrigin::kAuthor);
+ cascade.Add("min-block-size:1001px", CascadeOrigin::kAuthor);
+ cascade.Add("margin:1002px", CascadeOrigin::kAuthor);
+ cascade.Add("margin-top:revert", CascadeOrigin::kAuthor);
+ cascade.Add("margin-left:1003px", CascadeOrigin::kAuthor);
+ cascade.Add("margin-bottom:1004px", CascadeOrigin::kAuthor);
+ cascade.Add("margin-right:1005px", CascadeOrigin::kAuthor);
+ cascade.Apply();
+
+ EXPECT_EQ("auto", cascade.ComputedValue("width"));
+ EXPECT_EQ("10px", cascade.ComputedValue("height"));
+ EXPECT_EQ("103px", cascade.ComputedValue("min-width"));
+ EXPECT_EQ("1001px", cascade.ComputedValue("min-height"));
+ EXPECT_EQ("0px", cascade.ComputedValue("margin-top"));
+ EXPECT_EQ("1005px", cascade.ComputedValue("margin-right"));
+ EXPECT_EQ("1004px", cascade.ComputedValue("margin-bottom"));
+ EXPECT_EQ("1003px", cascade.ComputedValue("margin-left"));
+}
+
+TEST_F(StyleCascadeTest, RevertInKeyframe) {
+ AppendSheet(R"HTML(
+ @keyframes test {
+ from { margin-left: 0px; }
+ to { margin-left: revert; }
+ }
+ )HTML");
+
+ TestCascade cascade(GetDocument());
+
+ cascade.Add("margin-left:100px", CascadeOrigin::kUserAgent);
+ cascade.Add("animation:test linear 1000s -500s");
+ cascade.Apply();
+
+ cascade.CalculateAnimationUpdate();
+ cascade.Apply();
+
+ EXPECT_EQ("50px", cascade.ComputedValue("margin-left"));
+}
+
+TEST_F(StyleCascadeTest, RevertToCustomPropertyInKeyframe) {
+ RegisterProperty(GetDocument(), "--x", "<length>", "0px", false);
+
+ AppendSheet(R"HTML(
+ @keyframes test {
+ from { --x: 0px; }
+ to { --x: revert; }
+ }
+ )HTML");
+
+ TestCascade cascade(GetDocument());
+
+ cascade.Add("--x:100px", CascadeOrigin::kUser);
+ cascade.Add("--x:1000px", CascadeOrigin::kAuthor);
+ cascade.Add("animation:test linear 1000s -500s");
+ cascade.Apply();
+
+ cascade.CalculateAnimationUpdate();
+ cascade.Apply();
+
+ EXPECT_EQ("50px", cascade.ComputedValue("--x"));
+}
+
+TEST_F(StyleCascadeTest, RevertToCustomPropertyInKeyframeUnset) {
+ RegisterProperty(GetDocument(), "--x", "<length>", "0px", false);
+ RegisterProperty(GetDocument(), "--y", "<length>", "1000px", true);
+
+ AppendSheet(R"HTML(
+ @keyframes test {
+ from { --x: 100px; --y: 100px; }
+ to { --x: revert; --y: revert; }
+ }
+ )HTML");
+
+ TestCascade parent(GetDocument());
+ parent.Add("--y: 0px");
+ parent.Apply();
+ EXPECT_EQ("0px", parent.ComputedValue("--y"));
+
+ TestCascade cascade(GetDocument());
+ cascade.InheritFrom(parent.TakeStyle());
+ cascade.Add("--x:10000px", CascadeOrigin::kAuthor);
+ cascade.Add("--y:10000px", CascadeOrigin::kAuthor);
+ cascade.Add("animation:test linear 1000s -500s");
+ cascade.Apply();
+
+ cascade.CalculateAnimationUpdate();
+ cascade.Apply();
+
+ EXPECT_EQ("50px", cascade.ComputedValue("--x"));
+ EXPECT_EQ("50px", cascade.ComputedValue("--y"));
+}
+
+TEST_F(StyleCascadeTest, RevertToCustomPropertyInKeyframeEmptyInherit) {
+ RegisterProperty(GetDocument(), "--x", "<length>", "0px", true);
+
+ AppendSheet(R"HTML(
+ @keyframes test {
+ from { --x: 100px; }
+ to { --x: revert; }
+ }
+ )HTML");
+
+ TestCascade cascade(GetDocument());
+ cascade.Add("--x:10000px", CascadeOrigin::kAuthor);
+ cascade.Add("animation:test linear 1000s -500s");
+ cascade.Apply();
+
+ cascade.CalculateAnimationUpdate();
+ cascade.Apply();
+
+ EXPECT_EQ("50px", cascade.ComputedValue("--x"));
+}
+
+TEST_F(StyleCascadeTest, RevertInKeyframeResponsive) {
+ AppendSheet(R"HTML(
+ @keyframes test {
+ from { margin-left: 0px; }
+ to { margin-left: revert; }
+ }
+ )HTML");
+
+ TestCascade cascade(GetDocument());
+
+ cascade.Add("--x:100px", CascadeOrigin::kUser);
+ cascade.Add("margin-left:var(--x)", CascadeOrigin::kUser);
+ cascade.Add("animation:test linear 1000s -500s");
+ cascade.Apply();
+ cascade.CalculateAnimationUpdate();
+ cascade.Apply();
+
+ EXPECT_EQ("50px", cascade.ComputedValue("margin-left"));
+
+ cascade.Add("--x:80px", CascadeOrigin::kAuthor);
+ cascade.Apply();
+
+ EXPECT_EQ("40px", cascade.ComputedValue("margin-left"));
+}
+
+TEST_F(StyleCascadeTest, RevertToCycleInKeyframe) {
+ RegisterProperty(GetDocument(), "--x", "<length>", "0px", false);
+
+ AppendSheet(R"HTML(
+ @keyframes test {
+ from { --x: 100px; }
+ to { --x: revert; }
+ }
+ )HTML");
+
+ TestCascade cascade(GetDocument());
+
+ cascade.Add("--x:var(--y)", CascadeOrigin::kUser);
+ cascade.Add("--y:var(--x)", CascadeOrigin::kUser);
+ cascade.Add("--x:200px", CascadeOrigin::kAuthor);
+ cascade.Add("animation:test linear 1000s -500s");
+ cascade.Apply();
+
+ cascade.CalculateAnimationUpdate();
+ cascade.Apply();
+
+ EXPECT_EQ("0px", cascade.ComputedValue("--x"));
+}
+
+TEST_F(StyleCascadeTest, RevertCausesTransition) {
+ TestCascade cascade1(GetDocument());
+ cascade1.Add("width:200px", CascadeOrigin::kUser);
+ cascade1.Add("width:100px", CascadeOrigin::kAuthor);
+ cascade1.Add("transition: width 1000s steps(2, end)", CascadeOrigin::kAuthor);
+ cascade1.Apply();
+
+ GetDocument().body()->SetComputedStyle(cascade1.TakeStyle());
+
+ // Now simulate a new style, with new color values.
+ TestCascade cascade2(GetDocument());
+ cascade2.Add("width:200px", CascadeOrigin::kUser);
+ cascade2.Add("width:100px", CascadeOrigin::kAuthor);
+ cascade2.Add("width:revert", CascadeOrigin::kAuthor);
+ cascade2.Add("transition: width 1000s steps(2, start)",
+ CascadeOrigin::kAuthor);
+ cascade2.Apply();
+
+ cascade2.CalculateTransitionUpdate();
+ cascade2.Apply();
+
+ EXPECT_EQ("150px", cascade2.ComputedValue("width"));
+}
+
+TEST_F(StyleCascadeTest, CSSWideKeywordsInFallbacks) {
+ {
+ TestCascade cascade(GetDocument());
+ cascade.Add("display:var(--u,initial)");
+ cascade.Add("margin:var(--u,initial)");
+ cascade.Apply();
+ }
+ {
+ TestCascade cascade(GetDocument());
+ cascade.Add("display:var(--u,inherit)");
+ cascade.Add("margin:var(--u,inherit)");
+ cascade.Apply();
+ }
+ {
+ TestCascade cascade(GetDocument());
+ cascade.Add("display:var(--u,unset)");
+ cascade.Add("margin:var(--u,unset)");
+ cascade.Apply();
+ }
+ {
+ TestCascade cascade(GetDocument());
+ cascade.Add("display:var(--u,revert)");
+ cascade.Add("margin:var(--u,revert)");
+ cascade.Apply();
+ }
+
+ // TODO(crbug.com/1105782): Specs and WPT are currently in conflict
+ // regarding the correct behavior here. For now this test just verifies
+ // that we don't crash.
+}
+
TEST_F(StyleCascadeTest, RegisteredInitial) {
RegisterProperty(GetDocument(), "--x", "<length>", "0px", false);
@@ -1224,7 +1759,7 @@ TEST_F(StyleCascadeTest, SubstituteRegisteredUniversal) {
}
TEST_F(StyleCascadeTest, SubstituteRegisteredUniversalInvalid) {
- RegisterProperty(GetDocument(), "--x", "*", g_null_atom, false);
+ RegisterProperty(GetDocument(), "--x", "*", base::nullopt, false);
TestCascade cascade(GetDocument());
cascade.Add("--y", " var(--x) ");
@@ -1630,6 +2165,56 @@ TEST_F(StyleCascadeTest, AnimateStandardProperty) {
EXPECT_EQ("15px", cascade.ComputedValue("width"));
}
+TEST_F(StyleCascadeTest, AnimateLogicalProperty) {
+ // We don't support smooth interpolation of css-logical properties yet,
+ // so this test uses a paused animation at t=0.
+ // TODO(crbug.com/865579): Support animations of css-logical properties
+
+ AppendSheet(R"HTML(
+ @keyframes test {
+ from { margin-inline-start: 10px; }
+ to { margin-inline-start: 20px; }
+ }
+ )HTML");
+
+ TestCascade cascade(GetDocument());
+
+ cascade.Add("margin-left:1000px");
+ cascade.Add("animation:test 1s linear paused");
+ cascade.Apply();
+
+ cascade.CalculateAnimationUpdate();
+ cascade.Apply();
+
+ EXPECT_EQ(CascadeOrigin::kAnimation, cascade.GetOrigin("margin-left"));
+ EXPECT_EQ("10px", cascade.ComputedValue("margin-left"));
+}
+
+TEST_F(StyleCascadeTest, AnimateLogicalPropertyWithLookup) {
+ // We don't support smooth interpolation of css-logical properties yet,
+ // so this test uses a paused animation at t=0.
+ // TODO(crbug.com/865579): Support animations of css-logical properties
+
+ AppendSheet(R"HTML(
+ @keyframes test {
+ from { margin-inline-start: 10px; }
+ to { margin-inline-start: 20px; }
+ }
+ )HTML");
+
+ TestCascade cascade(GetDocument());
+
+ cascade.Add("margin-left:1000px");
+ cascade.Add("animation:test 1s linear paused");
+ cascade.Apply();
+
+ cascade.CalculateAnimationUpdate();
+ cascade.ApplySingle(GetCSSPropertyMarginLeft());
+
+ EXPECT_EQ(CascadeOrigin::kAnimation, cascade.GetOrigin("margin-left"));
+ EXPECT_EQ("10px", cascade.ComputedValue("margin-left"));
+}
+
TEST_F(StyleCascadeTest, AuthorImportantWinOverAnimations) {
AppendSheet(R"HTML(
@keyframes test {
@@ -1833,86 +2418,6 @@ TEST_F(StyleCascadeTest, AnimatedVisitedHighPrio) {
style->VisitedDependentColor(GetCSSPropertyColor()));
}
-TEST_F(StyleCascadeTest, AnimatedImportantOverrideFlag) {
- AppendSheet(R"HTML(
- @keyframes test {
- from { background-color: white; }
- to { background-color: gray; }
- }
- )HTML");
-
- TestCascade cascade(GetDocument());
- cascade.Add("animation:test 10s -5s linear");
- cascade.Add("background-color: green !important");
- cascade.Apply();
- EXPECT_FALSE(cascade.State().HasImportantOverrides());
-
- cascade.CalculateAnimationUpdate();
- cascade.Apply();
- EXPECT_TRUE(cascade.State().HasImportantOverrides());
-}
-
-TEST_F(StyleCascadeTest, AnimatedImportantOverrideNoFlag) {
- AppendSheet(R"HTML(
- @keyframes test {
- from { background-color: white; }
- to { background-color: gray; }
- }
- )HTML");
-
- TestCascade cascade(GetDocument());
- cascade.Add("animation:test 10s -5s linear");
- cascade.Add("color:green !important");
- cascade.Apply();
- EXPECT_FALSE(cascade.State().HasImportantOverrides());
-
- cascade.CalculateAnimationUpdate();
- cascade.Apply();
- EXPECT_FALSE(cascade.State().HasImportantOverrides());
-}
-
-TEST_F(StyleCascadeTest, AnimatedImportantOverrideFlagHighPriority) {
- AppendSheet(R"HTML(
- @keyframes test {
- from { color: white; }
- to { color: gray; }
- }
- )HTML");
-
- // 'color' is a high priority property, and therefore applied by lookup.
- TestCascade cascade(GetDocument());
- cascade.Add("animation:test 10s -5s linear");
- cascade.Add("color:green !important");
- cascade.Apply();
- EXPECT_FALSE(cascade.State().HasImportantOverrides());
-
- cascade.CalculateAnimationUpdate();
- cascade.Apply();
- EXPECT_TRUE(cascade.State().HasImportantOverrides());
-}
-
-TEST_F(StyleCascadeTest, AnimatedImportantOverrideFlagVisited) {
- AppendSheet(R"HTML(
- @keyframes test {
- from { background-color: white; }
- to { background-color: gray; }
- }
- )HTML");
-
- TestCascade cascade(GetDocument());
- cascade.State().Style()->SetInsideLink(EInsideLink::kInsideVisitedLink);
-
- cascade.Add(ParseDeclarationBlock("background-color:red !important"),
- CascadeOrigin::kAuthor, CSSSelector::kMatchVisited);
- cascade.Add("animation:test 10s -5s linear");
- cascade.Apply();
- EXPECT_FALSE(cascade.State().HasImportantOverrides());
-
- cascade.CalculateAnimationUpdate();
- cascade.Apply();
- EXPECT_TRUE(cascade.State().HasImportantOverrides());
-}
-
TEST_F(StyleCascadeTest, AnimatePendingSubstitutionValue) {
RegisterProperty(GetDocument(), "--x", "<length>", "0px", false);
@@ -1959,7 +2464,7 @@ TEST_F(StyleCascadeTest, ForeignObjectZoomVsEffectiveZoom) {
ASSERT_TRUE(foreign_object);
TestCascade cascade(GetDocument(), foreign_object);
- cascade.Add("-internal-effective-zoom:initial !important",
+ cascade.Add("zoom:-internal-reset-effective !important",
CascadeOrigin::kUserAgent);
cascade.Add("zoom:200%");
cascade.Apply();
@@ -1970,7 +2475,7 @@ TEST_F(StyleCascadeTest, ForeignObjectZoomVsEffectiveZoom) {
TEST_F(StyleCascadeTest, ZoomCascadeOrder) {
TestCascade cascade(GetDocument());
cascade.Add("zoom:200%", CascadeOrigin::kUserAgent);
- cascade.Add("-internal-effective-zoom:initial", CascadeOrigin::kUserAgent);
+ cascade.Add("zoom:-internal-reset-effective", CascadeOrigin::kUserAgent);
cascade.Apply();
EXPECT_EQ(1.0f, cascade.TakeStyle()->EffectiveZoom());
@@ -1986,17 +2491,22 @@ TEST_F(StyleCascadeTest, ZoomVsAll) {
}
TEST_F(StyleCascadeTest, InternalEffectiveZoomVsAll) {
+ TestCascade parent(GetDocument());
+ parent.Add("zoom", "200%");
+ parent.Apply();
+
TestCascade cascade(GetDocument());
- cascade.Add("-internal-effective-zoom:200%", CascadeOrigin::kUserAgent);
- cascade.Add("all:initial");
+ cascade.InheritFrom(parent.TakeStyle());
+ cascade.Add("zoom:-internal-reset-effective", CascadeOrigin::kUserAgent);
+ cascade.Add("all:inherit");
cascade.Apply();
- EXPECT_EQ(1.0f, cascade.TakeStyle()->EffectiveZoom());
+ EXPECT_EQ(4.0f, cascade.TakeStyle()->EffectiveZoom());
}
TEST_F(StyleCascadeTest, ZoomReversedCascadeOrder) {
TestCascade cascade(GetDocument());
- cascade.Add("-internal-effective-zoom:initial", CascadeOrigin::kUserAgent);
+ cascade.Add("zoom:-internal-reset-effective", CascadeOrigin::kUserAgent);
cascade.Add("zoom:200%", CascadeOrigin::kUserAgent);
cascade.Apply();
@@ -2006,7 +2516,7 @@ TEST_F(StyleCascadeTest, ZoomReversedCascadeOrder) {
TEST_F(StyleCascadeTest, ZoomImportant) {
TestCascade cascade(GetDocument());
cascade.Add("zoom:200% !important", CascadeOrigin::kUserAgent);
- cascade.Add("-internal-effective-zoom:initial", CascadeOrigin::kAuthor);
+ cascade.Add("zoom:-internal-reset-effective", CascadeOrigin::kAuthor);
cascade.Apply();
EXPECT_EQ(2.0f, cascade.TakeStyle()->EffectiveZoom());
@@ -2042,6 +2552,57 @@ TEST_F(StyleCascadeTest, WritingModePriority) {
EXPECT_EQ("vertical-lr", cascade.ComputedValue("-webkit-writing-mode"));
}
+TEST_F(StyleCascadeTest, RubyPositionCascadeOrder) {
+ TestCascade cascade(GetDocument());
+ cascade.Add("ruby-position", "over");
+ cascade.Add("-webkit-ruby-position", "after");
+ cascade.Apply();
+
+ EXPECT_EQ("under", cascade.ComputedValue("ruby-position"));
+ EXPECT_EQ("after", cascade.ComputedValue("-webkit-ruby-position"));
+}
+
+TEST_F(StyleCascadeTest, RubyPositionReverseCascadeOrder) {
+ TestCascade cascade(GetDocument());
+ cascade.Add("-webkit-ruby-position", "after");
+ cascade.Add("ruby-position", "over");
+ cascade.Apply();
+
+ EXPECT_EQ("over", cascade.ComputedValue("ruby-position"));
+ EXPECT_EQ("before", cascade.ComputedValue("-webkit-ruby-position"));
+}
+
+TEST_F(StyleCascadeTest, RubyPositionSurrogateCanCascadeAsOriginal) {
+ // Note: ruby-position is defined as the surrogate, and -webkit-ruby-position
+ // is the original.
+ ASSERT_TRUE(GetCSSPropertyRubyPosition().IsSurrogate());
+ ASSERT_FALSE(GetCSSPropertyWebkitRubyPosition().IsSurrogate());
+
+ const struct {
+ CSSValueID specified;
+ const char* webkit_expected;
+ const char* unprefixed_expected;
+ } tests[] = {
+ {CSSValueID::kBefore, "before", "over"},
+ {CSSValueID::kAfter, "after", "under"},
+ {CSSValueID::kOver, "before", "over"},
+ {CSSValueID::kUnder, "after", "under"},
+ };
+
+ for (const auto& test : tests) {
+ TestCascade cascade(GetDocument());
+ auto* set =
+ MakeGarbageCollected<MutableCSSPropertyValueSet>(kHTMLStandardMode);
+ set->SetProperty(CSSPropertyID::kWebkitRubyPosition,
+ *CSSIdentifierValue::Create(test.specified));
+ cascade.Add(set);
+ cascade.Apply();
+ EXPECT_EQ(test.unprefixed_expected, cascade.ComputedValue("ruby-position"));
+ EXPECT_EQ(test.webkit_expected,
+ cascade.ComputedValue("-webkit-ruby-position"));
+ }
+}
+
TEST_F(StyleCascadeTest, WebkitBorderImageCascadeOrder) {
String gradient1("linear-gradient(rgb(0, 0, 0), rgb(0, 128, 0))");
String gradient2("linear-gradient(rgb(0, 0, 0), rgb(0, 200, 0))");
@@ -2105,6 +2666,81 @@ TEST_F(StyleCascadeTest, WebkitBorderImageMixedOrder) {
EXPECT_EQ("space", cascade.ComputedValue("border-image-repeat"));
}
+TEST_F(StyleCascadeTest, InitialDirection) {
+ TestCascade cascade(GetDocument());
+ cascade.Add("margin-inline-start:10px");
+ cascade.Add("margin-inline-end:20px");
+ cascade.Apply();
+
+ EXPECT_EQ("10px", cascade.ComputedValue("margin-left"));
+ EXPECT_EQ("20px", cascade.ComputedValue("margin-right"));
+}
+
+TEST_F(StyleCascadeTest, NonInitialDirection) {
+ TestCascade cascade(GetDocument());
+ cascade.Add("margin-inline-start:10px");
+ cascade.Add("margin-inline-end:20px");
+ cascade.Add("direction:rtl");
+ cascade.Apply();
+
+ EXPECT_EQ("20px", cascade.ComputedValue("margin-left"));
+ EXPECT_EQ("10px", cascade.ComputedValue("margin-right"));
+}
+
+TEST_F(StyleCascadeTest, InitialWritingMode) {
+ TestCascade cascade(GetDocument());
+ cascade.Add("inline-size:10px");
+ cascade.Add("block-size:20px");
+ cascade.Apply();
+
+ EXPECT_EQ("10px", cascade.ComputedValue("width"));
+ EXPECT_EQ("20px", cascade.ComputedValue("height"));
+}
+
+TEST_F(StyleCascadeTest, NonInitialWritingMode) {
+ TestCascade cascade(GetDocument());
+ cascade.Add("inline-size:10px");
+ cascade.Add("block-size:20px");
+ cascade.Add("writing-mode:vertical-lr");
+ cascade.Apply();
+
+ EXPECT_EQ("20px", cascade.ComputedValue("width"));
+ EXPECT_EQ("10px", cascade.ComputedValue("height"));
+}
+
+TEST_F(StyleCascadeTest, DoesNotDependOnCascadeAffectingProperty) {
+ TestCascade cascade(GetDocument());
+ cascade.Add("width:10px");
+ cascade.Add("height:20px");
+ cascade.Apply();
+
+ EXPECT_FALSE(cascade.DependsOnCascadeAffectingProperty());
+ EXPECT_EQ("10px", cascade.ComputedValue("width"));
+ EXPECT_EQ("20px", cascade.ComputedValue("height"));
+}
+
+TEST_F(StyleCascadeTest, DependsOnCascadeAffectingProperty) {
+ TestCascade cascade(GetDocument());
+ cascade.Add("inline-size:10px");
+ cascade.Add("height:20px");
+ cascade.Apply();
+
+ EXPECT_TRUE(cascade.DependsOnCascadeAffectingProperty());
+ EXPECT_EQ("10px", cascade.ComputedValue("width"));
+ EXPECT_EQ("20px", cascade.ComputedValue("height"));
+}
+
+TEST_F(StyleCascadeTest, ResetDependsOnCascadeAffectingPropertyFlag) {
+ TestCascade cascade(GetDocument());
+ cascade.Add("inline-size:10px");
+ cascade.Add("height:20px");
+ cascade.Apply();
+
+ EXPECT_TRUE(cascade.DependsOnCascadeAffectingProperty());
+ cascade.Reset();
+ EXPECT_FALSE(cascade.DependsOnCascadeAffectingProperty());
+}
+
TEST_F(StyleCascadeTest, MarkReferenced) {
RegisterProperty(GetDocument(), "--x", "<length>", "0px", false);
RegisterProperty(GetDocument(), "--y", "<length>", "0px", false);
@@ -2113,11 +2749,10 @@ TEST_F(StyleCascadeTest, MarkReferenced) {
cascade.Add("width", "var(--x)");
cascade.Apply();
- const auto* registry = GetDocument().GetPropertyRegistry();
- ASSERT_TRUE(registry);
+ const auto& registry = GetDocument().EnsurePropertyRegistry();
- EXPECT_TRUE(registry->WasReferenced("--x"));
- EXPECT_FALSE(registry->WasReferenced("--y"));
+ EXPECT_TRUE(registry.WasReferenced("--x"));
+ EXPECT_FALSE(registry.WasReferenced("--y"));
}
TEST_F(StyleCascadeTest, MarkHasVariableReferenceLonghand) {
@@ -2219,10 +2854,10 @@ TEST_F(StyleCascadeTest, ApplyWithFilter) {
}
TEST_F(StyleCascadeTest, HasAuthorBackground) {
- Vector<String> properties = {"background-attachment"/*, "background-blend-mode",
+ Vector<String> properties = {"background-attachment", "background-blend-mode",
"background-clip", "background-image",
"background-origin", "background-position-x",
- "background-position-y", "background-size"*/};
+ "background-position-y", "background-size"};
for (String property : properties) {
TestCascade cascade(GetDocument());
@@ -2256,6 +2891,16 @@ TEST_F(StyleCascadeTest, HasAuthorBorder) {
}
}
+TEST_F(StyleCascadeTest, HasAuthorBorderLogical) {
+ TestCascade cascade(GetDocument());
+ cascade.Add("-webkit-appearance", "button", Origin::kUserAgent);
+ cascade.Add("border-block-start-color", "red", Origin::kUserAgent);
+ cascade.Add("border-block-start-color", "green", Origin::kAuthor);
+ cascade.Apply();
+ auto style = cascade.TakeStyle();
+ EXPECT_TRUE(style->HasAuthorBorder());
+}
+
TEST_F(StyleCascadeTest, NoAuthorBackgroundOrBorder) {
TestCascade cascade(GetDocument());
cascade.Add("-webkit-appearance", "button", Origin::kUserAgent);
@@ -2269,6 +2914,36 @@ TEST_F(StyleCascadeTest, NoAuthorBackgroundOrBorder) {
EXPECT_FALSE(style->HasAuthorBorder());
}
+TEST_F(StyleCascadeTest, AuthorBackgroundRevert) {
+ TestCascade cascade(GetDocument());
+ cascade.Add("-webkit-appearance", "button", Origin::kUserAgent);
+ cascade.Add("background-color", "red", Origin::kUserAgent);
+ cascade.Add("background-color", "revert", Origin::kAuthor);
+ cascade.Apply();
+ auto style = cascade.TakeStyle();
+ EXPECT_FALSE(style->HasAuthorBackground());
+}
+
+TEST_F(StyleCascadeTest, AuthorBorderRevert) {
+ TestCascade cascade(GetDocument());
+ cascade.Add("-webkit-appearance", "button", Origin::kUserAgent);
+ cascade.Add("border-top-color", "red", Origin::kUserAgent);
+ cascade.Add("border-top-color", "revert", Origin::kAuthor);
+ cascade.Apply();
+ auto style = cascade.TakeStyle();
+ EXPECT_FALSE(style->HasAuthorBorder());
+}
+
+TEST_F(StyleCascadeTest, AuthorBorderRevertLogical) {
+ TestCascade cascade(GetDocument());
+ cascade.Add("-webkit-appearance", "button", Origin::kUserAgent);
+ cascade.Add("border-block-start-color", "red", Origin::kUserAgent);
+ cascade.Add("border-block-start-color", "revert", Origin::kAuthor);
+ cascade.Apply();
+ auto style = cascade.TakeStyle();
+ EXPECT_FALSE(style->HasAuthorBorder());
+}
+
TEST_F(StyleCascadeTest, AnalyzeMatchResult) {
auto ua = CascadeOrigin::kUserAgent;
auto author = CascadeOrigin::kAuthor;
@@ -2304,6 +2979,28 @@ TEST_F(StyleCascadeTest, AnalyzeMatchResultAll) {
EXPECT_EQ(cascade.GetPriority("color"), cascade.GetPriority("display"));
}
+TEST_F(StyleCascadeTest, AnalyzeFlagsClean) {
+ AppendSheet(R"HTML(
+ @keyframes test {
+ from { top: 0px; }
+ to { top: 10px; }
+ }
+ )HTML");
+
+ TestCascade cascade(GetDocument());
+
+ cascade.Add("bottom:10px");
+ cascade.Add("animation:test linear 1000s -500s");
+ cascade.Apply();
+ EXPECT_FALSE(cascade.NeedsMatchResultAnalyze());
+ EXPECT_FALSE(cascade.NeedsInterpolationsAnalyze());
+
+ cascade.CalculateAnimationUpdate();
+ cascade.Apply();
+ EXPECT_FALSE(cascade.NeedsMatchResultAnalyze());
+ EXPECT_FALSE(cascade.NeedsInterpolationsAnalyze());
+}
+
TEST_F(StyleCascadeTest, ApplyMatchResultFilter) {
TestCascade cascade(GetDocument());
cascade.Add("display:block");
@@ -2391,4 +3088,30 @@ TEST_F(StyleCascadeTest, Reset) {
EXPECT_EQ(CascadePriority(), cascade.GetPriority("--x"));
}
+TEST_F(StyleCascadeTest, GetImportantSetEmpty) {
+ TestCascade cascade(GetDocument());
+ cascade.Add("color:red");
+ cascade.Add("width:1px");
+ cascade.Add("--x:green");
+ EXPECT_FALSE(cascade.GetImportantSet());
+}
+
+TEST_F(StyleCascadeTest, GetImportantSetSingle) {
+ TestCascade cascade(GetDocument());
+ cascade.Add("width:1px !important");
+ ASSERT_TRUE(cascade.GetImportantSet());
+ EXPECT_EQ(CSSBitset({CSSPropertyID::kWidth}), *cascade.GetImportantSet());
+}
+
+TEST_F(StyleCascadeTest, GetImportantSetMany) {
+ TestCascade cascade(GetDocument());
+ cascade.Add("width:1px !important");
+ cascade.Add("height:1px !important");
+ cascade.Add("top:1px !important");
+ ASSERT_TRUE(cascade.GetImportantSet());
+ EXPECT_EQ(CSSBitset({CSSPropertyID::kWidth, CSSPropertyID::kHeight,
+ CSSPropertyID::kTop}),
+ *cascade.GetImportantSet());
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/resolver/style_resolver.cc b/chromium/third_party/blink/renderer/core/css/resolver/style_resolver.cc
index 4b487f15cc4..29f5ff72d0c 100644
--- a/chromium/third_party/blink/renderer/core/css/resolver/style_resolver.cc
+++ b/chromium/third_party/blink/renderer/core/css/resolver/style_resolver.cc
@@ -90,6 +90,7 @@
#include "third_party/blink/renderer/core/html/track/vtt/vtt_cue.h"
#include "third_party/blink/renderer/core/html/track/vtt/vtt_element.h"
#include "third_party/blink/renderer/core/html_names.h"
+#include "third_party/blink/renderer/core/mathml_names.h"
#include "third_party/blink/renderer/core/media_type_names.h"
#include "third_party/blink/renderer/core/probe/core_probes.h"
#include "third_party/blink/renderer/core/style/style_inherited_variables.h"
@@ -116,10 +117,6 @@ void SetAnimationUpdateIfNeeded(StyleResolverState& state, Element& element) {
auto& element_animations = element.EnsureElementAnimations();
element_animations.CssAnimations().SetPendingUpdate(
state.AnimationUpdate());
- if (state.HasImportantOverrides())
- element_animations.SetHasImportantOverrides();
- if (state.HasFontAffectingAnimation())
- element_animations.SetHasFontAffectingAnimation();
}
}
@@ -208,6 +205,26 @@ static CSSPropertyValueSet* RightToLeftDeclaration() {
return right_to_left_decl;
}
+static CSSPropertyValueSet* MarkerUserAgentDeclarations() {
+ DEFINE_STATIC_LOCAL(
+ Persistent<MutableCSSPropertyValueSet>, marker_ua_decl,
+ (MakeGarbageCollected<MutableCSSPropertyValueSet>(kHTMLQuirksMode)));
+ if (marker_ua_decl->IsEmpty()) {
+ // Set 'unicode-bidi: isolate'
+ marker_ua_decl->SetProperty(
+ CSSPropertyID::kUnicodeBidi,
+ *CSSIdentifierValue::Create(CSSValueID::kIsolate));
+
+ // Set 'font-variant-numeric: tabular-nums'
+ CSSValueList* variant_numeric = CSSValueList::CreateSpaceSeparated();
+ variant_numeric->Append(
+ *CSSIdentifierValue::Create(CSSValueID::kTabularNums));
+ marker_ua_decl->SetProperty(CSSPropertyID::kFontVariantNumeric,
+ *variant_numeric);
+ }
+ return marker_ua_decl;
+}
+
static void CollectScopedResolversForHostedShadowTrees(
const Element& element,
HeapVector<Member<ScopedStyleResolver>, 8>& resolvers) {
@@ -610,15 +627,22 @@ void StyleResolver::MatchUserRules(ElementRuleCollector& collector) {
collector.FinishAddingUserRules();
}
-void StyleResolver::MatchUARules(ElementRuleCollector& collector) {
+void StyleResolver::MatchUARules(const Element& element,
+ ElementRuleCollector& collector) {
collector.SetMatchingUARules(true);
CSSDefaultStyleSheets& default_style_sheets =
CSSDefaultStyleSheets::Instance();
- RuleSet* user_agent_style_sheet =
- print_media_type_ ? default_style_sheets.DefaultPrintStyle()
- : default_style_sheets.DefaultStyle();
- MatchRuleSet(collector, user_agent_style_sheet);
+ if (!print_media_type_) {
+ if (LIKELY(element.IsHTMLElement() || element.IsVTTElement()))
+ MatchRuleSet(collector, default_style_sheets.DefaultStyle());
+ else if (element.IsSVGElement())
+ MatchRuleSet(collector, default_style_sheets.DefaultSVGStyle());
+ else if (element.namespaceURI() == mathml_names::kNamespaceURI)
+ MatchRuleSet(collector, default_style_sheets.DefaultMathMLStyle());
+ } else {
+ MatchRuleSet(collector, default_style_sheets.DefaultPrintStyle());
+ }
// In quirks mode, we match rules from the quirks user agent sheet.
if (GetDocument().InQuirksMode())
@@ -649,7 +673,7 @@ DISABLE_CFI_PERF
void StyleResolver::MatchAllRules(StyleResolverState& state,
ElementRuleCollector& collector,
bool include_smil_properties) {
- MatchUARules(collector);
+ MatchUARules(state.GetElement(), collector);
MatchUserRules(collector);
// Now check author rules, beginning first with presentational attributes
@@ -765,13 +789,15 @@ void StyleResolver::LoadPendingResources(StyleResolverState& state) {
state.GetElementStyleResources().LoadPendingResources(state.Style());
}
-static const ComputedStyle* CachedAnimationBaseComputedStyle(
- StyleResolverState& state) {
+static ElementAnimations* GetElementAnimations(StyleResolverState& state) {
if (!state.GetAnimatingElement())
return nullptr;
+ return state.GetAnimatingElement()->GetElementAnimations();
+}
- ElementAnimations* element_animations =
- state.GetAnimatingElement()->GetElementAnimations();
+static const ComputedStyle* CachedAnimationBaseComputedStyle(
+ StyleResolverState& state) {
+ ElementAnimations* element_animations = GetElementAnimations(state);
if (!element_animations)
return nullptr;
@@ -783,20 +809,56 @@ static const ComputedStyle* CachedAnimationBaseComputedStyle(
return nullptr;
}
+ if (CSSAnimations::IsAnimatingRevert(element_animations)) {
+ state.SetIsAnimatingRevert(true);
+ return nullptr;
+ }
+
+ if (CSSAnimations::IsAnimatingFontAffectingProperties(element_animations)) {
+ state.SetHasFontAffectingAnimation();
+ if (element_animations->BaseComputedStyle() &&
+ element_animations->BaseComputedStyle()->HasFontRelativeUnits()) {
+ return nullptr;
+ }
+ }
+
+ if (CSSAnimations::IsAnimatingStandardProperties(
+ element_animations, element_animations->BaseImportantSet(),
+ KeyframeEffect::kDefaultPriority)) {
+ state.SetHasImportantOverrides();
+ return nullptr;
+ }
+
return element_animations->BaseComputedStyle();
}
-static void UpdateAnimationBaseComputedStyle(StyleResolverState& state) {
+static void UpdateAnimationBaseComputedStyle(StyleResolverState& state,
+ StyleCascade* cascade) {
if (!state.GetAnimatingElement())
return;
ElementAnimations* element_animations =
state.GetAnimatingElement()->GetElementAnimations();
if (element_animations) {
- if (state.IsAnimatingCustomProperties()) {
+ std::unique_ptr<CSSBitset> important_set;
+ if (!element_animations->BaseComputedStyle()) {
+ important_set = (cascade ? cascade->GetImportantSet() : nullptr);
+ if (CSSAnimations::IsAnimatingStandardProperties(
+ element_animations, important_set.get(),
+ KeyframeEffect::kDefaultPriority)) {
+ state.SetHasImportantOverrides();
+ }
+ }
+
+ if (!element_animations->IsAnimationStyleChange() ||
+ state.IsAnimatingCustomProperties() || state.IsAnimatingRevert() ||
+ state.HasImportantOverrides() ||
+ (state.HasFontAffectingAnimation() &&
+ state.Style()->HasFontRelativeUnits())) {
element_animations->ClearBaseComputedStyle();
} else {
- element_animations->UpdateBaseComputedStyle(state.Style());
+ element_animations->UpdateBaseComputedStyle(state.Style(),
+ std::move(important_set));
}
}
}
@@ -980,7 +1042,7 @@ void StyleResolver::ApplyBaseComputedStyle(
DCHECK(ValidateBaseComputedStyle(animation_base_computed_style,
*state.Style()));
if (!animation_base_computed_style)
- UpdateAnimationBaseComputedStyle(state);
+ UpdateAnimationBaseComputedStyle(state, cascade);
}
}
@@ -1072,25 +1134,16 @@ bool StyleResolver::PseudoStyleForElementInternal(
// but that would use a slow universal element selector. So instead we apply
// the styles here as an optimization.
if (pseudo_style_request.pseudo_id == kPseudoIdMarker) {
- // Set 'unicode-bidi: isolate'
- state.Style()->SetUnicodeBidi(UnicodeBidi::kIsolate);
-
- // Set 'font-variant-numeric: tabular-nums'
- FontVariantNumeric variant_numeric;
- variant_numeric.SetNumericSpacing(FontVariantNumeric::kTabularNums);
- state.GetFontBuilder().SetVariantNumeric(variant_numeric);
- UpdateFont(state);
-
- // Don't bother matching rules if there is no style for ::marker
- if (!state.ParentStyle()->HasPseudoElementStyle(kPseudoIdMarker)) {
- StyleAdjuster::AdjustComputedStyle(state, nullptr);
- return true;
- }
+ cascade.MutableMatchResult().AddMatchedProperties(
+ MarkerUserAgentDeclarations());
}
- MatchUARules(collector);
- MatchUserRules(collector);
- MatchAuthorRules(state.GetElement(), collector);
+ // TODO(obrufau): support styling nested pseudo-elements
+ if (!element.IsPseudoElement()) {
+ MatchUARules(state.GetElement(), collector);
+ MatchUserRules(collector);
+ MatchAuthorRules(state.GetElement(), collector);
+ }
collector.FinishAddingAuthorRulesForTreeScope();
if (tracker_)
@@ -1119,7 +1172,7 @@ bool StyleResolver::PseudoStyleForElementInternal(
*state.Style()));
if (!animation_base_computed_style)
- UpdateAnimationBaseComputedStyle(state);
+ UpdateAnimationBaseComputedStyle(state, &cascade);
}
if (animation_base_computed_style) {
@@ -1304,8 +1357,11 @@ RuleIndexList* StyleResolver::PseudoCSSRulesForElement(
match_result, state.Style(),
EInsideLink::kNotInsideLink);
collector.SetMode(SelectorChecker::kCollectingCSSRules);
- CollectPseudoRulesForElement(*element, collector, pseudo_id,
- rules_to_include);
+ // TODO(obrufau): support collecting rules for nested ::marker
+ if (!element->IsPseudoElement()) {
+ CollectPseudoRulesForElement(*element, collector, pseudo_id,
+ rules_to_include);
+ }
if (tracker_)
AddMatchedRulesToTracker(collector);
@@ -1325,7 +1381,7 @@ void StyleResolver::CollectPseudoRulesForElement(
collector.SetPseudoElementStyleRequest(PseudoElementStyleRequest(pseudo_id));
if (rules_to_include & kUAAndUserCSSRules) {
- MatchUARules(collector);
+ MatchUARules(element, collector);
MatchUserRules(collector);
}
@@ -1674,12 +1730,6 @@ void StyleResolver::ApplyMatchedProperties(StyleResolverState& state,
}
}
-static unsigned ComputeMatchedPropertiesHash(
- const MatchedProperties* properties,
- unsigned size) {
- return StringHasher::HashMemory(properties, sizeof(MatchedProperties) * size);
-}
-
void StyleResolver::InvalidateMatchedPropertiesCache() {
matched_properties_cache_.Clear();
}
@@ -1795,17 +1845,12 @@ StyleResolver::CacheSuccess StyleResolver::ApplyMatchedCache(
const MatchResult& match_result) {
const Element& element = state.GetElement();
- unsigned cache_hash = match_result.IsCacheable()
- ? ComputeMatchedPropertiesHash(
- match_result.GetMatchedProperties().data(),
- match_result.GetMatchedProperties().size())
- : 0;
+ MatchedPropertiesCache::Key key(match_result);
+
bool is_inherited_cache_hit = false;
bool is_non_inherited_cache_hit = false;
const CachedMatchedProperties* cached_matched_properties =
- cache_hash ? matched_properties_cache_.Find(
- cache_hash, state, match_result.GetMatchedProperties())
- : nullptr;
+ key.IsValid() ? matched_properties_cache_.Find(key, state) : nullptr;
if (cached_matched_properties && MatchedPropertiesCache::IsCacheable(state)) {
INCREMENT_STYLE_STATS_COUNTER(GetDocument().GetStyleEngine(),
@@ -1843,8 +1888,8 @@ StyleResolver::CacheSuccess StyleResolver::ApplyMatchedCache(
UpdateFont(state);
}
- return CacheSuccess(is_inherited_cache_hit, is_non_inherited_cache_hit,
- cache_hash, cached_matched_properties);
+ return CacheSuccess(is_inherited_cache_hit, is_non_inherited_cache_hit, key,
+ cached_matched_properties);
}
void StyleResolver::MaybeAddToMatchedPropertiesCache(
@@ -1852,13 +1897,14 @@ void StyleResolver::MaybeAddToMatchedPropertiesCache(
const CacheSuccess& cache_success,
const MatchResult& match_result) {
if (!state.IsAnimatingCustomProperties() &&
- !cache_success.cached_matched_properties && cache_success.cache_hash &&
+ !cache_success.cached_matched_properties && cache_success.key.IsValid() &&
MatchedPropertiesCache::IsCacheable(state)) {
INCREMENT_STYLE_STATS_COUNTER(GetDocument().GetStyleEngine(),
matched_property_cache_added, 1);
- matched_properties_cache_.Add(*state.Style(), *state.ParentStyle(),
- cache_success.cache_hash,
- match_result.GetMatchedProperties());
+ // TODO(crbug.com/1057072): Pass dependencies to MatchedPropertiesCache.
+ HashSet<CSSPropertyName> unused_dependencies;
+ matched_properties_cache_.Add(cache_success.key, *state.Style(),
+ *state.ParentStyle(), unused_dependencies);
}
}
diff --git a/chromium/third_party/blink/renderer/core/css/resolver/style_resolver.h b/chromium/third_party/blink/renderer/core/css/resolver/style_resolver.h
index 7f64e22e336..383a12c65ce 100644
--- a/chromium/third_party/blink/renderer/core/css/resolver/style_resolver.h
+++ b/chromium/third_party/blink/renderer/core/css/resolver/style_resolver.h
@@ -160,7 +160,7 @@ class CORE_EXPORT StyleResolver final : public GarbageCollected<StyleResolver> {
PseudoId,
unsigned rules_to_include);
void MatchRuleSet(ElementRuleCollector&, RuleSet*);
- void MatchUARules(ElementRuleCollector&);
+ void MatchUARules(const Element&, ElementRuleCollector&);
void MatchUserRules(ElementRuleCollector&);
// This matches `::part` selectors. It looks in ancestor scopes as far as
// part mapping requires.
@@ -183,16 +183,16 @@ class CORE_EXPORT StyleResolver final : public GarbageCollected<StyleResolver> {
public:
bool is_inherited_cache_hit;
bool is_non_inherited_cache_hit;
- unsigned cache_hash;
+ MatchedPropertiesCache::Key key;
const CachedMatchedProperties* cached_matched_properties;
CacheSuccess(bool is_inherited_cache_hit,
bool is_non_inherited_cache_hit,
- unsigned cache_hash,
+ MatchedPropertiesCache::Key key,
const CachedMatchedProperties* cached_matched_properties)
: is_inherited_cache_hit(is_inherited_cache_hit),
is_non_inherited_cache_hit(is_non_inherited_cache_hit),
- cache_hash(cache_hash),
+ key(key),
cached_matched_properties(cached_matched_properties) {}
bool IsFullCacheHit() const {
diff --git a/chromium/third_party/blink/renderer/core/css/resolver/style_resolver_state.cc b/chromium/third_party/blink/renderer/core/css/resolver/style_resolver_state.cc
index b2cd50a4809..46d980e079f 100644
--- a/chromium/third_party/blink/renderer/core/css/resolver/style_resolver_state.cc
+++ b/chromium/third_party/blink/renderer/core/css/resolver/style_resolver_state.cc
@@ -23,6 +23,7 @@
#include "third_party/blink/renderer/core/css/resolver/style_resolver_state.h"
#include "third_party/blink/renderer/core/animation/css/css_animations.h"
+#include "third_party/blink/renderer/core/css/css_light_dark_value_pair.h"
#include "third_party/blink/renderer/core/css/css_property_value_set.h"
#include "third_party/blink/renderer/core/dom/node.h"
#include "third_party/blink/renderer/core/dom/node_computed_style.h"
@@ -217,4 +218,17 @@ const Element* StyleResolverState::GetAnimatingElement() const {
return pseudo_element_;
}
+const CSSValue& StyleResolverState::ResolveLightDarkPair(
+ const CSSProperty& property,
+ const CSSValue& value) {
+ if (const auto* pair = DynamicTo<CSSLightDarkValuePair>(value)) {
+ if (!property.IsInherited())
+ Style()->SetHasNonInheritedLightDarkValue();
+ if (Style()->UsedColorScheme() == WebColorScheme::kLight)
+ return pair->First();
+ return pair->Second();
+ }
+ return value;
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/resolver/style_resolver_state.h b/chromium/third_party/blink/renderer/core/css/resolver/style_resolver_state.h
index 24b06a2a7c5..af7d94ed519 100644
--- a/chromium/third_party/blink/renderer/core/css/resolver/style_resolver_state.h
+++ b/chromium/third_party/blink/renderer/core/css/resolver/style_resolver_state.h
@@ -128,14 +128,15 @@ class CORE_EXPORT StyleResolverState {
void SetIsAnimatingCustomProperties(bool value) {
is_animating_custom_properties_ = value;
}
+ bool IsAnimatingRevert() const { return is_animating_revert_; }
+ void SetIsAnimatingRevert(bool value) { is_animating_revert_ = value; }
// Normally, we apply all active animation effects on top of the style created
// by regular CSS declarations. However, !important declarations have a
- // higher priority than animation effects [1]. If StyleCascade skipped
- // application of some interpolation, it means something else in the cascade
- // had a higher priority (i.e. it was !important). In this case, we can't
- // use the base-computed-style optimization, since that code path is unable
- // to skip any animation effects at all.
+ // higher priority than animation effects [1]. If we're currently animating
+ // (not transitioning) a property which was declared !important in the base
+ // style, this flag is set such that we can disable the base computed style
+ // optimization.
//
// [1] https://drafts.csswg.org/css-cascade-4/#cascade-origin
bool HasImportantOverrides() const { return has_important_overrides_; }
@@ -216,6 +217,13 @@ class CORE_EXPORT StyleResolverState {
CSSParserMode GetParserMode() const;
+ // If the input CSSValue is a CSSLightDarkValuePair, return the light or dark
+ // CSSValue based on the UsedColorScheme. For all other values, just return a
+ // reference to the passed value. If the property is a non-inherited one, mark
+ // the ComputedStyle as having such a pair since that will make sure its not
+ // stored in the MatchedPropertiesCache.
+ const CSSValue& ResolveLightDarkPair(const CSSProperty&, const CSSValue&);
+
private:
enum class AnimatingElementType { kElement, kPseudoElement };
@@ -248,6 +256,10 @@ class CORE_EXPORT StyleResolverState {
CSSAnimationUpdate animation_update_;
bool is_animation_interpolation_map_ready_;
bool is_animating_custom_properties_;
+ // We can't use the base computed style optimization when 'revert' appears
+ // in a keyframe. (We need to build the cascade to know what to revert to).
+ // TODO(crbug.com/1068515): Refactor caching to remove these flags.
+ bool is_animating_revert_ = false;
bool has_important_overrides_ = false;
bool has_font_affecting_animation_ = false;
diff --git a/chromium/third_party/blink/renderer/core/css/resolver/style_resolver_test.cc b/chromium/third_party/blink/renderer/core/css/resolver/style_resolver_test.cc
index 7f9577045f0..46d01c3a140 100644
--- a/chromium/third_party/blink/renderer/core/css/resolver/style_resolver_test.cc
+++ b/chromium/third_party/blink/renderer/core/css/resolver/style_resolver_test.cc
@@ -5,7 +5,10 @@
#include "third_party/blink/renderer/core/css/resolver/style_resolver.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/core/animation/animation_test_helper.h"
+#include "third_party/blink/renderer/core/animation/document_timeline.h"
#include "third_party/blink/renderer/core/animation/element_animations.h"
+#include "third_party/blink/renderer/core/css/properties/css_property_ref.h"
#include "third_party/blink/renderer/core/css/style_engine.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/node_computed_style.h"
@@ -27,6 +30,14 @@ class StyleResolverTest : public PageTestBase {
return style;
}
+ String ComputedValue(String name, const ComputedStyle& style) {
+ CSSPropertyRef ref(name, GetDocument());
+ DCHECK(ref.IsValid());
+ return ref.GetProperty()
+ .CSSValueFromComputedStyle(style, nullptr, false)
+ ->CssText();
+ }
+
protected:
};
@@ -112,19 +123,20 @@ TEST_F(StyleResolverTest, HasEmUnits) {
TEST_F(StyleResolverTest, BasePresentIfFontRelativeUnitsAbsent) {
GetDocument().documentElement()->setInnerHTML("<div id=div>Test</div>");
UpdateAllLifecyclePhasesForTest();
-
Element* div = GetDocument().getElementById("div");
- StyleResolver* resolver = GetStyleEngine().Resolver();
- ASSERT_TRUE(resolver);
- ElementAnimations& animations = div->EnsureElementAnimations();
- animations.SetAnimationStyleChange(true);
- // We're animating a font affecting property, but we should still be able to
- // use the base computed style optimization, since no font-relative units
- // exist in the base.
- animations.SetHasFontAffectingAnimation();
- EXPECT_TRUE(resolver->StyleForElement(div));
- EXPECT_TRUE(animations.BaseComputedStyle());
+ auto* effect = CreateSimpleKeyframeEffectForTest(
+ div, CSSPropertyID::kFontSize, "50px", "100px");
+ GetDocument().Timeline().Play(effect);
+ UpdateAllLifecyclePhasesForTest();
+
+ EXPECT_EQ("50px", ComputedValue("font-size", *StyleForId("div")));
+
+ div->SetNeedsAnimationStyleRecalc();
+ StyleForId("div");
+
+ ASSERT_TRUE(div->GetElementAnimations());
+ EXPECT_TRUE(div->GetElementAnimations()->BaseComputedStyle());
}
TEST_F(StyleResolverTest, NoCrashWhenAnimatingWithoutCascade) {
@@ -145,6 +157,104 @@ TEST_F(StyleResolverTest, NoCrashWhenAnimatingWithoutCascade) {
UpdateAllLifecyclePhasesForTest();
}
+TEST_F(StyleResolverTest, AnimationNotMaskedByImportant) {
+ GetDocument().documentElement()->setInnerHTML(R"HTML(
+ <style>
+ div {
+ width: 10px;
+ height: 10px !important;
+ }
+ </style>
+ <div id=div></div>
+ )HTML");
+ UpdateAllLifecyclePhasesForTest();
+ Element* div = GetDocument().getElementById("div");
+
+ auto* effect = CreateSimpleKeyframeEffectForTest(div, CSSPropertyID::kWidth,
+ "50px", "100px");
+ GetDocument().Timeline().Play(effect);
+ UpdateAllLifecyclePhasesForTest();
+
+ EXPECT_EQ("50px", ComputedValue("width", *StyleForId("div")));
+ EXPECT_EQ("10px", ComputedValue("height", *StyleForId("div")));
+
+ div->SetNeedsAnimationStyleRecalc();
+ StyleForId("div");
+
+ ASSERT_TRUE(div->GetElementAnimations());
+ const CSSBitset* bitset = div->GetElementAnimations()->BaseImportantSet();
+ EXPECT_FALSE(CSSAnimations::IsAnimatingStandardProperties(
+ div->GetElementAnimations(), bitset, KeyframeEffect::kDefaultPriority));
+ EXPECT_TRUE(div->GetElementAnimations()->BaseComputedStyle());
+ EXPECT_FALSE(bitset && bitset->Has(CSSPropertyID::kWidth));
+ EXPECT_TRUE(bitset && bitset->Has(CSSPropertyID::kHeight));
+}
+
+TEST_F(StyleResolverTest, AnimationNotMaskedWithoutElementAnimations) {
+ EXPECT_FALSE(CSSAnimations::IsAnimatingStandardProperties(
+ /* ElementAnimations */ nullptr, std::make_unique<CSSBitset>().get(),
+ KeyframeEffect::kDefaultPriority));
+}
+
+TEST_F(StyleResolverTest, AnimationNotMaskedWithoutBitset) {
+ GetDocument().documentElement()->setInnerHTML(R"HTML(
+ <style>
+ div {
+ width: 10px;
+ height: 10px !important;
+ }
+ </style>
+ <div id=div></div>
+ )HTML");
+ UpdateAllLifecyclePhasesForTest();
+ Element* div = GetDocument().getElementById("div");
+
+ auto* effect = CreateSimpleKeyframeEffectForTest(div, CSSPropertyID::kWidth,
+ "50px", "100px");
+ GetDocument().Timeline().Play(effect);
+ UpdateAllLifecyclePhasesForTest();
+
+ EXPECT_EQ("50px", ComputedValue("width", *StyleForId("div")));
+ EXPECT_EQ("10px", ComputedValue("height", *StyleForId("div")));
+
+ div->SetNeedsAnimationStyleRecalc();
+ StyleForId("div");
+
+ ASSERT_TRUE(div->GetElementAnimations());
+ EXPECT_FALSE(CSSAnimations::IsAnimatingStandardProperties(
+ div->GetElementAnimations(), /* CSSBitset */ nullptr,
+ KeyframeEffect::kDefaultPriority));
+}
+
+TEST_F(StyleResolverTest, AnimationMaskedByImportant) {
+ GetDocument().documentElement()->setInnerHTML(R"HTML(
+ <style>
+ div {
+ width: 10px;
+ height: 10px !important;
+ }
+ </style>
+ <div id=div></div>
+ )HTML");
+ UpdateAllLifecyclePhasesForTest();
+ Element* div = GetDocument().getElementById("div");
+
+ auto* effect = CreateSimpleKeyframeEffectForTest(div, CSSPropertyID::kHeight,
+ "50px", "100px");
+ GetDocument().Timeline().Play(effect);
+ UpdateAllLifecyclePhasesForTest();
+
+ EXPECT_EQ("10px", ComputedValue("width", *StyleForId("div")));
+ EXPECT_EQ("10px", ComputedValue("height", *StyleForId("div")));
+
+ div->SetNeedsAnimationStyleRecalc();
+ StyleForId("div");
+
+ ASSERT_TRUE(div->GetElementAnimations());
+ EXPECT_FALSE(div->GetElementAnimations()->BaseComputedStyle());
+ EXPECT_FALSE(div->GetElementAnimations()->BaseImportantSet());
+}
+
class StyleResolverFontRelativeUnitTest
: public testing::WithParamInterface<const char*>,
public StyleResolverTest {};
@@ -155,12 +265,18 @@ TEST_P(StyleResolverFontRelativeUnitTest, NoBaseIfFontRelativeUnitPresent) {
UpdateAllLifecyclePhasesForTest();
Element* div = GetDocument().getElementById("div");
- ElementAnimations& animations = div->EnsureElementAnimations();
- animations.SetAnimationStyleChange(true);
- animations.SetHasFontAffectingAnimation();
+ auto* effect = CreateSimpleKeyframeEffectForTest(
+ div, CSSPropertyID::kFontSize, "50px", "100px");
+ GetDocument().Timeline().Play(effect);
+ UpdateAllLifecyclePhasesForTest();
+ EXPECT_EQ("50px", ComputedValue("font-size", *StyleForId("div")));
+
+ div->SetNeedsAnimationStyleRecalc();
+ auto computed_style = StyleForId("div");
- EXPECT_TRUE(StyleForId("div")->HasFontRelativeUnits());
- EXPECT_FALSE(animations.BaseComputedStyle());
+ EXPECT_TRUE(computed_style->HasFontRelativeUnits());
+ ASSERT_TRUE(div->GetElementAnimations());
+ EXPECT_FALSE(div->GetElementAnimations()->BaseComputedStyle());
}
TEST_P(StyleResolverFontRelativeUnitTest,
@@ -170,11 +286,18 @@ TEST_P(StyleResolverFontRelativeUnitTest,
UpdateAllLifecyclePhasesForTest();
Element* div = GetDocument().getElementById("div");
- ElementAnimations& animations = div->EnsureElementAnimations();
- animations.SetAnimationStyleChange(true);
+ auto* effect = CreateSimpleKeyframeEffectForTest(div, CSSPropertyID::kHeight,
+ "50px", "100px");
+ GetDocument().Timeline().Play(effect);
+ UpdateAllLifecyclePhasesForTest();
+ EXPECT_EQ("50px", ComputedValue("height", *StyleForId("div")));
+
+ div->SetNeedsAnimationStyleRecalc();
+ auto computed_style = StyleForId("div");
- EXPECT_TRUE(StyleForId("div")->HasFontRelativeUnits());
- EXPECT_TRUE(animations.BaseComputedStyle());
+ EXPECT_TRUE(computed_style->HasFontRelativeUnits());
+ ASSERT_TRUE(div->GetElementAnimations());
+ EXPECT_TRUE(div->GetElementAnimations()->BaseComputedStyle());
}
INSTANTIATE_TEST_SUITE_P(All,
diff --git a/chromium/third_party/blink/renderer/core/css/resolver/viewport_style_resolver.cc b/chromium/third_party/blink/renderer/core/css/resolver/viewport_style_resolver.cc
index e7a0ddea13f..4118e5261cd 100644
--- a/chromium/third_party/blink/renderer/core/css/resolver/viewport_style_resolver.cc
+++ b/chromium/third_party/blink/renderer/core/css/resolver/viewport_style_resolver.cc
@@ -385,8 +385,6 @@ void ViewportStyleResolver::UpdateViewport(
if (needs_update_ == kCollectRules) {
Reset();
CollectViewportRulesFromUASheets();
- if (RuntimeEnabledFeatures::CSSViewportEnabled())
- collection.CollectViewportRules(*this);
}
Resolve();
needs_update_ = kNoUpdate;
diff --git a/chromium/third_party/blink/renderer/core/css/selector_checker.cc b/chromium/third_party/blink/renderer/core/css/selector_checker.cc
index 5067dc81ebf..8f748ae1507 100644
--- a/chromium/third_party/blink/renderer/core/css/selector_checker.cc
+++ b/chromium/third_party/blink/renderer/core/css/selector_checker.cc
@@ -46,6 +46,7 @@
#include "third_party/blink/renderer/core/editing/frame_selection.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/picture_in_picture_controller.h"
+#include "third_party/blink/renderer/core/frame/settings.h"
#include "third_party/blink/renderer/core/fullscreen/fullscreen.h"
#include "third_party/blink/renderer/core/html/custom/element_internals.h"
#include "third_party/blink/renderer/core/html/forms/html_form_control_element.h"
@@ -620,7 +621,6 @@ SelectorChecker::MatchStatus SelectorChecker::MatchForRelation(
return MatchSelector(next_context, result);
}
return kSelectorFailsCompletely;
- break;
case CSSSelector::kSubSelector:
break;
}
@@ -1368,7 +1368,6 @@ bool SelectorChecker::CheckPseudoClassForVTT(
return false;
default:
return CheckPseudoClass(context, result);
- break;
}
return false;
}
@@ -1661,15 +1660,17 @@ bool SelectorChecker::MatchesFocusVisiblePseudoClass(const Element& element) {
return false;
const Document& document = element.GetDocument();
- bool always_show_focus_ring = element.MayTriggerVirtualKeyboard();
+ const Settings* settings = document.GetSettings();
+ bool always_show_focus = settings->GetAccessibilityAlwaysShowFocus();
+ bool is_text_input = element.MayTriggerVirtualKeyboard();
bool last_focus_from_mouse =
document.GetFrame() &&
document.GetFrame()->Selection().FrameIsFocusedAndActive() &&
document.LastFocusType() == mojom::blink::FocusType::kMouse;
bool had_keyboard_event = document.HadKeyboardEvent();
- return (!last_focus_from_mouse || had_keyboard_event ||
- always_show_focus_ring);
+ return (always_show_focus || is_text_input || !last_focus_from_mouse ||
+ had_keyboard_event);
}
// static
diff --git a/chromium/third_party/blink/renderer/core/css/style_engine.cc b/chromium/third_party/blink/renderer/core/css/style_engine.cc
index 4d430870ed3..3e91e19e1d9 100644
--- a/chromium/third_party/blink/renderer/core/css/style_engine.cc
+++ b/chromium/third_party/blink/renderer/core/css/style_engine.cc
@@ -738,7 +738,7 @@ void StyleEngine::DidDetach() {
environment_variables_ = nullptr;
}
-bool StyleEngine::ClearFontCacheAndAddUserFonts() {
+bool StyleEngine::ClearFontFaceCacheAndAddUserFonts() {
bool fonts_changed = false;
if (font_selector_ &&
@@ -800,8 +800,6 @@ void StyleEngine::MarkTreeScopeDirty(TreeScope& scope) {
void StyleEngine::MarkDocumentDirty() {
document_scope_dirty_ = true;
document_style_sheet_collection_->MarkSheetListDirty();
- if (RuntimeEnabledFeatures::CSSViewportEnabled())
- ViewportRulesChanged();
if (GetDocument().ImportLoader())
GetDocument().MasterDocument().GetStyleEngine().MarkDocumentDirty();
else
@@ -924,7 +922,7 @@ void StyleEngine::MarkFontsNeedUpdate() {
GetDocument().ScheduleLayoutTreeUpdateIfNeeded();
}
-void StyleEngine::FontsNeedUpdate(FontSelector*) {
+void StyleEngine::FontsNeedUpdate(FontSelector*, FontInvalidationReason) {
if (!GetDocument().IsActive())
return;
@@ -1328,7 +1326,7 @@ void StyleEngine::ScheduleInvalidationsForRuleSets(
const HeapHashSet<Member<RuleSet>>& rule_sets,
InvalidationScope invalidation_scope) {
#if DCHECK_IS_ON()
- // Full scope recalcs should be handled while collecting the ruleSets before
+ // Full scope recalcs should be handled while collecting the rule sets before
// calling this method.
for (auto rule_set : rule_sets)
DCHECK(!rule_set->Features().NeedsFullRecalcForRuleSetInvalidation());
@@ -1368,10 +1366,12 @@ void StyleEngine::ScheduleInvalidationsForRuleSets(
}
}
- if (element->GetStyleChangeType() < kSubtreeStyleChange)
+ if (element->GetStyleChangeType() < kSubtreeStyleChange &&
+ element->GetComputedStyle()) {
element = ElementTraversal::Next(*element, stay_within);
- else
+ } else {
element = ElementTraversal::NextSkippingChildren(*element, stay_within);
+ }
}
}
@@ -1515,29 +1515,18 @@ unsigned GetRuleSetFlags(const HeapHashSet<Member<RuleSet>> rule_sets) {
return flags;
}
-bool NeedsFullRecalcForRuleSetChanges(TreeScope& tree_scope,
- unsigned changed_rule_flags,
- bool has_rebuilt_font_cache) {
- if (changed_rule_flags & kFullRecalcRules)
- return true;
- if (!tree_scope.RootNode().IsDocumentNode())
- return false;
- return (changed_rule_flags & kFontFaceRules) || has_rebuilt_font_cache;
-}
-
} // namespace
void StyleEngine::InvalidateForRuleSetChanges(
TreeScope& tree_scope,
const HeapHashSet<Member<RuleSet>>& changed_rule_sets,
unsigned changed_rule_flags,
- InvalidationScope invalidation_scope,
- bool has_rebuilt_font_cache) {
+ InvalidationScope invalidation_scope) {
if (tree_scope.GetDocument().HasPendingForcedStyleRecalc())
return;
if (!tree_scope.GetDocument().documentElement())
return;
- if (changed_rule_sets.IsEmpty() && !has_rebuilt_font_cache)
+ if (changed_rule_sets.IsEmpty())
return;
Element& invalidation_root =
@@ -1545,8 +1534,7 @@ void StyleEngine::InvalidateForRuleSetChanges(
if (invalidation_root.GetStyleChangeType() == kSubtreeStyleChange)
return;
- if (NeedsFullRecalcForRuleSetChanges(tree_scope, changed_rule_flags,
- has_rebuilt_font_cache)) {
+ if (changed_rule_flags & kFullRecalcRules) {
invalidation_root.SetNeedsStyleRecalc(
kSubtreeStyleChange,
StyleChangeReasonForTracing::Create(
@@ -1581,7 +1569,7 @@ void StyleEngine::ApplyUserRuleSetChanges(
global_rule_set_->MarkDirty();
unsigned changed_rule_flags = GetRuleSetFlags(changed_rule_sets);
- bool has_rebuilt_font_cache = false;
+ bool has_rebuilt_font_face_cache = false;
if (changed_rule_flags & kFontFaceRules) {
if (ScopedStyleResolver* scoped_resolver =
GetDocument().GetScopedStyleResolver()) {
@@ -1592,7 +1580,7 @@ void StyleEngine::ApplyUserRuleSetChanges(
scoped_resolver->SetNeedsAppendAllSheets();
MarkDocumentDirty();
} else {
- has_rebuilt_font_cache = ClearFontCacheAndAddUserFonts();
+ has_rebuilt_font_face_cache = ClearFontFaceCacheAndAddUserFonts();
}
}
@@ -1608,9 +1596,13 @@ void StyleEngine::ApplyUserRuleSetChanges(
ScopedStyleResolver::KeyframesRulesAdded(GetDocument());
}
+ if ((changed_rule_flags & kFontFaceRules) || has_rebuilt_font_face_cache) {
+ GetFontSelector()->FontFaceInvalidated(
+ FontInvalidationReason::kGeneralInvalidation);
+ }
+
InvalidateForRuleSetChanges(GetDocument(), changed_rule_sets,
- changed_rule_flags, kInvalidateAllScopes,
- has_rebuilt_font_cache);
+ changed_rule_flags, kInvalidateAllScopes);
}
void StyleEngine::ApplyRuleSetChanges(
@@ -1626,12 +1618,12 @@ void StyleEngine::ApplyRuleSetChanges(
unsigned changed_rule_flags = GetRuleSetFlags(changed_rule_sets);
- bool rebuild_font_cache = change == kActiveSheetsChanged &&
- (changed_rule_flags & kFontFaceRules) &&
- tree_scope.RootNode().IsDocumentNode();
+ bool rebuild_font_face_cache = change == kActiveSheetsChanged &&
+ (changed_rule_flags & kFontFaceRules) &&
+ tree_scope.RootNode().IsDocumentNode();
ScopedStyleResolver* scoped_resolver = tree_scope.GetScopedStyleResolver();
if (scoped_resolver && scoped_resolver->NeedsAppendAllSheets()) {
- rebuild_font_cache = true;
+ rebuild_font_face_cache = true;
change = kActiveSheetsChanged;
}
@@ -1645,22 +1637,22 @@ void StyleEngine::ApplyRuleSetChanges(
ScopedStyleResolver::KeyframesRulesAdded(tree_scope);
if (changed_rule_flags & kPropertyRules) {
- // TODO(https://crbug.com/978786): Don't ignore TreeScope.
-
- // TODO(https://crbug.com/978781): Support unregistration.
- // At this point we could have unregistered properties for
- // change==kActiveSheetsChanged, but we don't yet support that.
-
- for (auto* it = new_style_sheets.begin(); it != new_style_sheets.end();
- it++) {
- DCHECK(it->second);
- AddPropertyRules(*it->second);
+ // @property rules are (for now) ignored in shadow trees, per spec.
+ // https://drafts.css-houdini.org/css-properties-values-api-1/#at-property-rule
+ if (tree_scope.RootNode().IsDocumentNode()) {
+ PropertyRegistration::RemoveDeclaredProperties(GetDocument());
+
+ for (auto* it = new_style_sheets.begin(); it != new_style_sheets.end();
+ it++) {
+ DCHECK(it->second);
+ AddPropertyRules(*it->second);
+ }
}
}
- bool has_rebuilt_font_cache = false;
- if (rebuild_font_cache)
- has_rebuilt_font_cache = ClearFontCacheAndAddUserFonts();
+ bool has_rebuilt_font_face_cache = false;
+ if (rebuild_font_face_cache)
+ has_rebuilt_font_face_cache = ClearFontFaceCacheAndAddUserFonts();
unsigned append_start_index = 0;
if (scoped_resolver) {
@@ -1682,8 +1674,15 @@ void StyleEngine::ApplyRuleSetChanges(
append_start_index, new_style_sheets);
}
+ if (tree_scope.RootNode().IsDocumentNode()) {
+ if ((changed_rule_flags & kFontFaceRules) || has_rebuilt_font_face_cache) {
+ GetFontSelector()->FontFaceInvalidated(
+ FontInvalidationReason::kGeneralInvalidation);
+ }
+ }
+
InvalidateForRuleSetChanges(tree_scope, changed_rule_sets, changed_rule_flags,
- kInvalidateCurrentScope, has_rebuilt_font_cache);
+ kInvalidateCurrentScope);
}
void StyleEngine::LoadVisionDeficiencyFilter() {
@@ -1765,7 +1764,7 @@ bool StyleEngine::UpdateRemUnits(const ComputedStyle* old_root_style,
return false;
}
-void StyleEngine::CustomPropertyRegistered() {
+void StyleEngine::PropertyRegistryChanged() {
// TODO(timloh): Invalidate only elements with this custom property set
MarkAllElementsForStyleRecalc(StyleChangeReasonForTracing::Create(
style_change_reason::kPropertyRegistration));
@@ -1895,29 +1894,12 @@ void StyleEngine::AddUserKeyframeStyle(StyleRuleKeyframes* rule) {
}
void StyleEngine::AddPropertyRules(const RuleSet& rule_set) {
- PropertyRegistry* registry = GetDocument().GetPropertyRegistry();
- if (!registry)
- return;
const HeapVector<Member<StyleRuleProperty>> property_rules =
rule_set.PropertyRules();
for (unsigned i = 0; i < property_rules.size(); ++i) {
StyleRuleProperty* rule = property_rules[i];
-
AtomicString name(rule->GetName());
-
- // For now, ignore silently if registration already exists.
- // TODO(https://crbug.com/978781): Support unregistration.
- if (registry->Registration(name))
- continue;
-
- PropertyRegistration* registration =
- PropertyRegistration::MaybeCreate(GetDocument(), name, *rule);
-
- if (!registration)
- continue;
-
- registry->RegisterProperty(name, *registration);
- CustomPropertyRegistered();
+ PropertyRegistration::DeclareProperty(GetDocument(), name, *rule);
}
}
@@ -1944,8 +1926,8 @@ DocumentStyleEnvironmentVariables& StyleEngine::EnsureEnvironmentVariables() {
scoped_refptr<StyleInitialData> StyleEngine::MaybeCreateAndGetInitialData() {
if (initial_data_)
return initial_data_;
- if (PropertyRegistry* registry = document_->GetPropertyRegistry()) {
- if (registry->RegistrationCount())
+ if (const PropertyRegistry* registry = document_->GetPropertyRegistry()) {
+ if (!registry->IsEmpty())
initial_data_ = StyleInitialData::Create(*registry);
}
return initial_data_;
diff --git a/chromium/third_party/blink/renderer/core/css/style_engine.h b/chromium/third_party/blink/renderer/core/css/style_engine.h
index e33a320f61a..4fb115318de 100644
--- a/chromium/third_party/blink/renderer/core/css/style_engine.h
+++ b/chromium/third_party/blink/renderer/core/css/style_engine.h
@@ -331,7 +331,7 @@ class CORE_EXPORT StyleEngine final : public GarbageCollected<StyleEngine>,
void CollectMatchingUserRules(ElementRuleCollector&) const;
- void CustomPropertyRegistered();
+ void PropertyRegistryChanged();
void EnvironmentVariableChanged();
@@ -389,7 +389,7 @@ class CORE_EXPORT StyleEngine final : public GarbageCollected<StyleEngine>,
private:
// FontSelectorClient implementation.
- void FontsNeedUpdate(FontSelector*) override;
+ void FontsNeedUpdate(FontSelector*, FontInvalidationReason) override;
void LoadVisionDeficiencyFilter();
@@ -464,8 +464,7 @@ class CORE_EXPORT StyleEngine final : public GarbageCollected<StyleEngine>,
TreeScope& tree_scope,
const HeapHashSet<Member<RuleSet>>& changed_rule_sets,
unsigned changed_rule_flags,
- InvalidationScope invalidation_scope,
- bool rebuild_font_cache);
+ InvalidationScope invalidation_scope);
void InvalidateInitialData();
void UpdateViewport();
@@ -480,7 +479,7 @@ class CORE_EXPORT StyleEngine final : public GarbageCollected<StyleEngine>,
void UpdateStyleSheetList(TreeScope&);
// Returns true if any @font-face rules are added or removed.
- bool ClearFontCacheAndAddUserFonts();
+ bool ClearFontFaceCacheAndAddUserFonts();
void ClearKeyframeRules() { keyframes_rule_map_.clear(); }
void ClearPropertyRules();
diff --git a/chromium/third_party/blink/renderer/core/css/style_engine_test.cc b/chromium/third_party/blink/renderer/core/css/style_engine_test.cc
index 0bab3c371e1..d8b6e717efa 100644
--- a/chromium/third_party/blink/renderer/core/css/style_engine_test.cc
+++ b/chromium/third_party/blink/renderer/core/css/style_engine_test.cc
@@ -2247,8 +2247,6 @@ TEST_F(StyleEngineTest, RecalcPropagatedWritingMode) {
}
TEST_F(StyleEngineTest, GetComputedStyleOutsideFlatTree) {
- ScopedFlatTreeStyleRecalcForTest feature_scope(true);
-
GetDocument().body()->setInnerHTML(
R"HTML(<div id="host"><div id="outer"><div id="inner"><div id="innermost"></div></div></div></div>)HTML");
@@ -2314,8 +2312,6 @@ TEST_F(StyleEngineTest, GetComputedStyleOutsideFlatTree) {
}
TEST_F(StyleEngineTest, MoveSlottedOutsideFlatTree) {
- ScopedFlatTreeStyleRecalcForTest feature_scope(true);
-
GetDocument().body()->setInnerHTML(R"HTML(
<div id="host1"><span></span></div>
<div id="host2"></div>
@@ -2340,8 +2336,6 @@ TEST_F(StyleEngineTest, MoveSlottedOutsideFlatTree) {
}
TEST_F(StyleEngineTest, StyleRecalcRootInShadowTree) {
- ScopedFlatTreeStyleRecalcForTest feature_scope(true);
-
GetDocument().body()->setInnerHTML(R"HTML(
<div id="host"></div>
)HTML");
@@ -2359,8 +2353,6 @@ TEST_F(StyleEngineTest, StyleRecalcRootInShadowTree) {
}
TEST_F(StyleEngineTest, StyleRecalcRootOutsideFlatTree) {
- ScopedFlatTreeStyleRecalcForTest feature_scope(true);
-
GetDocument().body()->setInnerHTML(R"HTML(
<div id="host"><div id="ensured"><span></span></div></div>
<div id="dirty"></div>
@@ -2392,8 +2384,6 @@ TEST_F(StyleEngineTest, StyleRecalcRootOutsideFlatTree) {
}
TEST_F(StyleEngineTest, RemoveStyleRecalcRootFromFlatTree) {
- ScopedFlatTreeStyleRecalcForTest scope(true);
-
GetDocument().body()->setInnerHTML(R"HTML(
<div id=host><span></span></div>
)HTML");
@@ -2428,8 +2418,6 @@ TEST_F(StyleEngineTest, RemoveStyleRecalcRootFromFlatTree) {
}
TEST_F(StyleEngineTest, SlottedWithEnsuredStyleOutsideFlatTree) {
- ScopedFlatTreeStyleRecalcForTest scope(true);
-
GetDocument().body()->setInnerHTML(R"HTML(
<div id="host"><span></span></div>
)HTML");
@@ -2457,8 +2445,6 @@ TEST_F(StyleEngineTest, SlottedWithEnsuredStyleOutsideFlatTree) {
}
TEST_F(StyleEngineTest, RecalcEnsuredStyleOutsideFlatTreeV0) {
- ScopedFlatTreeStyleRecalcForTest scope(true);
-
GetDocument().body()->setInnerHTML(R"HTML(
<div id="host"><span></span></div>
)HTML");
@@ -2483,8 +2469,6 @@ TEST_F(StyleEngineTest, RecalcEnsuredStyleOutsideFlatTreeV0) {
}
TEST_F(StyleEngineTest, ForceReattachRecalcRootAttachShadow) {
- ScopedFlatTreeStyleRecalcForTest scope(true);
-
GetDocument().body()->setInnerHTML(R"HTML(
<div id="reattach"></div><div id="host"><span></span></div>
)HTML");
@@ -2662,6 +2646,20 @@ TEST_F(StyleEngineTest,
GetCSSPropertyColor()));
}
+TEST_F(StyleEngineTest, RevertUseCount) {
+ ScopedCSSRevertForTest scoped_feature(true);
+
+ GetDocument().body()->setInnerHTML(
+ "<style>div { display: unset; }</style><div></div>");
+ UpdateAllLifecyclePhases();
+ EXPECT_FALSE(GetDocument().IsUseCounted(WebFeature::kCSSKeywordRevert));
+
+ GetDocument().body()->setInnerHTML(
+ "<style>div { display: revert; }</style><div></div>");
+ UpdateAllLifecyclePhases();
+ EXPECT_TRUE(GetDocument().IsUseCounted(WebFeature::kCSSKeywordRevert));
+}
+
class ParameterizedStyleEngineTest
: public testing::WithParamInterface<bool>,
private ScopedCSSReducedFontLoadingInvalidationsForTest,
diff --git a/chromium/third_party/blink/renderer/core/css/style_property_serializer.cc b/chromium/third_party/blink/renderer/core/css/style_property_serializer.cc
index a54cefc8d04..52a5a7cf847 100644
--- a/chromium/third_party/blink/renderer/core/css/style_property_serializer.cc
+++ b/chromium/third_party/blink/renderer/core/css/style_property_serializer.cc
@@ -402,9 +402,10 @@ String StylePropertySerializer::CommonShorthandChecks(
const CSSValue& value = *longhands[i];
if (!allow_initial && value.IsInitialValue())
return g_empty_string;
- if (value.IsInheritedValue() || value.IsUnsetValue() ||
- value.IsPendingSubstitutionValue())
+ if ((value.IsCSSWideKeyword() && !value.IsInitialValue()) ||
+ value.IsPendingSubstitutionValue()) {
return g_empty_string;
+ }
if (value.IsVariableReferenceValue())
return g_empty_string;
}
diff --git a/chromium/third_party/blink/renderer/core/css/style_recalc.h b/chromium/third_party/blink/renderer/core/css/style_recalc.h
index 71624336499..6fb3c216a26 100644
--- a/chromium/third_party/blink/renderer/core/css/style_recalc.h
+++ b/chromium/third_party/blink/renderer/core/css/style_recalc.h
@@ -38,27 +38,23 @@ class StyleRecalcChange {
StyleRecalcChange(Propagate propagate) : propagate_(propagate) {}
StyleRecalcChange ForChildren() const {
- return {RecalcDescendants() ? kRecalcDescendants : kNo, reattach_,
- calc_invisible_};
+ return {RecalcDescendants() ? kRecalcDescendants : kNo, reattach_};
}
StyleRecalcChange ForPseudoElement() const {
if (propagate_ == kUpdatePseudoElements)
- return {kRecalcChildren, reattach_, calc_invisible_};
+ return {kRecalcChildren, reattach_};
return *this;
}
StyleRecalcChange EnsureAtLeast(Propagate propagate) const {
if (propagate > propagate_)
- return {propagate, reattach_, calc_invisible_};
- return {propagate_, reattach_, calc_invisible_};
+ return {propagate, reattach_};
+ return {propagate_, reattach_};
}
StyleRecalcChange ForceRecalcDescendants() const {
- return {kRecalcDescendants, reattach_, calc_invisible_};
+ return {kRecalcDescendants, reattach_};
}
StyleRecalcChange ForceReattachLayoutTree() const {
- return {propagate_, true, calc_invisible_};
- }
- StyleRecalcChange ForceCalcInvisible() const {
- return {propagate_, reattach_, true};
+ return {propagate_, true};
}
bool ReattachLayoutTree() const { return reattach_; }
@@ -71,20 +67,15 @@ class StyleRecalcChange {
bool TraversePseudoElements(const Node&) const;
bool ShouldRecalcStyleFor(const Node&) const;
bool ShouldUpdatePseudoElement(const PseudoElement&) const;
- bool CalcInvisible() const { return calc_invisible_; }
private:
- StyleRecalcChange(Propagate propagate, bool reattach, bool calc_invisible)
- : propagate_(propagate),
- reattach_(reattach),
- calc_invisible_(calc_invisible) {}
+ StyleRecalcChange(Propagate propagate, bool reattach)
+ : propagate_(propagate), reattach_(reattach) {}
// To what extent do we need to update style for children.
Propagate propagate_ = kNo;
// Need to reattach layout tree if true.
bool reattach_ = false;
- // Forcing ComputedStyle for find-in-page for invisible DOM.
- bool calc_invisible_ = false;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/style_recalc_root.cc b/chromium/third_party/blink/renderer/core/css/style_recalc_root.cc
index fe2e85a0bba..7d741d334d0 100644
--- a/chromium/third_party/blink/renderer/core/css/style_recalc_root.cc
+++ b/chromium/third_party/blink/renderer/core/css/style_recalc_root.cc
@@ -22,18 +22,6 @@ Element& StyleRecalcRoot::RootElement() const {
// originating element for simplicity.
return *root_node->parentElement();
}
- if (!RuntimeEnabledFeatures::FlatTreeStyleRecalcEnabled()) {
- if (root_node->IsInShadowTree()) {
- // Since we traverse in light tree order, we might need to traverse
- // slotted shadow host children for inheritance for which the recalc root
- // is not an ancestor. Since we might re-slot slots, we need to start at
- // the outermost shadow host.
- TreeScope* tree_scope = &root_node->GetTreeScope();
- while (!tree_scope->ParentTreeScope()->RootNode().IsDocumentNode())
- tree_scope = tree_scope->ParentTreeScope();
- return To<ShadowRoot>(tree_scope->RootNode()).host();
- }
- }
if (root_node->IsTextNode())
root_node = root_node->GetStyleRecalcParent();
return To<Element>(*root_node);
@@ -53,7 +41,6 @@ namespace {
base::Optional<Member<Element>> FirstFlatTreeAncestorForChildDirty(
ContainerNode& parent) {
- DCHECK(RuntimeEnabledFeatures::FlatTreeStyleRecalcEnabled());
if (!parent.IsElementNode()) {
// The flat tree does not contain shadow roots or the document node. The
// closest ancestor for dirty bits is the shadow host or nullptr.
@@ -92,25 +79,22 @@ base::Optional<Member<Element>> FirstFlatTreeAncestorForChildDirty(
} // namespace
void StyleRecalcRoot::RootRemoved(ContainerNode& parent) {
- ContainerNode* ancestor = &parent;
- if (RuntimeEnabledFeatures::FlatTreeStyleRecalcEnabled()) {
- // We are notified with the light tree parent of the node(s) which were
- // removed from the DOM. If 'parent' is a shadow host, there are elements in
- // its shadow tree which are marked child-dirty which needs to be cleared in
- // order to clear the recalc root below. If we are not able to find the
- // closest flat tree ancestor for traversal, fall back to using the 'parent'
- // as the new recalc root to allow the child-dirty bits to be cleared on the
- // next style recalc.
- auto opt_ancestor = FirstFlatTreeAncestorForChildDirty(parent);
- if (!opt_ancestor) {
- Update(&parent, &parent);
- DCHECK(!IsSingleRoot());
- DCHECK_EQ(GetRootNode(), ancestor);
- return;
- }
- ancestor = opt_ancestor.value();
+ // We are notified with the light tree parent of the node(s) which were
+ // removed from the DOM. If 'parent' is a shadow host, there are elements in
+ // its shadow tree which are marked child-dirty which needs to be cleared in
+ // order to clear the recalc root below. If we are not able to find the
+ // closest flat tree ancestor for traversal, fall back to using the 'parent'
+ // as the new recalc root to allow the child-dirty bits to be cleared on the
+ // next style recalc.
+ auto opt_ancestor = FirstFlatTreeAncestorForChildDirty(parent);
+ if (!opt_ancestor) {
+ Update(&parent, &parent);
+ DCHECK(!IsSingleRoot());
+ DCHECK_EQ(GetRootNode(), &parent);
+ return;
}
- for (; ancestor; ancestor = ancestor->GetStyleRecalcParent()) {
+ for (Element* ancestor = opt_ancestor.value(); ancestor;
+ ancestor = ancestor->GetStyleRecalcParent()) {
DCHECK(ancestor->ChildNeedsStyleRecalc());
DCHECK(!ancestor->NeedsStyleRecalc());
ancestor->ClearChildNeedsStyleRecalc();
@@ -119,8 +103,6 @@ void StyleRecalcRoot::RootRemoved(ContainerNode& parent) {
}
void StyleRecalcRoot::RemovedFromFlatTree(const Node& node) {
- if (!RuntimeEnabledFeatures::FlatTreeStyleRecalcEnabled())
- return;
if (!GetRootNode())
return;
if (GetRootNode()->IsDocumentNode())
diff --git a/chromium/third_party/blink/renderer/core/css/style_rule.cc b/chromium/third_party/blink/renderer/core/css/style_rule.cc
index 1220ed8fd1c..abc3fc6c294 100644
--- a/chromium/third_party/blink/renderer/core/css/style_rule.cc
+++ b/chromium/third_party/blink/renderer/core/css/style_rule.cc
@@ -32,7 +32,6 @@
#include "third_party/blink/renderer/core/css/css_style_rule.h"
#include "third_party/blink/renderer/core/css/css_supports_rule.h"
#include "third_party/blink/renderer/core/css/css_value_list.h"
-#include "third_party/blink/renderer/core/css/css_viewport_rule.h"
#include "third_party/blink/renderer/core/css/style_rule_import.h"
#include "third_party/blink/renderer/core/css/style_rule_keyframe.h"
#include "third_party/blink/renderer/core/css/style_rule_namespace.h"
@@ -213,12 +212,9 @@ CSSRule* StyleRuleBase::CreateCSSOMWrapper(CSSStyleSheet* parent_sheet,
rule = MakeGarbageCollected<CSSNamespaceRule>(
To<StyleRuleNamespace>(self), parent_sheet);
break;
- case kViewport:
- rule = MakeGarbageCollected<CSSViewportRule>(To<StyleRuleViewport>(self),
- parent_sheet);
- break;
case kKeyframe:
case kCharset:
+ case kViewport:
NOTREACHED();
return nullptr;
}
@@ -333,6 +329,18 @@ MutableCSSPropertyValueSet& StyleRuleProperty::MutableProperties() {
return *To<MutableCSSPropertyValueSet>(properties_.Get());
}
+const CSSValue* StyleRuleProperty::GetSyntax() const {
+ return properties_->GetPropertyCSSValue(CSSPropertyID::kSyntax);
+}
+
+const CSSValue* StyleRuleProperty::Inherits() const {
+ return properties_->GetPropertyCSSValue(CSSPropertyID::kInherits);
+}
+
+const CSSValue* StyleRuleProperty::GetInitialValue() const {
+ return properties_->GetPropertyCSSValue(CSSPropertyID::kInitialValue);
+}
+
void StyleRuleProperty::TraceAfterDispatch(blink::Visitor* visitor) const {
visitor->Trace(properties_);
StyleRuleBase::TraceAfterDispatch(visitor);
diff --git a/chromium/third_party/blink/renderer/core/css/style_rule.h b/chromium/third_party/blink/renderer/core/css/style_rule.h
index a4a11462a2e..05bd60b1866 100644
--- a/chromium/third_party/blink/renderer/core/css/style_rule.h
+++ b/chromium/third_party/blink/renderer/core/css/style_rule.h
@@ -195,6 +195,9 @@ class StyleRuleProperty : public StyleRuleBase {
const CSSPropertyValueSet& Properties() const { return *properties_; }
MutableCSSPropertyValueSet& MutableProperties();
const String& GetName() const { return name_; }
+ const CSSValue* GetSyntax() const;
+ const CSSValue* Inherits() const;
+ const CSSValue* GetInitialValue() const;
StyleRuleProperty* Copy() const {
return MakeGarbageCollected<StyleRuleProperty>(*this);
diff --git a/chromium/third_party/blink/renderer/core/css/style_rule_import.cc b/chromium/third_party/blink/renderer/core/css/style_rule_import.cc
index 55a0036c700..b407494abdd 100644
--- a/chromium/third_party/blink/renderer/core/css/style_rule_import.cc
+++ b/chromium/third_party/blink/renderer/core/css/style_rule_import.cc
@@ -69,18 +69,23 @@ void StyleRuleImport::NotifyFinished(Resource* resource) {
// Fallback to an insecure context parser if we don't have a parent style
// sheet.
- const CSSParserContext* context =
+ const CSSParserContext* parent_context =
StrictCSSParserContext(SecureContextMode::kInsecureContext);
if (parent_style_sheet_) {
document = parent_style_sheet_->SingleOwnerDocument();
- context = parent_style_sheet_->ParserContext();
+ parent_context = parent_style_sheet_->ParserContext();
}
- context = MakeGarbageCollected<CSSParserContext>(
- context, cached_style_sheet->GetResponse().ResponseUrl(),
+
+ // If either parent or resource is marked as ad, the new CSS will be tagged
+ // as an ad.
+ CSSParserContext* context = MakeGarbageCollected<CSSParserContext>(
+ parent_context, cached_style_sheet->GetResponse().ResponseUrl(),
cached_style_sheet->GetResponse().IsCorsSameOrigin(),
cached_style_sheet->GetReferrerPolicy(), cached_style_sheet->Encoding(),
document);
+ if (cached_style_sheet->GetResourceRequest().IsAdResource())
+ context->SetIsAdRelated();
style_sheet_ = MakeGarbageCollected<StyleSheetContents>(
context, cached_style_sheet->Url(), this);
@@ -143,9 +148,16 @@ void StyleRuleImport::RequestStyleSheet() {
root_sheet = sheet;
}
+ Referrer referrer = parent_style_sheet_->ParserContext()->GetReferrer();
ResourceLoaderOptions options;
options.initiator_info.name = fetch_initiator_type_names::kCSS;
- FetchParameters params(ResourceRequest(abs_url), options);
+ options.initiator_info.referrer = referrer.referrer;
+ ResourceRequest resource_request(abs_url);
+ resource_request.SetReferrerString(referrer.referrer);
+ resource_request.SetReferrerPolicy(referrer.referrer_policy);
+ if (parent_style_sheet_->ParserContext()->IsAdRelated())
+ resource_request.SetIsAdResource();
+ FetchParameters params(std::move(resource_request), options);
params.SetCharset(parent_style_sheet_->Charset());
params.SetFromOriginDirtyStyleSheet(origin_clean_ != OriginClean::kTrue);
loading_ = true;
diff --git a/chromium/third_party/blink/renderer/core/css/style_sheet_contents_test.cc b/chromium/third_party/blink/renderer/core/css/style_sheet_contents_test.cc
index c8f5bdd4eb1..2288523fb93 100644
--- a/chromium/third_party/blink/renderer/core/css/style_sheet_contents_test.cc
+++ b/chromium/third_party/blink/renderer/core/css/style_sheet_contents_test.cc
@@ -58,49 +58,4 @@ TEST(StyleSheetContentsTest, InsertFontFaceRule) {
EXPECT_TRUE(style_sheet->HasFontFaceRule());
}
-TEST(StyleSheetContentsTest, HasViewportRule) {
- auto* context = MakeGarbageCollected<CSSParserContext>(
- kHTMLStandardMode, SecureContextMode::kInsecureContext);
-
- auto* style_sheet = MakeGarbageCollected<StyleSheetContents>(context);
- style_sheet->ParseString("@viewport { width: 200px}");
- EXPECT_EQ(1U, style_sheet->RuleCount());
- EXPECT_TRUE(style_sheet->HasViewportRule());
-}
-
-TEST(StyleSheetContentsTest, HasViewportRuleAfterInsertion) {
- auto* context = MakeGarbageCollected<CSSParserContext>(
- kHTMLStandardMode, SecureContextMode::kInsecureContext);
-
- auto* style_sheet = MakeGarbageCollected<StyleSheetContents>(context);
- style_sheet->ParseString("body { color: pink }");
- EXPECT_EQ(1U, style_sheet->RuleCount());
- EXPECT_FALSE(style_sheet->HasViewportRule());
-
- style_sheet->SetMutable();
- style_sheet->WrapperInsertRule(
- CSSParser::ParseRule(context, style_sheet, "@viewport { width: 200px }"),
- 0);
- EXPECT_EQ(2U, style_sheet->RuleCount());
- EXPECT_TRUE(style_sheet->HasViewportRule());
-}
-
-TEST(StyleSheetContentsTest, HasViewportRuleAfterInsertionIntoMediaRule) {
- auto* context = MakeGarbageCollected<CSSParserContext>(
- kHTMLStandardMode, SecureContextMode::kInsecureContext);
-
- auto* style_sheet = MakeGarbageCollected<StyleSheetContents>(context);
- style_sheet->ParseString("@media {}");
- ASSERT_EQ(1U, style_sheet->RuleCount());
- EXPECT_FALSE(style_sheet->HasViewportRule());
-
- auto* media_rule = To<StyleRuleMedia>(style_sheet->RuleAt(0));
- style_sheet->SetMutable();
- media_rule->WrapperInsertRule(
- 0,
- CSSParser::ParseRule(context, style_sheet, "@viewport { width: 200px }"));
- EXPECT_EQ(1U, media_rule->ChildRules().size());
- EXPECT_TRUE(style_sheet->HasViewportRule());
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/svg.css b/chromium/third_party/blink/renderer/core/css/svg.css
index f031de7f650..a4783c4cb69 100644
--- a/chromium/third_party/blink/renderer/core/css/svg.css
+++ b/chromium/third_party/blink/renderer/core/css/svg.css
@@ -87,7 +87,7 @@ tspan, textPath {
/* TODO(crbug.com/976224): Support zoom on foreignObject */
foreignObject {
- -internal-effective-zoom: initial !important;
+ zoom: -internal-reset-effective !important;
}
/*
diff --git a/chromium/third_party/blink/renderer/core/css/vision_deficiency.cc b/chromium/third_party/blink/renderer/core/css/vision_deficiency.cc
index 6ab3903071e..5d29202ce64 100644
--- a/chromium/third_party/blink/renderer/core/css/vision_deficiency.cc
+++ b/chromium/third_party/blink/renderer/core/css/vision_deficiency.cc
@@ -3,24 +3,22 @@
// found in the LICENSE file.
#include "third_party/blink/renderer/core/css/vision_deficiency.h"
+#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
+#include "third_party/blink/renderer/platform/wtf/text/string_view.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
namespace blink {
-AtomicString CreateFilterDataUrl(AtomicString piece) {
- // clang-format off
- AtomicString url =
- "data:image/svg+xml,"
- "<svg xmlns=\"http://www.w3.org/2000/svg\">"
- "<filter id=\"f\">" +
- piece +
- "</filter>"
- "</svg>"
- "#f";
- // clang-format on
- return url;
+namespace {
+
+AtomicString CreateFilterDataUrl(const char* piece) {
+ return "data:image/svg+xml,<svg xmlns=\"http://www.w3.org/2000/svg\">"
+ "<filter id=\"f\">" +
+ StringView(piece) + "</filter></svg>#f";
}
+} // namespace
+
AtomicString CreateVisionDeficiencyFilterUrl(
VisionDeficiency vision_deficiency) {
// The filter color matrices are based on the following research paper:
diff --git a/chromium/third_party/blink/renderer/core/display_lock/BUILD.gn b/chromium/third_party/blink/renderer/core/display_lock/BUILD.gn
index b331bb226e7..e02ed4cb974 100644
--- a/chromium/third_party/blink/renderer/core/display_lock/BUILD.gn
+++ b/chromium/third_party/blink/renderer/core/display_lock/BUILD.gn
@@ -8,6 +8,8 @@ blink_core_sources("display_lock") {
sources = [
"display_lock_context.cc",
"display_lock_context.h",
+ "display_lock_document_state.cc",
+ "display_lock_document_state.h",
"display_lock_utilities.cc",
"display_lock_utilities.h",
"render_subtree_activation_event.cc",
diff --git a/chromium/third_party/blink/renderer/core/display_lock/display_lock_context.cc b/chromium/third_party/blink/renderer/core/display_lock/display_lock_context.cc
index a758b00fa8a..d389bf68298 100644
--- a/chromium/third_party/blink/renderer/core/display_lock/display_lock_context.cc
+++ b/chromium/third_party/blink/renderer/core/display_lock/display_lock_context.cc
@@ -11,6 +11,7 @@
#include "third_party/blink/renderer/core/accessibility/ax_object_cache.h"
#include "third_party/blink/renderer/core/css/style_change_reason.h"
#include "third_party/blink/renderer/core/css/style_recalc.h"
+#include "third_party/blink/renderer/core/display_lock/display_lock_document_state.h"
#include "third_party/blink/renderer/core/display_lock/display_lock_utilities.h"
#include "third_party/blink/renderer/core/display_lock/render_subtree_activation_event.h"
#include "third_party/blink/renderer/core/dom/document.h"
@@ -85,32 +86,32 @@ void RecordActivationReason(Document* document,
ordered_reason, number_of_reasons);
if (document && reason == DisplayLockActivationReason::kFindInPage)
- document->MarkHasFindInPageSubtreeVisibilityActiveMatch();
+ document->MarkHasFindInPageContentVisibilityActiveMatch();
}
} // namespace
DisplayLockContext::DisplayLockContext(Element* element)
: element_(element), document_(&element_->GetDocument()) {
- document_->AddDisplayLockContext(this);
+ document_->GetDisplayLockDocumentState().AddDisplayLockContext(this);
DetermineIfSubtreeHasFocus();
DetermineIfSubtreeHasSelection();
}
-void DisplayLockContext::SetRequestedState(ESubtreeVisibility state) {
+void DisplayLockContext::SetRequestedState(EContentVisibility state) {
if (state_ == state)
return;
state_ = state;
switch (state_) {
- case ESubtreeVisibility::kVisible:
+ case EContentVisibility::kVisible:
RequestUnlock();
break;
- case ESubtreeVisibility::kAuto:
+ case EContentVisibility::kAuto:
RequestLock(static_cast<uint16_t>(DisplayLockActivationReason::kAny));
break;
- case ESubtreeVisibility::kHidden:
+ case EContentVisibility::kHidden:
RequestLock(0u);
break;
- case ESubtreeVisibility::kHiddenMatchable:
+ case EContentVisibility::kHiddenMatchable:
RequestLock(
static_cast<uint16_t>(DisplayLockActivationReason::kAny) &
~static_cast<uint16_t>(DisplayLockActivationReason::kViewport));
@@ -124,7 +125,7 @@ void DisplayLockContext::SetRequestedState(ESubtreeVisibility state) {
// set that to false, since the mode has switched to something else. If we're
// switching _to_ 'auto' mode, this should already be false and will be a
// no-op.
- DCHECK(state_ != ESubtreeVisibility::kAuto ||
+ DCHECK(state_ != EContentVisibility::kAuto ||
!needs_deferred_not_intersecting_signal_);
needs_deferred_not_intersecting_signal_ = false;
UpdateLifecycleNotificationRegistration();
@@ -132,15 +133,21 @@ void DisplayLockContext::SetRequestedState(ESubtreeVisibility state) {
// Note that we call this here since the |state_| change is a render affecting
// state, but is tracked independently.
NotifyRenderAffectingStateChanged();
+
+ // Since our state changed, check if we need to create a scoped force update
+ // object.
+ element_->GetDocument().GetDisplayLockDocumentState().ForceLockIfNeeded(
+ element_.Get());
}
void DisplayLockContext::AdjustElementStyle(ComputedStyle* style) const {
- if (state_ == ESubtreeVisibility::kVisible)
+ if (state_ == EContentVisibility::kVisible)
return;
- // If not visible, element gains style and layout containment. If skipped, it
- // also gains size containment.
- // https://wicg.github.io/display-locking/#subtree-visibility
- auto contain = style->Contain() | kContainsStyle | kContainsLayout;
+ // If not visible, element gains style, layout, and paint containment. If
+ // skipped, it also gains size containment.
+ // https://wicg.github.io/display-locking/#content-visibility
+ auto contain =
+ style->Contain() | kContainsStyle | kContainsLayout | kContainsPaint;
if (IsLocked())
contain |= kContainsSize;
style->SetContain(contain);
@@ -177,18 +184,21 @@ void DisplayLockContext::UpdateDocumentBookkeeping(
if (was_locked != is_locked) {
if (is_locked)
- document_->AddLockedDisplayLock();
+ document_->GetDisplayLockDocumentState().AddLockedDisplayLock();
else
- document_->RemoveLockedDisplayLock();
+ document_->GetDisplayLockDocumentState().RemoveLockedDisplayLock();
}
bool was_locked_and_blocking = was_locked && all_activation_was_blocked;
bool is_locked_and_blocking = is_locked && all_activation_is_blocked;
if (was_locked_and_blocking != is_locked_and_blocking) {
- if (is_locked_and_blocking)
- document_->IncrementDisplayLockBlockingAllActivation();
- else
- document_->DecrementDisplayLockBlockingAllActivation();
+ if (is_locked_and_blocking) {
+ document_->GetDisplayLockDocumentState()
+ .IncrementDisplayLockBlockingAllActivation();
+ } else {
+ document_->GetDisplayLockDocumentState()
+ .DecrementDisplayLockBlockingAllActivation();
+ }
}
}
@@ -203,15 +213,17 @@ void DisplayLockContext::UpdateActivationObservationIfNeeded() {
// We require observation if we are in 'auto' mode and we're connected to a
// view.
bool should_observe =
- state_ == ESubtreeVisibility::kAuto && ConnectedToView();
+ state_ == EContentVisibility::kAuto && ConnectedToView();
if (is_observed_ == should_observe)
return;
is_observed_ = should_observe;
if (should_observe) {
- document_->RegisterDisplayLockActivationObservation(element_);
+ document_->GetDisplayLockDocumentState()
+ .RegisterDisplayLockActivationObservation(element_);
} else {
- document_->UnregisterDisplayLockActivationObservation(element_);
+ document_->GetDisplayLockDocumentState()
+ .UnregisterDisplayLockActivationObservation(element_);
// If we're not listening to viewport intersections, then we can assume
// we're not intersecting:
// 1. We might not be connected, in which case we're not intersecting.
@@ -257,7 +269,7 @@ void DisplayLockContext::Lock() {
return;
// There are two ways we can get locked:
- // 1. A new subtree-visibility property needs us to be locked.
+ // 1. A new content-visibility property needs us to be locked.
// 2. We're in 'auto' mode and we are not intersecting the viewport.
// In the first case, we are already in style processing, so we don't need to
// invalidate style. However, in the second case we invalidate style so that
@@ -297,7 +309,8 @@ void DisplayLockContext::Lock() {
bool DisplayLockContext::ShouldStyle(DisplayLockLifecycleTarget target) const {
return !is_locked_ || target == DisplayLockLifecycleTarget::kSelf ||
update_forced_ ||
- (document_->ActivatableDisplayLocksForced() &&
+ (document_->GetDisplayLockDocumentState()
+ .ActivatableDisplayLocksForced() &&
IsActivatable(DisplayLockActivationReason::kAny));
}
@@ -307,6 +320,11 @@ void DisplayLockContext::DidStyle(DisplayLockLifecycleTarget target) {
if (ForceUnlockIfNeeded())
return;
+ if (!IsLocked() && state_ != EContentVisibility::kVisible) {
+ UpdateActivationObservationIfNeeded();
+ NotifyRenderAffectingStateChanged();
+ }
+
if (blocked_style_traversal_type_ == kStyleUpdateSelf)
blocked_style_traversal_type_ = kStyleUpdateNotRequired;
} else {
@@ -320,7 +338,8 @@ void DisplayLockContext::DidStyle(DisplayLockLifecycleTarget target) {
bool DisplayLockContext::ShouldLayout(DisplayLockLifecycleTarget target) const {
return !is_locked_ || target == DisplayLockLifecycleTarget::kSelf ||
update_forced_ ||
- (document_->ActivatableDisplayLocksForced() &&
+ (document_->GetDisplayLockDocumentState()
+ .ActivatableDisplayLocksForced() &&
IsActivatable(DisplayLockActivationReason::kAny));
}
@@ -360,7 +379,7 @@ bool DisplayLockContext::IsActivatable(
}
void DisplayLockContext::FireActivationEvent(Element* activated_element) {
- DCHECK(RuntimeEnabledFeatures::CSSSubtreeVisibilityActivationEventEnabled());
+ DCHECK(RuntimeEnabledFeatures::CSSContentVisibilityActivationEventEnabled());
element_->DispatchEvent(
*MakeGarbageCollected<RenderSubtreeActivationEvent>(*activated_element));
}
@@ -375,10 +394,10 @@ void DisplayLockContext::CommitForActivationWithSignal(
DCHECK(ShouldCommitForActivation(DisplayLockActivationReason::kAny));
// TODO(vmpstr): Remove this when we have a beforematch event.
- if (RuntimeEnabledFeatures::CSSSubtreeVisibilityActivationEventEnabled()) {
+ if (RuntimeEnabledFeatures::CSSContentVisibilityActivationEventEnabled()) {
document_->EnqueueDisplayLockActivationTask(
WTF::Bind(&DisplayLockContext::FireActivationEvent,
- weak_factory_.GetWeakPtr(), WrapPersistent(activated_element)));
+ WrapWeakPersistent(this), WrapPersistent(activated_element)));
}
RecordActivationReason(document_, reason);
@@ -438,33 +457,33 @@ bool DisplayLockContext::ShouldCommitForActivation(
return IsActivatable(reason) && IsLocked();
}
-DisplayLockContext::ScopedForcedUpdate
-DisplayLockContext::GetScopedForcedUpdate() {
- if (!is_locked_)
- return ScopedForcedUpdate(nullptr);
-
- DCHECK(!update_forced_);
- update_forced_ = true;
- TRACE_EVENT_NESTABLE_ASYNC_BEGIN0(
- TRACE_DISABLED_BY_DEFAULT("blink.debug.display_lock"), "LockForced",
- TRACE_ID_LOCAL(this));
+void DisplayLockContext::NotifyForcedUpdateScopeStarted() {
+ ++update_forced_;
+ if (update_forced_ == 1) {
+ TRACE_EVENT_NESTABLE_ASYNC_BEGIN0(
+ TRACE_DISABLED_BY_DEFAULT("blink.debug.display_lock"), "LockForced",
+ TRACE_ID_LOCAL(this));
+ }
- // Now that the update is forced, we should ensure that style layout, and
- // prepaint code can reach it via dirty bits. Note that paint isn't a part of
- // this, since |update_forced_| doesn't force paint to happen. See
- // ShouldPaint().
- MarkForStyleRecalcIfNeeded();
- MarkForLayoutIfNeeded();
- MarkAncestorsForPrePaintIfNeeded();
- return ScopedForcedUpdate(this);
+ if (IsLocked()) {
+ // Now that the update is forced, we should ensure that style layout, and
+ // prepaint code can reach it via dirty bits. Note that paint isn't a part
+ // of this, since |update_forced_| doesn't force paint to happen. See
+ // ShouldPaint().
+ MarkForStyleRecalcIfNeeded();
+ MarkForLayoutIfNeeded();
+ MarkAncestorsForPrePaintIfNeeded();
+ }
}
void DisplayLockContext::NotifyForcedUpdateScopeEnded() {
DCHECK(update_forced_);
- update_forced_ = false;
- TRACE_EVENT_NESTABLE_ASYNC_END0(
- TRACE_DISABLED_BY_DEFAULT("blink.debug.display_lock"), "LockForced",
- TRACE_ID_LOCAL(this));
+ --update_forced_;
+ if (update_forced_ == 0) {
+ TRACE_EVENT_NESTABLE_ASYNC_END0(
+ TRACE_DISABLED_BY_DEFAULT("blink.debug.display_lock"), "LockForced",
+ TRACE_ID_LOCAL(this));
+ }
}
void DisplayLockContext::Unlock() {
@@ -479,7 +498,7 @@ void DisplayLockContext::Unlock() {
ScheduleAnimation();
// There are a few ways we can get unlocked:
- // 1. A new subtree-visibility property needs us to be ulocked.
+ // 1. A new content-visibility property needs us to be ulocked.
// 2. We're in 'auto' mode and we are intersecting the viewport.
// 3. We're activating in hidden-matchable or auto mode
// In the first case, we are already in style processing, so we don't need to
@@ -596,7 +615,7 @@ bool DisplayLockContext::MarkForLayoutIfNeeded() {
if (IsElementDirtyForLayout()) {
// Forces the marking of ancestors to happen, even if
// |DisplayLockContext::ShouldLayout()| returns false.
- base::AutoReset<bool> scoped_force(&update_forced_, true);
+ base::AutoReset<int> scoped_force(&update_forced_, update_forced_ + 1);
if (child_layout_was_blocked_) {
// We've previously blocked a child traversal when doing self-layout for
// the locked element, so we're marking it with child-needs-layout so that
@@ -678,6 +697,11 @@ bool DisplayLockContext::MarkForCompositingUpdatesIfNeeded() {
if (needs_compositing_requirements_update_)
layout_box->Layer()->SetNeedsCompositingRequirementsUpdate();
needs_compositing_requirements_update_ = false;
+
+ if (needs_compositing_dependent_flag_update_)
+ layout_box->Layer()->SetNeedsCompositingInputsUpdate();
+ needs_compositing_dependent_flag_update_ = false;
+
return true;
}
return false;
@@ -720,12 +744,14 @@ void DisplayLockContext::DidMoveToNewDocument(Document& old_document) {
DCHECK(element_);
document_ = &element_->GetDocument();
- old_document.RemoveDisplayLockContext(this);
- document_->AddDisplayLockContext(this);
+ old_document.GetDisplayLockDocumentState().RemoveDisplayLockContext(this);
+ document_->GetDisplayLockDocumentState().AddDisplayLockContext(this);
if (is_observed_) {
- old_document.UnregisterDisplayLockActivationObservation(element_);
- document_->RegisterDisplayLockActivationObservation(element_);
+ old_document.GetDisplayLockDocumentState()
+ .UnregisterDisplayLockActivationObservation(element_);
+ document_->GetDisplayLockDocumentState()
+ .RegisterDisplayLockActivationObservation(element_);
}
// Since we're observing the lifecycle updates, ensure that we listen to the
@@ -741,11 +767,13 @@ void DisplayLockContext::DidMoveToNewDocument(Document& old_document) {
}
if (IsLocked()) {
- old_document.RemoveLockedDisplayLock();
- document_->AddLockedDisplayLock();
+ old_document.GetDisplayLockDocumentState().RemoveLockedDisplayLock();
+ document_->GetDisplayLockDocumentState().AddLockedDisplayLock();
if (!IsActivatable(DisplayLockActivationReason::kAny)) {
- old_document.DecrementDisplayLockBlockingAllActivation();
- document_->IncrementDisplayLockBlockingAllActivation();
+ old_document.GetDisplayLockDocumentState()
+ .DecrementDisplayLockBlockingAllActivation();
+ document_->GetDisplayLockDocumentState()
+ .IncrementDisplayLockBlockingAllActivation();
}
}
@@ -811,7 +839,7 @@ const char* DisplayLockContext::ShouldForceUnlock() const {
// just optimistically assume that we have all of the right containment in
// place. See crbug.com/926276 for more information.
if (element_->NeedsStyleRecalc()) {
- DCHECK(DisplayLockUtilities::NearestLockedExclusiveAncestor(*element_));
+ DCHECK(DisplayLockUtilities::LockedAncestorPreventingStyle(*element_));
return nullptr;
}
@@ -863,7 +891,8 @@ bool DisplayLockContext::ForceUnlockIfNeeded() {
// commit() isn't in progress, the web author won't know that the element
// got unlocked. Figure out how to notify the author.
if (auto* reason = ShouldForceUnlock()) {
- is_locked_ = false;
+ if (IsLocked())
+ Unlock();
return true;
}
return false;
@@ -946,9 +975,9 @@ void DisplayLockContext::NotifyRenderAffectingStateChanged() {
};
// Check that we're visible if and only if lock has not been requested.
- DCHECK(state_ == ESubtreeVisibility::kVisible ||
+ DCHECK(state_ == EContentVisibility::kVisible ||
state(RenderAffectingState::kLockRequested));
- DCHECK(state_ != ESubtreeVisibility::kVisible ||
+ DCHECK(state_ != EContentVisibility::kVisible ||
!state(RenderAffectingState::kLockRequested));
// We should be locked if the lock has been requested (the above DCHECKs
@@ -960,7 +989,7 @@ void DisplayLockContext::NotifyRenderAffectingStateChanged() {
// selection.
bool should_be_locked =
state(RenderAffectingState::kLockRequested) &&
- (state_ != ESubtreeVisibility::kAuto ||
+ (state_ != EContentVisibility::kAuto ||
(!state(RenderAffectingState::kIntersectsViewport) &&
!state(RenderAffectingState::kSubtreeHasFocus) &&
!state(RenderAffectingState::kSubtreeHasSelection)));
@@ -977,21 +1006,4 @@ void DisplayLockContext::Trace(Visitor* visitor) {
visitor->Trace(whitespace_reattach_set_);
}
-// Scoped objects implementation
-// -----------------------------------------------
-DisplayLockContext::ScopedForcedUpdate::ScopedForcedUpdate(
- DisplayLockContext* context)
- : context_(context) {}
-
-DisplayLockContext::ScopedForcedUpdate::ScopedForcedUpdate(
- ScopedForcedUpdate&& other)
- : context_(other.context_) {
- other.context_ = nullptr;
-}
-
-DisplayLockContext::ScopedForcedUpdate::~ScopedForcedUpdate() {
- if (context_)
- context_->NotifyForcedUpdateScopeEnded();
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/display_lock/display_lock_context.h b/chromium/third_party/blink/renderer/core/display_lock/display_lock_context.h
index 870b662ed60..57f785686f4 100644
--- a/chromium/third_party/blink/renderer/core/display_lock/display_lock_context.h
+++ b/chromium/third_party/blink/renderer/core/display_lock/display_lock_context.h
@@ -75,27 +75,11 @@ class CORE_EXPORT DisplayLockContext final
kStyleUpdateDescendants
};
- // See GetScopedForcedUpdate() for description.
- class CORE_EXPORT ScopedForcedUpdate {
- DISALLOW_NEW();
-
- public:
- ScopedForcedUpdate(ScopedForcedUpdate&&);
- ~ScopedForcedUpdate();
-
- private:
- friend class DisplayLockContext;
-
- ScopedForcedUpdate(DisplayLockContext*);
-
- UntracedMember<DisplayLockContext> context_ = nullptr;
- };
-
explicit DisplayLockContext(Element*);
~DisplayLockContext() = default;
- // Called by style to update the current state of subtree-visibility.
- void SetRequestedState(ESubtreeVisibility state);
+ // Called by style to update the current state of content-visibility.
+ void SetRequestedState(EContentVisibility state);
// Called by style to adjust the element's style based on the current state.
void AdjustElementStyle(ComputedStyle* style) const;
@@ -139,13 +123,6 @@ class CORE_EXPORT DisplayLockContext final
// Returns true if this context is locked.
bool IsLocked() const { return is_locked_; }
- // Returns a ScopedForcedUpdate object which for the duration of its lifetime
- // will allow updates to happen on this element's subtree. For the element
- // itself, the frame rect will still be the same as at the time the lock was
- // acquired. Only one ScopedForcedUpdate can be retrieved from the same
- // context at a time.
- ScopedForcedUpdate GetScopedForcedUpdate();
-
bool UpdateForced() const { return update_forced_; }
// This is called when the element with which this context is associated is
@@ -180,6 +157,9 @@ class CORE_EXPORT DisplayLockContext final
void NotifyCompositingRequirementsUpdateWasBlocked() {
needs_compositing_requirements_update_ = true;
}
+ void NotifyCompositingDescendantDependentFlagUpdateWasBlocked() {
+ needs_compositing_dependent_flag_update_ = true;
+ }
// Notify this element will be disconnected.
void NotifyWillDisconnect();
@@ -218,6 +198,10 @@ class CORE_EXPORT DisplayLockContext final
void Trace(Visitor*) override;
private:
+ // Give access to |NotifyForcedUpdateScopeStarted()| and
+ // |NotifyForcedUpdateScopeEnded()|.
+ friend class DisplayLockUtilities;
+
// Test friends.
friend class DisplayLockContextRenderingTest;
friend class DisplayLockContextTest;
@@ -230,6 +214,10 @@ class CORE_EXPORT DisplayLockContext final
// the subtree rooted at this element should be rendered.
void RequestUnlock();
+ // Called in |DisplayLockUtilities| to notify the state of scope.
+ void NotifyForcedUpdateScopeStarted();
+ void NotifyForcedUpdateScopeEnded();
+
// Records the locked context counts on the document as well as context that
// block all activation.
void UpdateDocumentBookkeeping(bool was_locked,
@@ -261,10 +249,6 @@ class CORE_EXPORT DisplayLockContext final
bool IsElementDirtyForLayout() const;
bool IsElementDirtyForPrePaint() const;
- // When ScopedForcedUpdate is destroyed, it calls this function. See
- // GetScopedForcedUpdate() for more information.
- void NotifyForcedUpdateScopeEnded();
-
// Helper to schedule an animation to delay lifecycle updates for the next
// frame.
void ScheduleAnimation();
@@ -317,7 +301,7 @@ class CORE_EXPORT DisplayLockContext final
WeakMember<Element> element_;
WeakMember<Document> document_;
- ESubtreeVisibility state_ = ESubtreeVisibility::kVisible;
+ EContentVisibility state_ = EContentVisibility::kVisible;
// See StyleEngine's |whitespace_reattach_set_|.
// Set of elements that had at least one rendered children removed
@@ -328,7 +312,8 @@ class CORE_EXPORT DisplayLockContext final
// style recalc on them.
HeapHashSet<Member<Element>> whitespace_reattach_set_;
- bool update_forced_ = false;
+ // If non-zero, then the update has been forced.
+ int update_forced_ = 0;
StyleType blocked_style_traversal_type_ = kStyleUpdateNotRequired;
// Signifies whether we've blocked a layout tree reattachment on |element_|'s
@@ -340,6 +325,7 @@ class CORE_EXPORT DisplayLockContext final
bool needs_prepaint_subtree_walk_ = false;
bool needs_graphics_layer_collection_ = false;
bool needs_compositing_requirements_update_ = false;
+ bool needs_compositing_dependent_flag_update_ = false;
// Will be true if child traversal was blocked on a previous layout run on the
// locked element. We need to keep track of this to ensure that on the next
@@ -378,10 +364,6 @@ class CORE_EXPORT DisplayLockContext final
bool render_affecting_state_[static_cast<int>(
RenderAffectingState::kNumRenderAffectingStates)] = {false};
-
- // TODO(vmpstr): This is only needed while we're still sending activation
- // events.
- base::WeakPtrFactory<DisplayLockContext> weak_factory_{this};
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/display_lock/display_lock_context_test.cc b/chromium/third_party/blink/renderer/core/display_lock/display_lock_context_test.cc
index bb877c91f75..4a9864200b7 100644
--- a/chromium/third_party/blink/renderer/core/display_lock/display_lock_context_test.cc
+++ b/chromium/third_party/blink/renderer/core/display_lock/display_lock_context_test.cc
@@ -12,6 +12,8 @@
#include "mojo/public/cpp/bindings/receiver.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
#include "third_party/blink/renderer/core/css/style_change_reason.h"
+#include "third_party/blink/renderer/core/display_lock/display_lock_document_state.h"
+#include "third_party/blink/renderer/core/display_lock/display_lock_utilities.h"
#include "third_party/blink/renderer/core/dom/dom_token_list.h"
#include "third_party/blink/renderer/core/dom/events/native_event_listener.h"
#include "third_party/blink/renderer/core/dom/node_computed_style.h"
@@ -23,6 +25,7 @@
#include "third_party/blink/renderer/core/frame/frame_test_helpers.h"
#include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
#include "third_party/blink/renderer/core/html/html_template_element.h"
+#include "third_party/blink/renderer/core/paint/paint_layer.h"
#include "third_party/blink/renderer/core/style/computed_style.h"
#include "third_party/blink/renderer/core/testing/core_unit_test_helper.h"
#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
@@ -87,18 +90,16 @@ class DisplayLockEmptyEventListener final : public NativeEventListener {
};
} // namespace
-class DisplayLockContextTest : public testing::Test,
- private ScopedCSSSubtreeVisibilityHiddenMatchableForTest {
+class DisplayLockContextTest
+ : public testing::Test,
+ private ScopedCSSContentVisibilityHiddenMatchableForTest {
public:
- DisplayLockContextTest() : ScopedCSSSubtreeVisibilityHiddenMatchableForTest(true) {}
+ DisplayLockContextTest()
+ : ScopedCSSContentVisibilityHiddenMatchableForTest(true) {}
- void SetUp() override {
- web_view_helper_.Initialize();
- }
+ void SetUp() override { web_view_helper_.Initialize(); }
- void TearDown() override {
- web_view_helper_.Reset();
- }
+ void TearDown() override { web_view_helper_.Reset(); }
Document& GetDocument() {
return *static_cast<Document*>(
@@ -128,7 +129,7 @@ class DisplayLockContextTest : public testing::Test,
void LockElement(Element& element, bool activatable) {
StringBuilder value;
- value.Append("subtree-visibility: hidden");
+ value.Append("content-visibility: hidden");
if (activatable)
value.Append("-matchable");
element.setAttribute(html_names::kStyleAttr, value.ToAtomicString());
@@ -142,7 +143,7 @@ class DisplayLockContextTest : public testing::Test,
}
void UnlockImmediate(DisplayLockContext* context) {
- context->SetRequestedState(ESubtreeVisibility::kVisible);
+ context->SetRequestedState(EContentVisibility::kVisible);
}
bool GraphicsLayerNeedsCollection(DisplayLockContext* context) const {
@@ -201,12 +202,12 @@ TEST_F(DisplayLockContextTest, LockAfterAppendStyleDirtyBits) {
DisplayLockLifecycleTarget::kChildren));
EXPECT_FALSE(element->GetDisplayLockContext()->ShouldPaint(
DisplayLockLifecycleTarget::kChildren));
- EXPECT_EQ(GetDocument().LockedDisplayLockCount(), 1);
+ EXPECT_EQ(
+ GetDocument().GetDisplayLockDocumentState().LockedDisplayLockCount(), 1);
// If the element is dirty, style recalc would handle it in the next recalc.
- element->setAttribute(
- html_names::kStyleAttr,
- "subtree-visibility: hidden; color: red;");
+ element->setAttribute(html_names::kStyleAttr,
+ "content-visibility: hidden; color: red;");
EXPECT_TRUE(GetDocument().body()->ChildNeedsStyleRecalc());
EXPECT_TRUE(element->NeedsStyleRecalc());
EXPECT_FALSE(element->ChildNeedsStyleRecalc());
@@ -236,9 +237,8 @@ TEST_F(DisplayLockContextTest, LockAfterAppendStyleDirtyBits) {
EXPECT_FALSE(child->NeedsStyleRecalc());
// Lock the child.
- child->setAttribute(
- html_names::kStyleAttr,
- "subtree-visibility: hidden; color: blue;");
+ child->setAttribute(html_names::kStyleAttr,
+ "content-visibility: hidden; color: blue;");
UpdateAllLifecyclePhasesForTest();
EXPECT_FALSE(GetDocument().body()->ChildNeedsStyleRecalc());
@@ -678,8 +678,12 @@ TEST_F(DisplayLockContextTest, CallUpdateStyleAndLayoutAfterChange) {
DisplayLockLifecycleTarget::kChildren));
EXPECT_FALSE(element->GetDisplayLockContext()->ShouldPaint(
DisplayLockLifecycleTarget::kChildren));
- EXPECT_EQ(GetDocument().LockedDisplayLockCount(), 1);
- EXPECT_EQ(GetDocument().DisplayLockBlockingAllActivationCount(), 1);
+ EXPECT_EQ(
+ GetDocument().GetDisplayLockDocumentState().LockedDisplayLockCount(), 1);
+ EXPECT_EQ(GetDocument()
+ .GetDisplayLockDocumentState()
+ .DisplayLockBlockingAllActivationCount(),
+ 1);
EXPECT_FALSE(element->NeedsStyleRecalc());
EXPECT_FALSE(element->ChildNeedsStyleRecalc());
@@ -747,7 +751,7 @@ TEST_F(DisplayLockContextTest, CallUpdateStyleAndLayoutAfterChangeCSS) {
background: blue;
}
.locked {
- subtree-visibility: hidden;
+ content-visibility: hidden;
}
</style>
<body><div class=locked id="container"><b>t</b>esting<div id=inner></div></div></body>
@@ -762,8 +766,12 @@ TEST_F(DisplayLockContextTest, CallUpdateStyleAndLayoutAfterChangeCSS) {
DisplayLockLifecycleTarget::kChildren));
EXPECT_FALSE(element->GetDisplayLockContext()->ShouldPaint(
DisplayLockLifecycleTarget::kChildren));
- EXPECT_EQ(GetDocument().LockedDisplayLockCount(), 1);
- EXPECT_EQ(GetDocument().DisplayLockBlockingAllActivationCount(), 1);
+ EXPECT_EQ(
+ GetDocument().GetDisplayLockDocumentState().LockedDisplayLockCount(), 1);
+ EXPECT_EQ(GetDocument()
+ .GetDisplayLockDocumentState()
+ .DisplayLockBlockingAllActivationCount(),
+ 1);
EXPECT_TRUE(ReattachWasBlocked(element->GetDisplayLockContext()));
// Note that we didn't create a layout object for inner, since the layout tree
@@ -814,8 +822,12 @@ TEST_F(DisplayLockContextTest, LockedElementAndDescendantsAreNotFocusable) {
ASSERT_TRUE(GetDocument().getElementById("textfield")->IsKeyboardFocusable());
ASSERT_TRUE(GetDocument().getElementById("textfield")->IsMouseFocusable());
ASSERT_TRUE(GetDocument().getElementById("textfield")->IsFocusable());
- EXPECT_EQ(GetDocument().LockedDisplayLockCount(), 0);
- EXPECT_EQ(GetDocument().DisplayLockBlockingAllActivationCount(), 0);
+ EXPECT_EQ(
+ GetDocument().GetDisplayLockDocumentState().LockedDisplayLockCount(), 0);
+ EXPECT_EQ(GetDocument()
+ .GetDisplayLockDocumentState()
+ .DisplayLockBlockingAllActivationCount(),
+ 0);
auto* element = GetDocument().getElementById("container");
LockElement(*element, false);
@@ -827,8 +839,12 @@ TEST_F(DisplayLockContextTest, LockedElementAndDescendantsAreNotFocusable) {
DisplayLockLifecycleTarget::kChildren));
EXPECT_FALSE(element->GetDisplayLockContext()->ShouldPaint(
DisplayLockLifecycleTarget::kChildren));
- EXPECT_EQ(GetDocument().LockedDisplayLockCount(), 1);
- EXPECT_EQ(GetDocument().DisplayLockBlockingAllActivationCount(), 1);
+ EXPECT_EQ(
+ GetDocument().GetDisplayLockDocumentState().LockedDisplayLockCount(), 1);
+ EXPECT_EQ(GetDocument()
+ .GetDisplayLockDocumentState()
+ .DisplayLockBlockingAllActivationCount(),
+ 1);
// The input should not be focusable now.
EXPECT_FALSE(
@@ -852,8 +868,12 @@ TEST_F(DisplayLockContextTest, LockedElementAndDescendantsAreNotFocusable) {
UpdateAllLifecyclePhasesForTest();
- EXPECT_EQ(GetDocument().LockedDisplayLockCount(), 0);
- EXPECT_EQ(GetDocument().DisplayLockBlockingAllActivationCount(), 0);
+ EXPECT_EQ(
+ GetDocument().GetDisplayLockDocumentState().LockedDisplayLockCount(), 0);
+ EXPECT_EQ(GetDocument()
+ .GetDisplayLockDocumentState()
+ .DisplayLockBlockingAllActivationCount(),
+ 0);
EXPECT_TRUE(GetDocument().getElementById("textfield")->IsKeyboardFocusable());
EXPECT_TRUE(GetDocument().getElementById("textfield")->IsMouseFocusable());
EXPECT_TRUE(GetDocument().getElementById("textfield")->IsFocusable());
@@ -899,8 +919,12 @@ TEST_F(DisplayLockContextTest, DisplayLockPreventsActivation) {
LockElement(*container, false);
- EXPECT_EQ(GetDocument().LockedDisplayLockCount(), 1);
- EXPECT_EQ(GetDocument().DisplayLockBlockingAllActivationCount(), 1);
+ EXPECT_EQ(
+ GetDocument().GetDisplayLockDocumentState().LockedDisplayLockCount(), 1);
+ EXPECT_EQ(GetDocument()
+ .GetDisplayLockDocumentState()
+ .DisplayLockBlockingAllActivationCount(),
+ 1);
EXPECT_FALSE(
host->DisplayLockPreventsActivation(DisplayLockActivationReason::kAny));
EXPECT_TRUE(container->DisplayLockPreventsActivation(
@@ -914,8 +938,12 @@ TEST_F(DisplayLockContextTest, DisplayLockPreventsActivation) {
CommitElement(*container);
- EXPECT_EQ(GetDocument().LockedDisplayLockCount(), 0);
- EXPECT_EQ(GetDocument().DisplayLockBlockingAllActivationCount(), 0);
+ EXPECT_EQ(
+ GetDocument().GetDisplayLockDocumentState().LockedDisplayLockCount(), 0);
+ EXPECT_EQ(GetDocument()
+ .GetDisplayLockDocumentState()
+ .DisplayLockBlockingAllActivationCount(),
+ 0);
EXPECT_FALSE(
host->DisplayLockPreventsActivation(DisplayLockActivationReason::kAny));
EXPECT_FALSE(container->DisplayLockPreventsActivation(
@@ -925,8 +953,12 @@ TEST_F(DisplayLockContextTest, DisplayLockPreventsActivation) {
UpdateAllLifecyclePhasesForTest();
- EXPECT_EQ(GetDocument().LockedDisplayLockCount(), 0);
- EXPECT_EQ(GetDocument().DisplayLockBlockingAllActivationCount(), 0);
+ EXPECT_EQ(
+ GetDocument().GetDisplayLockDocumentState().LockedDisplayLockCount(), 0);
+ EXPECT_EQ(GetDocument()
+ .GetDisplayLockDocumentState()
+ .DisplayLockBlockingAllActivationCount(),
+ 0);
EXPECT_FALSE(
host->DisplayLockPreventsActivation(DisplayLockActivationReason::kAny));
EXPECT_FALSE(container->DisplayLockPreventsActivation(
@@ -936,14 +968,18 @@ TEST_F(DisplayLockContextTest, DisplayLockPreventsActivation) {
SetHtmlInnerHTML(R"HTML(
<body>
- <div id="nonviewport" style="subtree-visibility: hidden-matchable">
+ <div id="nonviewport" style="content-visibility: hidden-matchable">
</div>
</body>
)HTML");
auto* non_viewport = GetDocument().getElementById("nonviewport");
- EXPECT_EQ(GetDocument().LockedDisplayLockCount(), 1);
- EXPECT_EQ(GetDocument().DisplayLockBlockingAllActivationCount(), 0);
+ EXPECT_EQ(
+ GetDocument().GetDisplayLockDocumentState().LockedDisplayLockCount(), 1);
+ EXPECT_EQ(GetDocument()
+ .GetDisplayLockDocumentState()
+ .DisplayLockBlockingAllActivationCount(),
+ 0);
EXPECT_FALSE(non_viewport->DisplayLockPreventsActivation(
DisplayLockActivationReason::kAny));
@@ -987,8 +1023,12 @@ TEST_F(DisplayLockContextTest,
DisplayLockLifecycleTarget::kChildren));
EXPECT_FALSE(element->GetDisplayLockContext()->ShouldPaint(
DisplayLockLifecycleTarget::kChildren));
- EXPECT_EQ(GetDocument().LockedDisplayLockCount(), 1);
- EXPECT_EQ(GetDocument().DisplayLockBlockingAllActivationCount(), 1);
+ EXPECT_EQ(
+ GetDocument().GetDisplayLockDocumentState().LockedDisplayLockCount(), 1);
+ EXPECT_EQ(GetDocument()
+ .GetDisplayLockDocumentState()
+ .DisplayLockBlockingAllActivationCount(),
+ 1);
// The input should not be focusable now.
EXPECT_FALSE(text_field->IsKeyboardFocusable());
@@ -1018,8 +1058,12 @@ TEST_F(DisplayLockContextTest, LockedCountsWithMultipleLocks) {
</body>
)HTML");
- EXPECT_EQ(GetDocument().LockedDisplayLockCount(), 0);
- EXPECT_EQ(GetDocument().DisplayLockBlockingAllActivationCount(), 0);
+ EXPECT_EQ(
+ GetDocument().GetDisplayLockDocumentState().LockedDisplayLockCount(), 0);
+ EXPECT_EQ(GetDocument()
+ .GetDisplayLockDocumentState()
+ .DisplayLockBlockingAllActivationCount(),
+ 0);
auto* one = GetDocument().getElementById("one");
auto* two = GetDocument().getElementById("two");
@@ -1027,42 +1071,66 @@ TEST_F(DisplayLockContextTest, LockedCountsWithMultipleLocks) {
LockElement(*one, false);
- EXPECT_EQ(GetDocument().LockedDisplayLockCount(), 1);
- EXPECT_EQ(GetDocument().DisplayLockBlockingAllActivationCount(), 1);
+ EXPECT_EQ(
+ GetDocument().GetDisplayLockDocumentState().LockedDisplayLockCount(), 1);
+ EXPECT_EQ(GetDocument()
+ .GetDisplayLockDocumentState()
+ .DisplayLockBlockingAllActivationCount(),
+ 1);
LockElement(*two, false);
// Because |two| is nested, the lock counts aren't updated since the lock
// doesn't actually take effect until style can determine that we should lock.
- EXPECT_EQ(GetDocument().LockedDisplayLockCount(), 1);
- EXPECT_EQ(GetDocument().DisplayLockBlockingAllActivationCount(), 1);
+ EXPECT_EQ(
+ GetDocument().GetDisplayLockDocumentState().LockedDisplayLockCount(), 1);
+ EXPECT_EQ(GetDocument()
+ .GetDisplayLockDocumentState()
+ .DisplayLockBlockingAllActivationCount(),
+ 1);
LockElement(*three, false);
- EXPECT_EQ(GetDocument().LockedDisplayLockCount(), 2);
- EXPECT_EQ(GetDocument().DisplayLockBlockingAllActivationCount(), 2);
+ EXPECT_EQ(
+ GetDocument().GetDisplayLockDocumentState().LockedDisplayLockCount(), 2);
+ EXPECT_EQ(GetDocument()
+ .GetDisplayLockDocumentState()
+ .DisplayLockBlockingAllActivationCount(),
+ 2);
// Now commit the outer lock.
CommitElement(*one);
// The counts remain the same since now the inner lock is determined to be
// locked.
- EXPECT_EQ(GetDocument().LockedDisplayLockCount(), 2);
- EXPECT_EQ(GetDocument().DisplayLockBlockingAllActivationCount(), 2);
+ EXPECT_EQ(
+ GetDocument().GetDisplayLockDocumentState().LockedDisplayLockCount(), 2);
+ EXPECT_EQ(GetDocument()
+ .GetDisplayLockDocumentState()
+ .DisplayLockBlockingAllActivationCount(),
+ 2);
// Commit the inner lock.
CommitElement(*two);
// Both inner and outer locks should have committed.
- EXPECT_EQ(GetDocument().LockedDisplayLockCount(), 1);
- EXPECT_EQ(GetDocument().DisplayLockBlockingAllActivationCount(), 1);
+ EXPECT_EQ(
+ GetDocument().GetDisplayLockDocumentState().LockedDisplayLockCount(), 1);
+ EXPECT_EQ(GetDocument()
+ .GetDisplayLockDocumentState()
+ .DisplayLockBlockingAllActivationCount(),
+ 1);
// Commit the sibling lock.
CommitElement(*three);
// Both inner and outer locks should have committed.
- EXPECT_EQ(GetDocument().LockedDisplayLockCount(), 0);
- EXPECT_EQ(GetDocument().DisplayLockBlockingAllActivationCount(), 0);
+ EXPECT_EQ(
+ GetDocument().GetDisplayLockDocumentState().LockedDisplayLockCount(), 0);
+ EXPECT_EQ(GetDocument()
+ .GetDisplayLockDocumentState()
+ .DisplayLockBlockingAllActivationCount(),
+ 0);
}
TEST_F(DisplayLockContextTest, ActivatableNotCountedAsBlocking) {
@@ -1081,8 +1149,12 @@ TEST_F(DisplayLockContextTest, ActivatableNotCountedAsBlocking) {
</body>
)HTML");
- EXPECT_EQ(GetDocument().LockedDisplayLockCount(), 0);
- EXPECT_EQ(GetDocument().DisplayLockBlockingAllActivationCount(), 0);
+ EXPECT_EQ(
+ GetDocument().GetDisplayLockDocumentState().LockedDisplayLockCount(), 0);
+ EXPECT_EQ(GetDocument()
+ .GetDisplayLockDocumentState()
+ .DisplayLockBlockingAllActivationCount(),
+ 0);
auto* activatable = GetDocument().getElementById("activatable");
auto* non_activatable = GetDocument().getElementById("nonActivatable");
@@ -1094,29 +1166,45 @@ TEST_F(DisplayLockContextTest, ActivatableNotCountedAsBlocking) {
LockElement(*activatable, true);
- EXPECT_EQ(GetDocument().LockedDisplayLockCount(), 1);
- EXPECT_EQ(GetDocument().DisplayLockBlockingAllActivationCount(), 0);
+ EXPECT_EQ(
+ GetDocument().GetDisplayLockDocumentState().LockedDisplayLockCount(), 1);
+ EXPECT_EQ(GetDocument()
+ .GetDisplayLockDocumentState()
+ .DisplayLockBlockingAllActivationCount(),
+ 0);
EXPECT_TRUE(activatable->GetDisplayLockContext()->IsActivatable(
DisplayLockActivationReason::kAny));
LockElement(*non_activatable, false);
- EXPECT_EQ(GetDocument().LockedDisplayLockCount(), 2);
- EXPECT_EQ(GetDocument().DisplayLockBlockingAllActivationCount(), 1);
+ EXPECT_EQ(
+ GetDocument().GetDisplayLockDocumentState().LockedDisplayLockCount(), 2);
+ EXPECT_EQ(GetDocument()
+ .GetDisplayLockDocumentState()
+ .DisplayLockBlockingAllActivationCount(),
+ 1);
EXPECT_FALSE(non_activatable->GetDisplayLockContext()->IsActivatable(
DisplayLockActivationReason::kAny));
// Now commit the lock for |non_activatable|.
CommitElement(*non_activatable);
- EXPECT_EQ(GetDocument().LockedDisplayLockCount(), 1);
- EXPECT_EQ(GetDocument().DisplayLockBlockingAllActivationCount(), 0);
+ EXPECT_EQ(
+ GetDocument().GetDisplayLockDocumentState().LockedDisplayLockCount(), 1);
+ EXPECT_EQ(GetDocument()
+ .GetDisplayLockDocumentState()
+ .DisplayLockBlockingAllActivationCount(),
+ 0);
// Re-acquire the lock for |activatable| again with the activatable flag.
LockElement(*activatable, true);
- EXPECT_EQ(GetDocument().LockedDisplayLockCount(), 1);
- EXPECT_EQ(GetDocument().DisplayLockBlockingAllActivationCount(), 0);
+ EXPECT_EQ(
+ GetDocument().GetDisplayLockDocumentState().LockedDisplayLockCount(), 1);
+ EXPECT_EQ(GetDocument()
+ .GetDisplayLockDocumentState()
+ .DisplayLockBlockingAllActivationCount(),
+ 0);
EXPECT_TRUE(activatable->GetDisplayLockContext()->IsActivatable(
DisplayLockActivationReason::kAny));
}
@@ -1143,8 +1231,12 @@ TEST_F(DisplayLockContextTest, ElementInTemplate) {
</body>
)HTML");
- EXPECT_EQ(GetDocument().LockedDisplayLockCount(), 0);
- EXPECT_EQ(GetDocument().DisplayLockBlockingAllActivationCount(), 0);
+ EXPECT_EQ(
+ GetDocument().GetDisplayLockDocumentState().LockedDisplayLockCount(), 0);
+ EXPECT_EQ(GetDocument()
+ .GetDisplayLockDocumentState()
+ .DisplayLockBlockingAllActivationCount(),
+ 0);
auto* template_el =
To<HTMLTemplateElement>(GetDocument().getElementById("template"));
@@ -1154,8 +1246,12 @@ TEST_F(DisplayLockContextTest, ElementInTemplate) {
// Try to lock an element in a template.
LockElement(*child, false);
- EXPECT_EQ(GetDocument().LockedDisplayLockCount(), 0);
- EXPECT_EQ(GetDocument().DisplayLockBlockingAllActivationCount(), 0);
+ EXPECT_EQ(
+ GetDocument().GetDisplayLockDocumentState().LockedDisplayLockCount(), 0);
+ EXPECT_EQ(GetDocument()
+ .GetDisplayLockDocumentState()
+ .DisplayLockBlockingAllActivationCount(),
+ 0);
EXPECT_FALSE(child->GetDisplayLockContext());
// Commit also works, but does nothing.
@@ -1172,22 +1268,29 @@ TEST_F(DisplayLockContextTest, ElementInTemplate) {
// These should be 0, since container is display: none, so locking its child
// is not visible to style.
- EXPECT_EQ(GetDocument().LockedDisplayLockCount(), 0);
- EXPECT_EQ(GetDocument().DisplayLockBlockingAllActivationCount(), 0);
+ EXPECT_EQ(
+ GetDocument().GetDisplayLockDocumentState().LockedDisplayLockCount(), 0);
+ EXPECT_EQ(GetDocument()
+ .GetDisplayLockDocumentState()
+ .DisplayLockBlockingAllActivationCount(),
+ 0);
ASSERT_FALSE(document_child->GetDisplayLockContext());
container->setAttribute(html_names::kStyleAttr, "display: block;");
EXPECT_TRUE(container->NeedsStyleRecalc());
UpdateAllLifecyclePhasesForTest();
- EXPECT_EQ(GetDocument().LockedDisplayLockCount(), 1);
- EXPECT_EQ(GetDocument().DisplayLockBlockingAllActivationCount(), 1);
+ EXPECT_EQ(
+ GetDocument().GetDisplayLockDocumentState().LockedDisplayLockCount(), 1);
+ EXPECT_EQ(GetDocument()
+ .GetDisplayLockDocumentState()
+ .DisplayLockBlockingAllActivationCount(),
+ 1);
ASSERT_TRUE(document_child->GetDisplayLockContext());
EXPECT_TRUE(document_child->GetDisplayLockContext()->IsLocked());
- document_child->setAttribute(
- html_names::kStyleAttr,
- "subtree-visibility: hidden; color: red;");
+ document_child->setAttribute(html_names::kStyleAttr,
+ "content-visibility: hidden; color: red;");
UpdateAllLifecyclePhasesForTest();
EXPECT_FALSE(document_child->NeedsStyleRecalc());
@@ -1197,8 +1300,12 @@ TEST_F(DisplayLockContextTest, ElementInTemplate) {
UpdateAllLifecyclePhasesForTest();
EXPECT_FALSE(document_child->GetDisplayLockContext()->IsLocked());
- EXPECT_EQ(GetDocument().LockedDisplayLockCount(), 0);
- EXPECT_EQ(GetDocument().DisplayLockBlockingAllActivationCount(), 0);
+ EXPECT_EQ(
+ GetDocument().GetDisplayLockDocumentState().LockedDisplayLockCount(), 0);
+ EXPECT_EQ(GetDocument()
+ .GetDisplayLockDocumentState()
+ .DisplayLockBlockingAllActivationCount(),
+ 0);
EXPECT_FALSE(document_child->NeedsStyleRecalc());
EXPECT_FALSE(document_child->ChildNeedsStyleRecalc());
@@ -1635,18 +1742,28 @@ TEST_F(DisplayLockContextTest, DescendantNeedsPaintPropertyUpdateBlocked) {
EXPECT_FALSE(handler_object->DescendantNeedsPaintPropertyUpdate());
}
-class DisplayLockContextRenderingTest : public RenderingTest,
- private ScopedCSSSubtreeVisibilityHiddenMatchableForTest {
+class DisplayLockContextRenderingTest
+ : public RenderingTest,
+ private ScopedCSSContentVisibilityHiddenMatchableForTest {
public:
DisplayLockContextRenderingTest()
: RenderingTest(MakeGarbageCollected<SingleChildLocalFrameClient>()),
- ScopedCSSSubtreeVisibilityHiddenMatchableForTest(true) {}
+ ScopedCSSContentVisibilityHiddenMatchableForTest(true) {}
+
+ void SetUp() override {
+ EnableCompositing();
+ RenderingTest::SetUp();
+ }
bool IsObservingLifecycle(DisplayLockContext* context) const {
return context->is_registered_for_lifecycle_notifications_;
}
+ bool DescendantDependentFlagUpdateWasBlocked(
+ DisplayLockContext* context) const {
+ return context->needs_compositing_dependent_flag_update_;
+ }
void LockImmediate(DisplayLockContext* context) {
- context->SetRequestedState(ESubtreeVisibility::kHidden);
+ context->SetRequestedState(EContentVisibility::kHidden);
}
void RunStartOfLifecycleTasks() {
auto start_of_lifecycle_tasks =
@@ -1654,6 +1771,11 @@ class DisplayLockContextRenderingTest : public RenderingTest,
for (auto& task : start_of_lifecycle_tasks)
std::move(task).Run();
}
+ DisplayLockUtilities::ScopedForcedUpdate GetScopedForcedUpdate(
+ const Node* node,
+ bool include_self = false) {
+ return DisplayLockUtilities::ScopedForcedUpdate(node, include_self);
+ }
};
TEST_F(DisplayLockContextRenderingTest, FrameDocumentRemovedWhileAcquire) {
@@ -1676,6 +1798,113 @@ TEST_F(DisplayLockContextRenderingTest, FrameDocumentRemovedWhileAcquire) {
}
TEST_F(DisplayLockContextRenderingTest,
+ VisualOverflowCalculateOnChildPaintLayer) {
+ SetHtmlInnerHTML(R"HTML(
+ <style>
+ .hidden { content-visibility: hidden }
+ .paint_layer { contain: paint }
+ .composited { will-change: transform }
+ </style>
+ <div id=lockable class=paint_layer>
+ <div id=parent class=paint_layer>
+ <div id=child class=paint_layer>
+ <span>content</span>
+ <span>content</span>
+ <span>content</span>
+ </div>
+ </div>
+ </div>
+ )HTML");
+
+ auto* parent = GetDocument().getElementById("parent");
+ auto* parent_box = ToLayoutBoxModelObject(parent->GetLayoutObject());
+ ASSERT_TRUE(parent_box);
+ EXPECT_TRUE(parent_box->Layer());
+ EXPECT_TRUE(parent_box->HasSelfPaintingLayer());
+
+ // Lock the container.
+ auto* lockable = GetDocument().getElementById("lockable");
+ lockable->classList().Add("hidden");
+ UpdateAllLifecyclePhasesForTest();
+
+ auto* child = GetDocument().getElementById("child");
+ auto* child_layer = ToLayoutBoxModelObject(child->GetLayoutObject())->Layer();
+ child_layer->SetNeedsVisualOverflowRecalc();
+ EXPECT_TRUE(child_layer->NeedsVisualOverflowRecalc());
+
+ // The following should not crash/DCHECK.
+ UpdateAllLifecyclePhasesForTest();
+
+ // Verify that the display lock knows that the descendant dependent flags
+ // update was blocked.
+ ASSERT_TRUE(lockable->GetDisplayLockContext());
+ EXPECT_TRUE(DescendantDependentFlagUpdateWasBlocked(
+ lockable->GetDisplayLockContext()));
+ EXPECT_TRUE(child_layer->NeedsVisualOverflowRecalc());
+
+ // After unlocking, we should process the pending visual overflow recalc.
+ lockable->classList().Remove("hidden");
+ UpdateAllLifecyclePhasesForTest();
+
+ EXPECT_FALSE(child_layer->NeedsVisualOverflowRecalc());
+}
+
+TEST_F(DisplayLockContextRenderingTest,
+ VisualOverflowCalculateOnChildPaintLayerInForcedLock) {
+ SetHtmlInnerHTML(R"HTML(
+ <style>
+ .hidden { content-visibility: hidden }
+ .paint_layer { contain: paint }
+ .composited { will-change: transform }
+ </style>
+ <div id=lockable class=paint_layer>
+ <div id=parent class=paint_layer>
+ <div id=child class=paint_layer>
+ <span>content</span>
+ <span>content</span>
+ <span>content</span>
+ </div>
+ </div>
+ </div>
+ )HTML");
+
+ auto* parent = GetDocument().getElementById("parent");
+ auto* parent_box = ToLayoutBoxModelObject(parent->GetLayoutObject());
+ ASSERT_TRUE(parent_box);
+ EXPECT_TRUE(parent_box->Layer());
+ EXPECT_TRUE(parent_box->HasSelfPaintingLayer());
+
+ // Lock the container.
+ auto* lockable = GetDocument().getElementById("lockable");
+ lockable->classList().Add("hidden");
+ UpdateAllLifecyclePhasesForTest();
+
+ auto* child = GetDocument().getElementById("child");
+ auto* child_layer = ToLayoutBoxModelObject(child->GetLayoutObject())->Layer();
+ child_layer->SetNeedsVisualOverflowRecalc();
+ EXPECT_TRUE(child_layer->NeedsVisualOverflowRecalc());
+
+ ASSERT_TRUE(lockable->GetDisplayLockContext());
+ {
+ auto scope = GetScopedForcedUpdate(lockable, true /* include self */);
+
+ // The following should not crash/DCHECK.
+ UpdateAllLifecyclePhasesForTest();
+ }
+
+ // Verify that the display lock doesn't keep extra state since the update was
+ // processed.
+ EXPECT_FALSE(DescendantDependentFlagUpdateWasBlocked(
+ lockable->GetDisplayLockContext()));
+ EXPECT_FALSE(child_layer->NeedsVisualOverflowRecalc());
+
+ // After unlocking, we should not need to do any extra work.
+ lockable->classList().Remove("hidden");
+ EXPECT_FALSE(child_layer->NeedsVisualOverflowRecalc());
+
+ UpdateAllLifecyclePhasesForTest();
+}
+TEST_F(DisplayLockContextRenderingTest,
SelectionOnAnonymousColumnSpannerDoesNotCrash) {
SetHtmlInnerHTML(R"HTML(
<style>
@@ -1744,7 +1973,7 @@ TEST_F(DisplayLockContextRenderingTest, ObjectsNeedingLayoutConsidersLocks) {
EXPECT_EQ(total_count, 10u);
GetDocument().getElementById("e")->setAttribute(html_names::kStyleAttr,
- "subtree-visibility: auto");
+ "content-visibility: auto");
UpdateAllLifecyclePhasesForTest();
// Note that the dirty_all call propagate the dirty bit from the unlocked
@@ -1760,7 +1989,7 @@ TEST_F(DisplayLockContextRenderingTest, ObjectsNeedingLayoutConsidersLocks) {
EXPECT_EQ(total_count, 8u);
GetDocument().getElementById("a")->setAttribute(html_names::kStyleAttr,
- "subtree-visibility: auto");
+ "content-visibility: auto");
UpdateAllLifecyclePhasesForTest();
// Note that this dirty_all call is now not propagating the dirty bits at all,
@@ -1779,8 +2008,8 @@ TEST_F(DisplayLockContextRenderingTest,
NestedLockDoesNotInvalidateOnHideOrShow) {
SetHtmlInnerHTML(R"HTML(
<style>
- .auto { subtree-visibility: auto; }
- .hidden { subtree-visibility: hidden; }
+ .auto { content-visibility: auto; }
+ .hidden { content-visibility: hidden; }
.item { height: 10px; }
/* this is important to not invalidate layout when we hide the element! */
#outer { contain: style layout; }
@@ -1916,8 +2145,8 @@ TEST_F(DisplayLockContextRenderingTest,
TEST_F(DisplayLockContextRenderingTest, NestedLockDoesHideWhenItIsOffscreen) {
SetHtmlInnerHTML(R"HTML(
<style>
- .auto { subtree-visibility: auto; }
- .hidden { subtree-visibility: hidden; }
+ .auto { content-visibility: auto; }
+ .hidden { content-visibility: hidden; }
.item { height: 10px; }
/* this is important to not invalidate layout when we hide the element! */
#outer { contain: style layout; }
@@ -2062,4 +2291,371 @@ TEST_F(DisplayLockContextRenderingTest, NestedLockDoesHideWhenItIsOffscreen) {
// We're locked.
EXPECT_TRUE(inner_context->IsLocked());
}
+
+TEST_F(DisplayLockContextRenderingTest,
+ LockedCanvasWithFallbackHasFocusableStyle) {
+ SetHtmlInnerHTML(R"HTML(
+ <style>
+ .auto { content-visibility: auto; }
+ .spacer { height: 3000px; }
+ </style>
+ <div class=spacer></div>
+ <div class=auto>
+ <canvas>
+ <div id=target tabindex=0></div>
+ </canvas>
+ </div>
+ )HTML");
+
+ auto* target = GetDocument().getElementById("target");
+ EXPECT_TRUE(target->IsFocusable());
+}
+
+TEST_F(DisplayLockContextRenderingTest, ForcedUnlockBookkeeping) {
+ SetHtmlInnerHTML(R"HTML(
+ <style>
+ .hidden { content-visibility: hidden; }
+ .inline { display: inline; }
+ </style>
+ <div id=target class=hidden></div>
+ )HTML");
+
+ auto* target = GetDocument().getElementById("target");
+ auto* context = target->GetDisplayLockContext();
+
+ ASSERT_TRUE(context);
+ EXPECT_TRUE(context->IsLocked());
+ EXPECT_EQ(
+ GetDocument().GetDisplayLockDocumentState().LockedDisplayLockCount(), 1);
+
+ target->classList().Add("inline");
+ UpdateAllLifecyclePhasesForTest();
+
+ EXPECT_FALSE(context->IsLocked());
+ EXPECT_EQ(
+ GetDocument().GetDisplayLockDocumentState().LockedDisplayLockCount(), 0);
+}
+
+TEST_F(DisplayLockContextRenderingTest, LayoutRootIsSkippedIfLocked) {
+ SetHtmlInnerHTML(R"HTML(
+ <style>
+ .hidden { content-visibility: hidden; }
+ .contained { contain: strict; }
+ .positioned { position: absolute; top: 0; left: 0; }
+ </style>
+ <div id=hide>
+ <div class=contained>
+ <div id=new_parent class="contained positioned">
+ <div>
+ <div id=target></div>
+ </div>
+ </div>
+ </div>
+ </div>
+ )HTML");
+
+ // Lock an ancestor.
+ auto* hide = GetDocument().getElementById("hide");
+ hide->classList().Add("hidden");
+ UpdateAllLifecyclePhasesForTest();
+
+ auto* target = GetDocument().getElementById("target");
+ auto* new_parent = GetDocument().getElementById("new_parent");
+
+ // Reparent elements which will invalidate layout without needing to process
+ // style (which is blocked by the display-lock).
+ new_parent->appendChild(target);
+
+ // Note that we don't check target here, since it doesn't have a layout object
+ // after being re-parented.
+ EXPECT_TRUE(new_parent->GetLayoutObject()->NeedsLayout());
+
+ // Updating the lifecycle should not update new_parent, since it is in a
+ // locked subtree.
+ UpdateAllLifecyclePhasesForTest();
+ EXPECT_TRUE(new_parent->GetLayoutObject()->NeedsLayout());
+
+ // Unlocking and updating should update everything.
+ hide->classList().Remove("hidden");
+ UpdateAllLifecyclePhasesForTest();
+
+ EXPECT_FALSE(hide->GetLayoutObject()->NeedsLayout());
+ EXPECT_FALSE(target->GetLayoutObject()->NeedsLayout());
+ EXPECT_FALSE(new_parent->GetLayoutObject()->NeedsLayout());
+}
+
+TEST_F(DisplayLockContextRenderingTest,
+ LayoutRootIsProcessedIfLockedAndForced) {
+ SetHtmlInnerHTML(R"HTML(
+ <style>
+ .hidden { content-visibility: hidden; }
+ .contained { contain: strict; }
+ .positioned { position: absolute; top: 0; left: 0; }
+ </style>
+ <div id=hide>
+ <div class=contained>
+ <div id=new_parent class="contained positioned">
+ <div>
+ <div id=target></div>
+ </div>
+ </div>
+ </div>
+ </div>
+ )HTML");
+
+ // Lock an ancestor.
+ auto* hide = GetDocument().getElementById("hide");
+ hide->classList().Add("hidden");
+ UpdateAllLifecyclePhasesForTest();
+
+ auto* target = GetDocument().getElementById("target");
+ auto* new_parent = GetDocument().getElementById("new_parent");
+
+ // Reparent elements which will invalidate layout without needing to process
+ // style (which is blocked by the display-lock).
+ new_parent->appendChild(target);
+
+ // Note that we don't check target here, since it doesn't have a layout object
+ // after being re-parented.
+ EXPECT_TRUE(new_parent->GetLayoutObject()->NeedsLayout());
+
+ {
+ auto scope = GetScopedForcedUpdate(hide, true /* include self */);
+
+ // Updating the lifecycle should update target and new_parent, since it is
+ // in a locked but forced subtree.
+ UpdateAllLifecyclePhasesForTest();
+ EXPECT_FALSE(target->GetLayoutObject()->NeedsLayout());
+ EXPECT_FALSE(new_parent->GetLayoutObject()->NeedsLayout());
+ }
+
+ // Unlocking and updating should update everything.
+ hide->classList().Remove("hidden");
+ UpdateAllLifecyclePhasesForTest();
+
+ EXPECT_FALSE(hide->GetLayoutObject()->NeedsLayout());
+ EXPECT_FALSE(target->GetLayoutObject()->NeedsLayout());
+ EXPECT_FALSE(new_parent->GetLayoutObject()->NeedsLayout());
+}
+
+TEST_F(DisplayLockContextRenderingTest, ContainStrictChild) {
+ SetHtmlInnerHTML(R"HTML(
+ <style>
+ .hidden { content-visibility: hidden; }
+ .contained { contain: strict; }
+ #target { backface-visibility: hidden; }
+ </style>
+ <div id=hide>
+ <div id=container class=contained>
+ <div id=target></div>
+ </div>
+ </div>
+ )HTML");
+
+ // Lock an ancestor.
+ auto* hide = GetDocument().getElementById("hide");
+ hide->classList().Add("hidden");
+
+ // This should not DCHECK.
+ UpdateAllLifecyclePhasesForTest();
+
+ hide->classList().Remove("hidden");
+ UpdateAllLifecyclePhasesForTest();
+}
+
+TEST_F(DisplayLockContextRenderingTest, CompositingRootIsSkippedIfLocked) {
+ SetHtmlInnerHTML(R"HTML(
+ <style>
+ .hidden { content-visibility: hidden; }
+ .contained { contain: strict; }
+ #target { backface-visibility: hidden; }
+ </style>
+ <div id=hide>
+ <div id=container class=contained>
+ <div id=target></div>
+ </div>
+ </div>
+ )HTML");
+
+ // Lock an ancestor.
+ auto* hide = GetDocument().getElementById("hide");
+ hide->classList().Add("hidden");
+ UpdateAllLifecyclePhasesForTest();
+
+ auto* target = GetDocument().getElementById("target");
+ ASSERT_TRUE(target->GetLayoutObject());
+ auto* target_box = ToLayoutBoxModelObject(target->GetLayoutObject());
+ ASSERT_TRUE(target_box);
+ EXPECT_TRUE(target_box->Layer());
+ EXPECT_TRUE(target_box->HasSelfPaintingLayer());
+ auto* target_layer = target_box->Layer();
+
+ target_layer->SetNeedsCompositingInputsUpdate();
+ EXPECT_TRUE(target_layer->NeedsCompositingInputsUpdate());
+
+ auto* container = GetDocument().getElementById("container");
+ ASSERT_TRUE(container->GetLayoutObject());
+ auto* container_box = ToLayoutBoxModelObject(container->GetLayoutObject());
+ ASSERT_TRUE(container_box);
+ EXPECT_TRUE(container_box->Layer());
+ EXPECT_TRUE(container_box->HasSelfPaintingLayer());
+ auto* container_layer = container_box->Layer();
+
+ auto* compositor = target_layer->Compositor();
+ ASSERT_TRUE(compositor);
+
+ EXPECT_EQ(compositor->GetCompositingInputsRoot(), container_layer);
+
+ UpdateAllLifecyclePhasesForTest();
+
+ EXPECT_EQ(compositor->GetCompositingInputsRoot(), container_layer);
+ EXPECT_TRUE(target_layer->NeedsCompositingInputsUpdate());
+
+ hide->classList().Remove("hidden");
+
+ UpdateAllLifecyclePhasesForTest();
+
+ EXPECT_FALSE(compositor->GetCompositingInputsRoot());
+ EXPECT_FALSE(target_layer->NeedsCompositingInputsUpdate());
+}
+
+TEST_F(DisplayLockContextRenderingTest,
+ CompositingRootIsProcessedIfLockedButForced) {
+ SetHtmlInnerHTML(R"HTML(
+ <style>
+ .hidden { content-visibility: hidden; }
+ .contained { contain: strict; }
+ #target { backface-visibility: hidden; }
+ </style>
+ <div id=hide>
+ <div class=contained>
+ <div id=container class=contained>
+ <div id=target></div>
+ </div>
+ </div>
+ </div>
+ )HTML");
+
+ // Lock an ancestor.
+ auto* hide = GetDocument().getElementById("hide");
+ hide->classList().Add("hidden");
+ UpdateAllLifecyclePhasesForTest();
+
+ auto* target = GetDocument().getElementById("target");
+ ASSERT_TRUE(target->GetLayoutObject());
+ auto* target_box = ToLayoutBoxModelObject(target->GetLayoutObject());
+ ASSERT_TRUE(target_box);
+ EXPECT_TRUE(target_box->Layer());
+ EXPECT_TRUE(target_box->HasSelfPaintingLayer());
+ auto* target_layer = target_box->Layer();
+
+ target_layer->SetNeedsCompositingInputsUpdate();
+ EXPECT_TRUE(target_layer->NeedsCompositingInputsUpdate());
+
+ auto* container = GetDocument().getElementById("container");
+ ASSERT_TRUE(container->GetLayoutObject());
+ auto* container_box = ToLayoutBoxModelObject(container->GetLayoutObject());
+ ASSERT_TRUE(container_box);
+ EXPECT_TRUE(container_box->Layer());
+ EXPECT_TRUE(container_box->HasSelfPaintingLayer());
+ auto* container_layer = container_box->Layer();
+
+ auto* compositor = target_layer->Compositor();
+ ASSERT_TRUE(compositor);
+
+ EXPECT_EQ(compositor->GetCompositingInputsRoot(), container_layer);
+
+ {
+ auto scope = GetScopedForcedUpdate(hide, true /* include self */);
+ UpdateAllLifecyclePhasesForTest();
+ }
+
+ EXPECT_FALSE(compositor->GetCompositingInputsRoot());
+ EXPECT_FALSE(target_layer->NeedsCompositingInputsUpdate());
+
+ hide->classList().Remove("hidden");
+
+ UpdateAllLifecyclePhasesForTest();
+
+ EXPECT_FALSE(compositor->GetCompositingInputsRoot());
+ EXPECT_FALSE(target_layer->NeedsCompositingInputsUpdate());
+}
+
+TEST_F(DisplayLockContextRenderingTest,
+ NeedsLayoutTreeUpdateForNodeRespectsForcedLocks) {
+ SetHtmlInnerHTML(R"HTML(
+ <style>
+ .hidden { content-visibility: hidden; }
+ .contained { contain: strict; }
+ .backface_hidden { backface-visibility: hidden; }
+ </style>
+ <div id=hide>
+ <div id=container class=contained>
+ <div id=target></div>
+ </div>
+ </div>
+ )HTML");
+
+ // Lock an ancestor.
+ auto* hide = GetDocument().getElementById("hide");
+ hide->classList().Add("hidden");
+ UpdateAllLifecyclePhasesForTest();
+
+ auto* target = GetDocument().getElementById("target");
+ target->classList().Add("backface_hidden");
+
+ auto scope = GetScopedForcedUpdate(hide, true /* include self */);
+ EXPECT_TRUE(GetDocument().NeedsLayoutTreeUpdateForNode(*target));
+}
+
+class DisplayLockContextLegacyRenderingTest
+ : public RenderingTest,
+ private ScopedCSSContentVisibilityHiddenMatchableForTest,
+ private ScopedLayoutNGForTest {
+ public:
+ DisplayLockContextLegacyRenderingTest()
+ : RenderingTest(MakeGarbageCollected<SingleChildLocalFrameClient>()),
+ ScopedCSSContentVisibilityHiddenMatchableForTest(true),
+ ScopedLayoutNGForTest(false) {}
+};
+
+TEST_F(DisplayLockContextLegacyRenderingTest,
+ QuirksHiddenParentBlocksChildLayout) {
+ GetDocument().SetCompatibilityMode(Document::kQuirksMode);
+ SetHtmlInnerHTML(R"HTML(
+ <style>
+ .hidden { content-visibility: hidden; }
+ #grandparent { height: 100px; }
+ #parent { height: auto; }
+ #item { height: 10%; }
+ </style>
+ <div id=grandparent>
+ <div id=parent>
+ <div>
+ <div id=item></div>
+ </div>
+ </div>
+ </div>
+ )HTML");
+
+ auto* grandparent = GetDocument().getElementById("grandparent");
+ auto* parent = GetDocument().getElementById("parent");
+ auto* item = GetDocument().getElementById("item");
+
+ auto* grandparent_box = ToLayoutBox(grandparent->GetLayoutObject());
+ auto* item_box = ToLayoutBox(item->GetLayoutObject());
+
+ ASSERT_TRUE(grandparent_box);
+ ASSERT_TRUE(parent->GetLayoutObject());
+ ASSERT_TRUE(item_box);
+
+ EXPECT_EQ(item_box->PercentHeightContainer(), grandparent_box);
+ parent->classList().Add("hidden");
+ grandparent->setAttribute(html_names::kStyleAttr, "height: 150px");
+
+ // This shouldn't DCHECK. We are allowed to have dirty percent height
+ // descendants in quirks mode since they can cross a display-lock boundary.
+ UpdateAllLifecyclePhasesForTest();
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/display_lock/display_lock_document_state.cc b/chromium/third_party/blink/renderer/core/display_lock/display_lock_document_state.cc
new file mode 100644
index 00000000000..2551d422d18
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/display_lock/display_lock_document_state.cc
@@ -0,0 +1,209 @@
+// 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/core/display_lock/display_lock_document_state.h"
+
+#include "third_party/blink/renderer/core/display_lock/display_lock_context.h"
+#include "third_party/blink/renderer/core/dom/document.h"
+#include "third_party/blink/renderer/core/dom/element.h"
+#include "third_party/blink/renderer/core/dom/flat_tree_traversal.h"
+#include "third_party/blink/renderer/core/intersection_observer/intersection_observer.h"
+#include "third_party/blink/renderer/core/intersection_observer/intersection_observer_entry.h"
+
+namespace blink {
+
+DisplayLockDocumentState::DisplayLockDocumentState(Document* document)
+ : document_(document) {}
+
+void DisplayLockDocumentState::Trace(Visitor* visitor) {
+ visitor->Trace(document_);
+ visitor->Trace(intersection_observer_);
+ visitor->Trace(display_lock_contexts_);
+ visitor->Trace(forced_node_info_);
+}
+
+void DisplayLockDocumentState::AddDisplayLockContext(
+ DisplayLockContext* context) {
+ display_lock_contexts_.insert(context);
+}
+
+void DisplayLockDocumentState::RemoveDisplayLockContext(
+ DisplayLockContext* context) {
+ display_lock_contexts_.erase(context);
+}
+
+int DisplayLockDocumentState::DisplayLockCount() const {
+ return display_lock_contexts_.size();
+}
+
+void DisplayLockDocumentState::AddLockedDisplayLock() {
+ TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("blink.debug.display_lock"),
+ "LockedDisplayLockCount", TRACE_ID_LOCAL(this),
+ locked_display_lock_count_);
+ ++locked_display_lock_count_;
+}
+
+void DisplayLockDocumentState::RemoveLockedDisplayLock() {
+ DCHECK(locked_display_lock_count_);
+ --locked_display_lock_count_;
+ TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("blink.debug.display_lock"),
+ "LockedDisplayLockCount", TRACE_ID_LOCAL(this),
+ locked_display_lock_count_);
+}
+
+int DisplayLockDocumentState::LockedDisplayLockCount() const {
+ return locked_display_lock_count_;
+}
+
+void DisplayLockDocumentState::IncrementDisplayLockBlockingAllActivation() {
+ ++display_lock_blocking_all_activation_count_;
+}
+
+void DisplayLockDocumentState::DecrementDisplayLockBlockingAllActivation() {
+ DCHECK(display_lock_blocking_all_activation_count_);
+ --display_lock_blocking_all_activation_count_;
+}
+
+int DisplayLockDocumentState::DisplayLockBlockingAllActivationCount() const {
+ return display_lock_blocking_all_activation_count_;
+}
+
+void DisplayLockDocumentState::RegisterDisplayLockActivationObservation(
+ Element* element) {
+ EnsureIntersectionObserver().observe(element);
+}
+
+void DisplayLockDocumentState::UnregisterDisplayLockActivationObservation(
+ Element* element) {
+ EnsureIntersectionObserver().unobserve(element);
+}
+
+IntersectionObserver& DisplayLockDocumentState::EnsureIntersectionObserver() {
+ if (!intersection_observer_) {
+ // Use kDeliverDuringPostLifecycleSteps method, since we delay delivering
+ // the signal to the display lock context until the next frame's rAF
+ // callbacks have run. This means for the duration of the idle time that
+ // follows, we won't dirty layout.
+ //
+ // Note that we use 50% margin (on the viewport) so that we get the
+ // observation before the element enters the viewport.
+ intersection_observer_ = IntersectionObserver::Create(
+ {Length::Percent(50.f)}, {std::numeric_limits<float>::min()}, document_,
+ WTF::BindRepeating(
+ &DisplayLockDocumentState::ProcessDisplayLockActivationObservation,
+ WrapWeakPersistent(this)),
+ IntersectionObserver::kDeliverDuringPostLifecycleSteps);
+ }
+ return *intersection_observer_;
+}
+
+void DisplayLockDocumentState::ProcessDisplayLockActivationObservation(
+ const HeapVector<Member<IntersectionObserverEntry>>& entries) {
+ DCHECK(document_);
+ DCHECK(document_->View());
+ for (auto& entry : entries) {
+ auto* context = entry->target()->GetDisplayLockContext();
+ DCHECK(context);
+ if (entry->isIntersecting()) {
+ document_->View()->EnqueueStartOfLifecycleTask(
+ WTF::Bind(&DisplayLockContext::NotifyIsIntersectingViewport,
+ WrapWeakPersistent(context)));
+ } else {
+ document_->View()->EnqueueStartOfLifecycleTask(
+ WTF::Bind(&DisplayLockContext::NotifyIsNotIntersectingViewport,
+ WrapWeakPersistent(context)));
+ }
+ }
+ document_->View()->ScheduleAnimation();
+}
+
+DisplayLockDocumentState::ScopedForceActivatableDisplayLocks
+DisplayLockDocumentState::GetScopedForceActivatableLocks() {
+ return ScopedForceActivatableDisplayLocks(this);
+}
+
+bool DisplayLockDocumentState::ActivatableDisplayLocksForced() const {
+ return activatable_display_locks_forced_;
+}
+
+void DisplayLockDocumentState::NotifySelectionRemoved() {
+ for (auto context : display_lock_contexts_)
+ context->NotifySubtreeLostSelection();
+}
+
+void DisplayLockDocumentState::BeginNodeForcedScope(
+ const Node* node,
+ bool self_was_forced,
+ DisplayLockUtilities::ScopedForcedUpdate::Impl* impl) {
+ forced_node_info_.push_back(ForcedNodeInfo(node, self_was_forced, impl));
+}
+
+void DisplayLockDocumentState::EndNodeForcedScope(
+ DisplayLockUtilities::ScopedForcedUpdate::Impl* impl) {
+ for (wtf_size_t i = 0; i < forced_node_info_.size(); ++i) {
+ if (forced_node_info_[i].chain == impl) {
+ forced_node_info_.EraseAt(i);
+ return;
+ }
+ }
+ // We should always find a scope to erase.
+ NOTREACHED();
+}
+
+void DisplayLockDocumentState::ForceLockIfNeeded(Element* element) {
+ DCHECK(element->GetDisplayLockContext());
+ for (wtf_size_t i = 0; i < forced_node_info_.size(); ++i)
+ ForceLockIfNeededForInfo(element, &forced_node_info_[i]);
+}
+
+void DisplayLockDocumentState::ForceLockIfNeededForInfo(
+ Element* element,
+ ForcedNodeInfo* forced_node_info) {
+ auto ancestor_view =
+ forced_node_info->self_forced
+ ? FlatTreeTraversal::InclusiveAncestorsOf(*forced_node_info->node)
+ : FlatTreeTraversal::AncestorsOf(*forced_node_info->node);
+ for (Node& ancestor : ancestor_view) {
+ if (element == &ancestor) {
+ forced_node_info->chain->AddForcedUpdateScopeForContext(
+ element->GetDisplayLockContext());
+ break;
+ }
+ }
+}
+
+// ScopedForcedActivatableDisplayLocks implementation -----------
+DisplayLockDocumentState::ScopedForceActivatableDisplayLocks::
+ ScopedForceActivatableDisplayLocks(DisplayLockDocumentState* state)
+ : state_(state) {
+ if (++state_->activatable_display_locks_forced_ == 1) {
+ for (auto context : state_->display_lock_contexts_)
+ context->DidForceActivatableDisplayLocks();
+ }
+}
+
+DisplayLockDocumentState::ScopedForceActivatableDisplayLocks::
+ ScopedForceActivatableDisplayLocks(
+ ScopedForceActivatableDisplayLocks&& other)
+ : state_(other.state_) {
+ other.state_ = nullptr;
+}
+
+DisplayLockDocumentState::ScopedForceActivatableDisplayLocks&
+DisplayLockDocumentState::ScopedForceActivatableDisplayLocks::operator=(
+ ScopedForceActivatableDisplayLocks&& other) {
+ state_ = other.state_;
+ other.state_ = nullptr;
+ return *this;
+}
+
+DisplayLockDocumentState::ScopedForceActivatableDisplayLocks::
+ ~ScopedForceActivatableDisplayLocks() {
+ if (!state_)
+ return;
+ DCHECK(state_->activatable_display_locks_forced_);
+ --state_->activatable_display_locks_forced_;
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/display_lock/display_lock_document_state.h b/chromium/third_party/blink/renderer/core/display_lock/display_lock_document_state.h
new file mode 100644
index 00000000000..371261b979a
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/display_lock/display_lock_document_state.h
@@ -0,0 +1,161 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_DISPLAY_LOCK_DISPLAY_LOCK_DOCUMENT_STATE_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_DISPLAY_LOCK_DISPLAY_LOCK_DOCUMENT_STATE_H_
+
+#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/core/display_lock/display_lock_utilities.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/member.h"
+
+namespace blink {
+
+class DisplayLockContext;
+class Document;
+class Element;
+class IntersectionObserver;
+class IntersectionObserverEntry;
+
+// This class is responsible for keeping document level state for the display
+// locking feature.
+class CORE_EXPORT DisplayLockDocumentState final
+ : public GarbageCollected<DisplayLockDocumentState> {
+ public:
+ explicit DisplayLockDocumentState(Document* document);
+
+ // GC.
+ void Trace(Visitor*);
+
+ // Registers a display lock context with the state. This is used to force all
+ // activatable locks.
+ void AddDisplayLockContext(DisplayLockContext*);
+ void RemoveDisplayLockContext(DisplayLockContext*);
+ int DisplayLockCount() const;
+
+ // Bookkeeping: the count of all locked display locks.
+ void AddLockedDisplayLock();
+ void RemoveLockedDisplayLock();
+ int LockedDisplayLockCount() const;
+
+ // Bookkeeping: the count of all locked display locks which block all
+ // activation (i.e. content-visibility: hidden locks).
+ void IncrementDisplayLockBlockingAllActivation();
+ void DecrementDisplayLockBlockingAllActivation();
+ int DisplayLockBlockingAllActivationCount() const;
+
+ // Register the given element for intersection observation. Used for detecting
+ // viewport intersections for content-visibility: auto locks.
+ void RegisterDisplayLockActivationObservation(Element*);
+ void UnregisterDisplayLockActivationObservation(Element*);
+
+ // Returns true if all activatable locks have been forced.
+ bool ActivatableDisplayLocksForced() const;
+
+ class ScopedForceActivatableDisplayLocks {
+ STACK_ALLOCATED();
+
+ public:
+ ScopedForceActivatableDisplayLocks(ScopedForceActivatableDisplayLocks&&);
+ ~ScopedForceActivatableDisplayLocks();
+
+ ScopedForceActivatableDisplayLocks& operator=(
+ ScopedForceActivatableDisplayLocks&&);
+
+ private:
+ friend DisplayLockDocumentState;
+ explicit ScopedForceActivatableDisplayLocks(DisplayLockDocumentState*);
+
+ DisplayLockDocumentState* state_;
+ };
+
+ ScopedForceActivatableDisplayLocks GetScopedForceActivatableLocks();
+
+ // Notify the display locks that selection was removed.
+ void NotifySelectionRemoved();
+
+ // This is called when the forced scope is created or destroyed in
+ // |ScopedForcedUpdate::Impl|. This is used to ensure that we can create new
+ // locks that are immediately forced by the existing forced scope.
+ //
+ // Consider the situation A -> B -> C, where C is the child node which is the
+ // target of the forced lock (the parameter passed here), and B is its parent
+ // and A is its grandparent. Suppose that A and B have locks, but since style
+ // was blocked by A, B's lock has not been created yet. When we force the
+ // update from C we call `NotifyNodeForced()`, and A's lock is forced by the
+ // given |ScopedForcedUpdate::Impl|. Then we process the style and while
+ // processing B's style, we find that there is a new lock there. This lock
+ // needs to be forced immediately, since it is in the ancestor chain of C.
+ // This is done by calling `ForceLockIfNeeded()` below, which adds B's scope
+ // to the chain. At the end of the scope, everything is un-forced and
+ // `EndNodeForcedScope()` is called to clean up state.
+ //
+ // Note that there can only be one scope created at a time, so we don't keep
+ // track of more than one of these scopes. This is enforced by private access
+ // modifier + friends, as well as DCHECKs.
+ void BeginNodeForcedScope(
+ const Node* node,
+ bool self_was_forced,
+ DisplayLockUtilities::ScopedForcedUpdate::Impl* chain);
+ void EndNodeForcedScope(
+ DisplayLockUtilities::ScopedForcedUpdate::Impl* chain);
+
+ // Forces the lock on the given element, if it isn't yet forced but appears on
+ // the ancestor chain for the forced element (which was set via
+ // `BeginNodeForcedScope()`).
+ void ForceLockIfNeeded(Element*);
+
+ class ForcedNodeInfo {
+ DISALLOW_NEW();
+
+ public:
+ ForcedNodeInfo(const Node* node,
+ bool self_forced,
+ DisplayLockUtilities::ScopedForcedUpdate::Impl* chain)
+ : node(node), self_forced(self_forced), chain(chain) {}
+
+ void Trace(Visitor* visitor) {
+ visitor->Trace(node);
+ visitor->Trace(chain);
+ }
+
+ Member<const Node> node;
+ bool self_forced;
+ Member<DisplayLockUtilities::ScopedForcedUpdate::Impl> chain;
+ };
+
+ private:
+ IntersectionObserver& EnsureIntersectionObserver();
+
+ void ProcessDisplayLockActivationObservation(
+ const HeapVector<Member<IntersectionObserverEntry>>&);
+
+ void ForceLockIfNeededForInfo(Element*, ForcedNodeInfo*);
+
+ Member<Document> document_;
+
+ Member<IntersectionObserver> intersection_observer_ = nullptr;
+ HeapHashSet<WeakMember<DisplayLockContext>> display_lock_contexts_;
+
+ int locked_display_lock_count_ = 0;
+ int display_lock_blocking_all_activation_count_ = 0;
+
+ // If greater than 0, then the activatable locks are forced.
+ int activatable_display_locks_forced_ = 0;
+
+ // Contains all of the currently forced node infos, each of which represents
+ // the node that caused the scope to be created.
+ HeapVector<ForcedNodeInfo> forced_node_info_;
+};
+
+} // namespace blink
+
+// This ensures |blink::DisplayLockDocumentState::ForcedNodeInfo| does not touch
+// other on-heap objects in its destructor and so it can be cleared with memset.
+// This is needed to allocate it in HeapVector directly.
+WTF_ALLOW_CLEAR_UNUSED_SLOTS_WITH_MEM_FUNCTIONS(
+ blink::DisplayLockDocumentState::ForcedNodeInfo)
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_DISPLAY_LOCK_DISPLAY_LOCK_DOCUMENT_STATE_H_
diff --git a/chromium/third_party/blink/renderer/core/display_lock/display_lock_utilities.cc b/chromium/third_party/blink/renderer/core/display_lock/display_lock_utilities.cc
index 183b36b0f3c..b07c4a0a43c 100644
--- a/chromium/third_party/blink/renderer/core/display_lock/display_lock_utilities.cc
+++ b/chromium/third_party/blink/renderer/core/display_lock/display_lock_utilities.cc
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/core/display_lock/display_lock_utilities.h"
#include "third_party/blink/renderer/core/display_lock/display_lock_context.h"
+#include "third_party/blink/renderer/core/display_lock/display_lock_document_state.h"
#include "third_party/blink/renderer/core/dom/element.h"
#include "third_party/blink/renderer/core/dom/flat_tree_traversal.h"
#include "third_party/blink/renderer/core/dom/node.h"
@@ -31,35 +32,6 @@ const Node* GetFrameOwnerNode(const Node* child) {
return child->GetDocument().GetFrame()->OwnerLayoutObject()->GetNode();
}
-bool UpdateStyleAndLayoutForRangeIfNeeded(const EphemeralRangeInFlatTree& range,
- DisplayLockActivationReason reason) {
- if (range.IsNull() || range.IsCollapsed())
- return false;
- if (!RuntimeEnabledFeatures::CSSSubtreeVisibilityEnabled() ||
- range.GetDocument().LockedDisplayLockCount() ==
- range.GetDocument().DisplayLockBlockingAllActivationCount())
- return false;
- Vector<DisplayLockContext::ScopedForcedUpdate> scoped_forced_update_list_;
- for (Node& node : range.Nodes()) {
- for (Element* locked_activatable_ancestor :
- DisplayLockUtilities::ActivatableLockedInclusiveAncestors(node,
- reason)) {
- DCHECK(locked_activatable_ancestor->GetDisplayLockContext());
- DCHECK(locked_activatable_ancestor->GetDisplayLockContext()->IsLocked());
- if (locked_activatable_ancestor->GetDisplayLockContext()->UpdateForced())
- break;
- scoped_forced_update_list_.push_back(
- locked_activatable_ancestor->GetDisplayLockContext()
- ->GetScopedForcedUpdate());
- }
- }
- if (!scoped_forced_update_list_.IsEmpty()) {
- range.GetDocument().UpdateStyleAndLayout(
- DocumentUpdateReason::kDisplayLock);
- }
- return !scoped_forced_update_list_.IsEmpty();
-}
-
void PopulateAncestorContexts(Node* node,
std::set<DisplayLockContext*>* contexts) {
DCHECK(node);
@@ -72,16 +44,47 @@ void PopulateAncestorContexts(Node* node,
}
}
+template <typename Lambda>
+Element* LockedAncestorPreventingUpdate(const Node& node,
+ Lambda update_is_prevented) {
+ for (auto* ancestor =
+ DisplayLockUtilities::NearestLockedExclusiveAncestor(node);
+ ancestor;
+ ancestor =
+ DisplayLockUtilities::NearestLockedExclusiveAncestor(*ancestor)) {
+ DCHECK(ancestor->GetDisplayLockContext());
+ if (update_is_prevented(ancestor->GetDisplayLockContext()))
+ return ancestor;
+ }
+ return nullptr;
+}
+
+template <typename Lambda>
+Element* LockedAncestorPreventingUpdate(const LayoutObject& object,
+ Lambda update_is_prevented) {
+ if (auto* ancestor =
+ DisplayLockUtilities::NearestLockedExclusiveAncestor(object)) {
+ if (update_is_prevented(ancestor->GetDisplayLockContext()))
+ return ancestor;
+ return LockedAncestorPreventingUpdate(*ancestor, update_is_prevented);
+ }
+ return nullptr;
+}
+
} // namespace
bool DisplayLockUtilities::ActivateFindInPageMatchRangeIfNeeded(
const EphemeralRangeInFlatTree& range) {
- if (!RuntimeEnabledFeatures::CSSSubtreeVisibilityEnabled())
+ if (!RuntimeEnabledFeatures::CSSContentVisibilityEnabled())
return false;
DCHECK(!range.IsNull());
DCHECK(!range.IsCollapsed());
- if (range.GetDocument().LockedDisplayLockCount() ==
- range.GetDocument().DisplayLockBlockingAllActivationCount())
+ if (range.GetDocument()
+ .GetDisplayLockDocumentState()
+ .LockedDisplayLockCount() ==
+ range.GetDocument()
+ .GetDisplayLockDocumentState()
+ .DisplayLockBlockingAllActivationCount())
return false;
// Find-in-page matches can't span multiple block-level elements (because the
// text will be broken by newlines between blocks), so first we find the
@@ -105,9 +108,13 @@ bool DisplayLockUtilities::ActivateSelectionRangeIfNeeded(
const EphemeralRangeInFlatTree& range) {
if (range.IsNull() || range.IsCollapsed())
return false;
- if (!RuntimeEnabledFeatures::CSSSubtreeVisibilityEnabled() ||
- range.GetDocument().LockedDisplayLockCount() ==
- range.GetDocument().DisplayLockBlockingAllActivationCount())
+ if (!RuntimeEnabledFeatures::CSSContentVisibilityEnabled() ||
+ range.GetDocument()
+ .GetDisplayLockDocumentState()
+ .LockedDisplayLockCount() ==
+ range.GetDocument()
+ .GetDisplayLockDocumentState()
+ .DisplayLockBlockingAllActivationCount())
return false;
UpdateStyleAndLayoutForRangeIfNeeded(range,
DisplayLockActivationReason::kSelection);
@@ -133,9 +140,13 @@ DisplayLockUtilities::ActivatableLockedInclusiveAncestors(
DisplayLockActivationReason reason) {
HeapVector<Member<Element>> elements_to_activate;
const_cast<Node*>(&node)->UpdateDistributionForFlatTreeTraversal();
- if (!RuntimeEnabledFeatures::CSSSubtreeVisibilityEnabled() ||
- node.GetDocument().LockedDisplayLockCount() ==
- node.GetDocument().DisplayLockBlockingAllActivationCount())
+ if (!RuntimeEnabledFeatures::CSSContentVisibilityEnabled() ||
+ node.GetDocument()
+ .GetDisplayLockDocumentState()
+ .LockedDisplayLockCount() ==
+ node.GetDocument()
+ .GetDisplayLockDocumentState()
+ .DisplayLockBlockingAllActivationCount())
return elements_to_activate;
for (Node& ancestor : FlatTreeTraversal::InclusiveAncestorsOf(node)) {
@@ -157,15 +168,22 @@ DisplayLockUtilities::ActivatableLockedInclusiveAncestors(
return elements_to_activate;
}
-DisplayLockUtilities::ScopedChainForcedUpdate::ScopedChainForcedUpdate(
- const Node* node,
- bool include_self) {
- if (!RuntimeEnabledFeatures::CSSSubtreeVisibilityEnabled())
+DisplayLockUtilities::ScopedForcedUpdate::Impl::Impl(const Node* node,
+ bool include_self)
+ : node_(node) {
+ if (!RuntimeEnabledFeatures::CSSContentVisibilityEnabled())
return;
- CreateParentFrameScopeIfNeeded(node);
+ auto* owner_node = GetFrameOwnerNode(node);
+ if (owner_node)
+ parent_frame_impl_ = MakeGarbageCollected<Impl>(owner_node, true);
- if (node->GetDocument().LockedDisplayLockCount() == 0)
+ node->GetDocument().GetDisplayLockDocumentState().BeginNodeForcedScope(
+ node, include_self, this);
+
+ if (node->GetDocument()
+ .GetDisplayLockDocumentState()
+ .LockedDisplayLockCount() == 0)
return;
const_cast<Node*>(node)->UpdateDistributionForFlatTreeTraversal();
@@ -194,30 +212,40 @@ DisplayLockUtilities::ScopedChainForcedUpdate::ScopedChainForcedUpdate(
if (!ancestor_node)
continue;
if (auto* context = ancestor_node->GetDisplayLockContext()) {
- if (context->UpdateForced())
- break;
- scoped_update_forced_list_.push_back(context->GetScopedForcedUpdate());
+ context->NotifyForcedUpdateScopeStarted();
+ forced_context_set_.insert(context);
}
}
}
-void DisplayLockUtilities::ScopedChainForcedUpdate::
- CreateParentFrameScopeIfNeeded(const Node* node) {
- auto* owner_node = GetFrameOwnerNode(node);
- if (owner_node) {
- parent_frame_scope_ =
- std::make_unique<ScopedChainForcedUpdate>(owner_node, true);
+void DisplayLockUtilities::ScopedForcedUpdate::Impl::Destroy() {
+ if (RuntimeEnabledFeatures::CSSContentVisibilityEnabled())
+ node_->GetDocument().GetDisplayLockDocumentState().EndNodeForcedScope(this);
+ if (parent_frame_impl_)
+ parent_frame_impl_->Destroy();
+ for (auto context : forced_context_set_) {
+ context->NotifyForcedUpdateScopeEnded();
}
}
+void DisplayLockUtilities::ScopedForcedUpdate::Impl::
+ AddForcedUpdateScopeForContext(DisplayLockContext* context) {
+ auto result = forced_context_set_.insert(context);
+ if (result.is_new_entry)
+ context->NotifyForcedUpdateScopeStarted();
+}
+
const Element* DisplayLockUtilities::NearestLockedInclusiveAncestor(
const Node& node) {
const_cast<Node*>(&node)->UpdateDistributionForFlatTreeTraversal();
auto* element = DynamicTo<Element>(node);
if (!element)
return NearestLockedExclusiveAncestor(node);
- if (!RuntimeEnabledFeatures::CSSSubtreeVisibilityEnabled() ||
- !node.isConnected() || node.GetDocument().LockedDisplayLockCount() == 0 ||
+ if (!RuntimeEnabledFeatures::CSSContentVisibilityEnabled() ||
+ !node.isConnected() ||
+ node.GetDocument()
+ .GetDisplayLockDocumentState()
+ .LockedDisplayLockCount() == 0 ||
!node.CanParticipateInFlatTree()) {
return nullptr;
}
@@ -235,8 +263,11 @@ Element* DisplayLockUtilities::NearestLockedInclusiveAncestor(Node& node) {
Element* DisplayLockUtilities::NearestLockedExclusiveAncestor(
const Node& node) {
- if (!RuntimeEnabledFeatures::CSSSubtreeVisibilityEnabled() ||
- !node.isConnected() || node.GetDocument().LockedDisplayLockCount() == 0 ||
+ if (!RuntimeEnabledFeatures::CSSContentVisibilityEnabled() ||
+ !node.isConnected() ||
+ node.GetDocument()
+ .GetDisplayLockDocumentState()
+ .LockedDisplayLockCount() == 0 ||
!node.CanParticipateInFlatTree()) {
return nullptr;
}
@@ -257,8 +288,10 @@ Element* DisplayLockUtilities::NearestLockedExclusiveAncestor(
Element* DisplayLockUtilities::HighestLockedInclusiveAncestor(
const Node& node) {
- if (!RuntimeEnabledFeatures::CSSSubtreeVisibilityEnabled() ||
- node.GetDocument().LockedDisplayLockCount() == 0 ||
+ if (!RuntimeEnabledFeatures::CSSContentVisibilityEnabled() ||
+ node.GetDocument()
+ .GetDisplayLockDocumentState()
+ .LockedDisplayLockCount() == 0 ||
!node.CanParticipateInFlatTree()) {
return nullptr;
}
@@ -278,8 +311,10 @@ Element* DisplayLockUtilities::HighestLockedInclusiveAncestor(
Element* DisplayLockUtilities::HighestLockedExclusiveAncestor(
const Node& node) {
- if (!RuntimeEnabledFeatures::CSSSubtreeVisibilityEnabled() ||
- node.GetDocument().LockedDisplayLockCount() == 0 ||
+ if (!RuntimeEnabledFeatures::CSSContentVisibilityEnabled() ||
+ node.GetDocument()
+ .GetDisplayLockDocumentState()
+ .LockedDisplayLockCount() == 0 ||
!node.CanParticipateInFlatTree()) {
return nullptr;
}
@@ -314,10 +349,14 @@ Element* DisplayLockUtilities::NearestLockedExclusiveAncestor(
bool DisplayLockUtilities::IsInUnlockedOrActivatableSubtree(
const Node& node,
DisplayLockActivationReason activation_reason) {
- if (!RuntimeEnabledFeatures::CSSSubtreeVisibilityEnabled(
+ if (!RuntimeEnabledFeatures::CSSContentVisibilityEnabled(
node.GetExecutionContext()) ||
- node.GetDocument().LockedDisplayLockCount() == 0 ||
- node.GetDocument().DisplayLockBlockingAllActivationCount() == 0 ||
+ node.GetDocument()
+ .GetDisplayLockDocumentState()
+ .LockedDisplayLockCount() == 0 ||
+ node.GetDocument()
+ .GetDisplayLockDocumentState()
+ .DisplayLockBlockingAllActivationCount() == 0 ||
!node.CanParticipateInFlatTree()) {
return true;
}
@@ -333,13 +372,15 @@ bool DisplayLockUtilities::IsInUnlockedOrActivatableSubtree(
bool DisplayLockUtilities::IsInLockedSubtreeCrossingFrames(
const Node& source_node) {
- if (!RuntimeEnabledFeatures::CSSSubtreeVisibilityEnabled())
+ if (!RuntimeEnabledFeatures::CSSContentVisibilityEnabled())
return false;
const Node* node = &source_node;
// Special case self-node checking.
auto* element = DynamicTo<Element>(node);
- if (element && node->GetDocument().LockedDisplayLockCount()) {
+ if (element && node->GetDocument()
+ .GetDisplayLockDocumentState()
+ .LockedDisplayLockCount()) {
auto* context = element->GetDisplayLockContext();
if (context && !context->ShouldLayout(DisplayLockLifecycleTarget::kSelf))
return true;
@@ -363,8 +404,10 @@ bool DisplayLockUtilities::IsInLockedSubtreeCrossingFrames(
}
void DisplayLockUtilities::ElementLostFocus(Element* element) {
- if (!RuntimeEnabledFeatures::CSSSubtreeVisibilityEnabled() ||
- (element && element->GetDocument().DisplayLockCount() == 0))
+ if (!RuntimeEnabledFeatures::CSSContentVisibilityEnabled() ||
+ (element && element->GetDocument()
+ .GetDisplayLockDocumentState()
+ .DisplayLockCount() == 0))
return;
for (; element; element = FlatTreeTraversal::ParentElement(*element)) {
auto* context = element->GetDisplayLockContext();
@@ -373,8 +416,10 @@ void DisplayLockUtilities::ElementLostFocus(Element* element) {
}
}
void DisplayLockUtilities::ElementGainedFocus(Element* element) {
- if (!RuntimeEnabledFeatures::CSSSubtreeVisibilityEnabled() ||
- (element && element->GetDocument().DisplayLockCount() == 0))
+ if (!RuntimeEnabledFeatures::CSSContentVisibilityEnabled() ||
+ (element && element->GetDocument()
+ .GetDisplayLockDocumentState()
+ .DisplayLockCount() == 0))
return;
for (; element; element = FlatTreeTraversal::ParentElement(*element)) {
@@ -387,11 +432,13 @@ void DisplayLockUtilities::ElementGainedFocus(Element* element) {
void DisplayLockUtilities::SelectionChanged(
const EphemeralRangeInFlatTree& old_selection,
const EphemeralRangeInFlatTree& new_selection) {
- if (!RuntimeEnabledFeatures::CSSSubtreeVisibilityEnabled() ||
- (!old_selection.IsNull() &&
- old_selection.GetDocument().DisplayLockCount() == 0) ||
- (!new_selection.IsNull() &&
- new_selection.GetDocument().DisplayLockCount() == 0))
+ if (!RuntimeEnabledFeatures::CSSContentVisibilityEnabled() ||
+ (!old_selection.IsNull() && old_selection.GetDocument()
+ .GetDisplayLockDocumentState()
+ .DisplayLockCount() == 0) ||
+ (!new_selection.IsNull() && new_selection.GetDocument()
+ .GetDisplayLockDocumentState()
+ .DisplayLockCount() == 0))
return;
TRACE_EVENT0("blink", "DisplayLockUtilities::SelectionChanged");
@@ -454,7 +501,66 @@ void DisplayLockUtilities::SelectionChanged(
}
void DisplayLockUtilities::SelectionRemovedFromDocument(Document& document) {
- document.NotifySelectionRemovedFromDisplayLocks();
+ document.GetDisplayLockDocumentState().NotifySelectionRemoved();
+}
+
+Element* DisplayLockUtilities::LockedAncestorPreventingPrePaint(
+ const LayoutObject& object) {
+ return LockedAncestorPreventingUpdate(
+ object, [](DisplayLockContext* context) {
+ return !context->ShouldPrePaint(DisplayLockLifecycleTarget::kChildren);
+ });
+}
+
+Element* DisplayLockUtilities::LockedAncestorPreventingLayout(
+ const LayoutObject& object) {
+ return LockedAncestorPreventingUpdate(
+ object, [](DisplayLockContext* context) {
+ return !context->ShouldLayout(DisplayLockLifecycleTarget::kChildren);
+ });
+}
+
+Element* DisplayLockUtilities::LockedAncestorPreventingStyle(const Node& node) {
+ return LockedAncestorPreventingUpdate(node, [](DisplayLockContext* context) {
+ return !context->ShouldStyle(DisplayLockLifecycleTarget::kChildren);
+ });
+}
+
+bool DisplayLockUtilities::UpdateStyleAndLayoutForRangeIfNeeded(
+ const EphemeralRangeInFlatTree& range,
+ DisplayLockActivationReason reason) {
+ if (range.IsNull() || range.IsCollapsed())
+ return false;
+ if (!RuntimeEnabledFeatures::CSSContentVisibilityEnabled() ||
+ range.GetDocument()
+ .GetDisplayLockDocumentState()
+ .LockedDisplayLockCount() ==
+ range.GetDocument()
+ .GetDisplayLockDocumentState()
+ .DisplayLockBlockingAllActivationCount())
+ return false;
+ HeapVector<Member<DisplayLockContext>> forced_context_list_;
+ for (Node& node : range.Nodes()) {
+ for (Element* locked_activatable_ancestor :
+ DisplayLockUtilities::ActivatableLockedInclusiveAncestors(node,
+ reason)) {
+ DCHECK(locked_activatable_ancestor->GetDisplayLockContext());
+ DCHECK(locked_activatable_ancestor->GetDisplayLockContext()->IsLocked());
+ auto* context = locked_activatable_ancestor->GetDisplayLockContext();
+ // TODO(vmpstr): Clean this up not to call
+ // |NotifyForcedUpdateScopeStarted()| directly.
+ context->NotifyForcedUpdateScopeStarted();
+ forced_context_list_.push_back(context);
+ }
+ }
+ if (!forced_context_list_.IsEmpty()) {
+ range.GetDocument().UpdateStyleAndLayout(
+ DocumentUpdateReason::kDisplayLock);
+ }
+ for (auto context : forced_context_list_) {
+ context->NotifyForcedUpdateScopeEnded();
+ }
+ return !forced_context_list_.IsEmpty();
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/display_lock/display_lock_utilities.h b/chromium/third_party/blink/renderer/core/display_lock/display_lock_utilities.h
index 8a875f84521..f9b43ec5004 100644
--- a/chromium/third_party/blink/renderer/core/display_lock/display_lock_utilities.h
+++ b/chromium/third_party/blink/renderer/core/display_lock/display_lock_utilities.h
@@ -19,20 +19,74 @@ class CORE_EXPORT DisplayLockUtilities {
public:
// This class forces updates on display locks from the given node up the
// ancestor chain until the local frame root.
- class CORE_EXPORT ScopedChainForcedUpdate {
- DISALLOW_COPY_AND_ASSIGN(ScopedChainForcedUpdate);
+ class CORE_EXPORT ScopedForcedUpdate {
+ DISALLOW_COPY_AND_ASSIGN(ScopedForcedUpdate);
+ STACK_ALLOCATED();
public:
- explicit ScopedChainForcedUpdate(const Node* node,
- bool include_self = false);
- ~ScopedChainForcedUpdate() = default;
-
- void CreateParentFrameScopeIfNeeded(const Node* node);
+ ScopedForcedUpdate(ScopedForcedUpdate&& other) : impl_(other.impl_) {
+ other.impl_ = nullptr;
+ }
+ ~ScopedForcedUpdate() {
+ if (impl_)
+ impl_->Destroy();
+ }
+
+ ScopedForcedUpdate& operator=(ScopedForcedUpdate&& other) {
+ impl_ = other.impl_;
+ other.impl_ = nullptr;
+ return *this;
+ }
private:
- Vector<DisplayLockContext::ScopedForcedUpdate> scoped_update_forced_list_;
- std::unique_ptr<ScopedChainForcedUpdate> parent_frame_scope_;
+ // It is important not to create multiple ScopedChainForcedUpdate scopes.
+ // The following functions update some combination of Style, Layout, Paint
+ // information after forcing the display locks. It should be enough to use
+ // one of the following functions instead of forcing the scope manually.
+ friend void Document::UpdateStyleAndLayoutForNode(
+ const Node* node,
+ DocumentUpdateReason reason);
+ friend void Document::UpdateStyleAndLayoutTreeForNode(const Node*);
+ friend void Document::UpdateStyleAndLayoutTreeForSubtree(const Node* node);
+ friend void Document::EnsurePaintLocationDataValidForNode(
+ const Node* node,
+ DocumentUpdateReason reason);
+
+ friend class DisplayLockContext;
+
+ // Test friends.
+ friend class DisplayLockContextRenderingTest;
+
+ explicit ScopedForcedUpdate(const Node* node, bool include_self = false)
+ : impl_(MakeGarbageCollected<Impl>(node, include_self)) {}
+
+ friend class DisplayLockDocumentState;
+
+ class CORE_EXPORT Impl final : public GarbageCollected<Impl> {
+ public:
+ explicit Impl(const Node* node, bool include_self = false);
+
+ // Adds another display-lock scope to this chain. Added when a new lock is
+ // created in the ancestor chain of this chain's node.
+ void AddForcedUpdateScopeForContext(DisplayLockContext*);
+
+ void Destroy();
+
+ void Trace(Visitor* visitor) {
+ visitor->Trace(node_);
+ visitor->Trace(forced_context_set_);
+ visitor->Trace(parent_frame_impl_);
+ }
+
+ private:
+ Member<const Node> node_;
+ HeapHashSet<Member<DisplayLockContext>> forced_context_set_;
+ Member<Impl> parent_frame_impl_;
+ };
+
+ Impl* impl_ = nullptr;
};
+
// Activates all the nodes within a find-in-page match |range|.
// Returns true if at least one node gets activated.
// See: http://bit.ly/2RXULVi, "beforeactivate Event" part.
@@ -70,6 +124,21 @@ class CORE_EXPORT DisplayLockUtilities {
static Element* NearestLockedInclusiveAncestor(const LayoutObject& object);
static Element* NearestLockedExclusiveAncestor(const LayoutObject& object);
+ // Returns the nearest ancestor element which has a lock that prevents
+ // prepaint. Note that this is different from a nearest locked ancestor since
+ // the prepaint update can be forced.
+ static Element* LockedAncestorPreventingPrePaint(const LayoutObject& object);
+
+ // Returns the nearest ancestor element which has a lock that prevents
+ // layout. Note that this is different from a nearest locked ancestor since
+ // the layout update can be forced.
+ static Element* LockedAncestorPreventingLayout(const LayoutObject& object);
+
+ // Returns the nearest ancestor element which has a lock that prevents
+ // style. Note that this is different from a nearest locked ancestor since
+ // the style update can be forced.
+ static Element* LockedAncestorPreventingStyle(const Node& element);
+
// Returns true if |node| is not in a locked subtree, or if it's possible to
// activate all of the locked ancestors for |activation_reason|.
static bool IsInUnlockedOrActivatableSubtree(
@@ -99,6 +168,11 @@ class CORE_EXPORT DisplayLockUtilities {
static void SelectionChanged(const EphemeralRangeInFlatTree& old_selection,
const EphemeralRangeInFlatTree& new_selection);
static void SelectionRemovedFromDocument(Document& document);
+
+ private:
+ static bool UpdateStyleAndLayoutForRangeIfNeeded(
+ const EphemeralRangeInFlatTree& range,
+ DisplayLockActivationReason reason);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/display_lock/display_lock_utilities_test.cc b/chromium/third_party/blink/renderer/core/display_lock/display_lock_utilities_test.cc
index f055499b51b..f13d7044c1a 100644
--- a/chromium/third_party/blink/renderer/core/display_lock/display_lock_utilities_test.cc
+++ b/chromium/third_party/blink/renderer/core/display_lock/display_lock_utilities_test.cc
@@ -6,6 +6,7 @@
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
#include "third_party/blink/renderer/core/display_lock/display_lock_context.h"
+#include "third_party/blink/renderer/core/display_lock/display_lock_document_state.h"
#include "third_party/blink/renderer/core/dom/shadow_root.h"
#include "third_party/blink/renderer/core/testing/core_unit_test_helper.h"
#include "third_party/blink/renderer/core/testing/page_test_base.h"
@@ -13,16 +14,17 @@
namespace blink {
-class DisplayLockUtilitiesTest : public RenderingTest,
- private ScopedCSSSubtreeVisibilityHiddenMatchableForTest {
+class DisplayLockUtilitiesTest
+ : public RenderingTest,
+ private ScopedCSSContentVisibilityHiddenMatchableForTest {
public:
DisplayLockUtilitiesTest()
: RenderingTest(MakeGarbageCollected<SingleChildLocalFrameClient>()),
- ScopedCSSSubtreeVisibilityHiddenMatchableForTest(true) {}
+ ScopedCSSContentVisibilityHiddenMatchableForTest(true) {}
void LockElement(Element& element, bool activatable) {
StringBuilder value;
- value.Append("subtree-visibility: hidden");
+ value.Append("content-visibility: hidden");
if (activatable)
value.Append("-matchable");
element.setAttribute(html_names::kStyleAttr, value.ToAtomicString());
@@ -60,8 +62,12 @@ TEST_F(DisplayLockUtilitiesTest, DISABLED_ActivatableLockedInclusiveAncestors) {
Element& shadow_div = *shadow_root.getElementById("shadowDiv");
LockElement(outer, true);
- EXPECT_EQ(GetDocument().LockedDisplayLockCount(), 1);
- EXPECT_EQ(GetDocument().DisplayLockBlockingAllActivationCount(), 0);
+ EXPECT_EQ(
+ GetDocument().GetDisplayLockDocumentState().LockedDisplayLockCount(), 1);
+ EXPECT_EQ(GetDocument()
+ .GetDisplayLockDocumentState()
+ .DisplayLockBlockingAllActivationCount(),
+ 0);
// Querying from every element gives |outer|.
HeapVector<Member<Element>> result_for_outer =
DisplayLockUtilities::ActivatableLockedInclusiveAncestors(
@@ -95,8 +101,12 @@ TEST_F(DisplayLockUtilitiesTest, DISABLED_ActivatableLockedInclusiveAncestors) {
// Lock innermost with activatable flag.
LockElement(innermost, true);
- EXPECT_EQ(GetDocument().LockedDisplayLockCount(), 2);
- EXPECT_EQ(GetDocument().DisplayLockBlockingAllActivationCount(), 0);
+ EXPECT_EQ(
+ GetDocument().GetDisplayLockDocumentState().LockedDisplayLockCount(), 2);
+ EXPECT_EQ(GetDocument()
+ .GetDisplayLockDocumentState()
+ .DisplayLockBlockingAllActivationCount(),
+ 0);
result_for_outer = DisplayLockUtilities::ActivatableLockedInclusiveAncestors(
outer, DisplayLockActivationReason::kAny);
@@ -131,8 +141,12 @@ TEST_F(DisplayLockUtilitiesTest, DISABLED_ActivatableLockedInclusiveAncestors) {
// Unlock everything.
CommitElement(innermost);
CommitElement(outer);
- EXPECT_EQ(GetDocument().LockedDisplayLockCount(), 0);
- EXPECT_EQ(GetDocument().DisplayLockBlockingAllActivationCount(), 0);
+ EXPECT_EQ(
+ GetDocument().GetDisplayLockDocumentState().LockedDisplayLockCount(), 0);
+ EXPECT_EQ(GetDocument()
+ .GetDisplayLockDocumentState()
+ .DisplayLockBlockingAllActivationCount(),
+ 0);
EXPECT_EQ(DisplayLockUtilities::ActivatableLockedInclusiveAncestors(
outer, DisplayLockActivationReason::kAny)
@@ -192,8 +206,11 @@ TEST_F(DisplayLockUtilitiesTest, LockedSubtreeCrossingFrames) {
// Lock parent.
LockElement(*parent, false);
- EXPECT_EQ(GetDocument().LockedDisplayLockCount(), 0);
- EXPECT_EQ(ChildDocument().LockedDisplayLockCount(), 1);
+ EXPECT_EQ(
+ GetDocument().GetDisplayLockDocumentState().LockedDisplayLockCount(), 0);
+ EXPECT_EQ(
+ ChildDocument().GetDisplayLockDocumentState().LockedDisplayLockCount(),
+ 1);
EXPECT_FALSE(
DisplayLockUtilities::IsInLockedSubtreeCrossingFrames(*grandparent));
diff --git a/chromium/third_party/blink/renderer/core/display_lock/render_subtree_activation_event.idl b/chromium/third_party/blink/renderer/core/display_lock/render_subtree_activation_event.idl
index 104b4d1bb09..b304b20d346 100644
--- a/chromium/third_party/blink/renderer/core/display_lock/render_subtree_activation_event.idl
+++ b/chromium/third_party/blink/renderer/core/display_lock/render_subtree_activation_event.idl
@@ -3,7 +3,8 @@
// found in the LICENSE file.
[
- RuntimeEnabled=CSSSubtreeVisibilityActivationEvent
+ Exposed=Window,
+ RuntimeEnabled=CSSContentVisibilityActivationEvent
] interface RenderSubtreeActivationEvent : Event {
readonly attribute Element activatedElement;
};
diff --git a/chromium/third_party/blink/renderer/core/dom/aria_attributes.idl b/chromium/third_party/blink/renderer/core/dom/aria_attributes.idl
index 31bee8c6dc3..9f6a22ba398 100644
--- a/chromium/third_party/blink/renderer/core/dom/aria_attributes.idl
+++ b/chromium/third_party/blink/renderer/core/dom/aria_attributes.idl
@@ -39,7 +39,8 @@
[CEReactions, Reflect=aria_rowcount] attribute DOMString? ariaRowCount;
[CEReactions, Reflect=aria_rowindex] attribute DOMString? ariaRowIndex;
[CEReactions, Reflect=aria_rowspan] attribute DOMString? ariaRowSpan;
- [CEReactions, Reflect=aria_setsize] attribute DOMString? ariaSelected;
+ [CEReactions, Reflect=aria_selected] attribute DOMString? ariaSelected;
+ [CEReactions, Reflect=aria_setsize] attribute DOMString? ariaSetSize;
[CEReactions, Reflect=aria_sort] attribute DOMString? ariaSort;
[CEReactions, Reflect=aria_valuemax] attribute DOMString? ariaValueMax;
[CEReactions, Reflect=aria_valuemin] attribute DOMString? ariaValueMin;
diff --git a/chromium/third_party/blink/renderer/core/dom/container_node.cc b/chromium/third_party/blink/renderer/core/dom/container_node.cc
index b946eea979a..7eacc4f0932 100644
--- a/chromium/third_party/blink/renderer/core/dom/container_node.cc
+++ b/chromium/third_party/blink/renderer/core/dom/container_node.cc
@@ -1047,9 +1047,11 @@ bool ContainerNode::ChildrenChangedAllChildrenRemovedNeedsList() const {
return false;
}
-void ContainerNode::CloneChildNodesFrom(const ContainerNode& node) {
+void ContainerNode::CloneChildNodesFrom(const ContainerNode& node,
+ CloneChildrenFlag flag) {
+ DCHECK_NE(flag, CloneChildrenFlag::kSkip);
for (const Node& child : NodeTraversal::ChildrenOf(node))
- AppendChild(child.Clone(GetDocument(), CloneChildrenFlag::kClone));
+ AppendChild(child.Clone(GetDocument(), flag));
}
PhysicalRect ContainerNode::BoundingBox() const {
@@ -1551,6 +1553,12 @@ RadioNodeList* ContainerNode::GetRadioNodeList(const AtomicString& name,
}
Element* ContainerNode::getElementById(const AtomicString& id) const {
+ // According to https://dom.spec.whatwg.org/#concept-id, empty IDs are
+ // treated as equivalent to the lack of an id attribute.
+ if (id.IsEmpty()) {
+ return nullptr;
+ }
+
if (IsInTreeScope()) {
// Fast path if we are in a tree scope: call getElementById() on tree scope
// and check if the matching element is in our subtree.
diff --git a/chromium/third_party/blink/renderer/core/dom/container_node.h b/chromium/third_party/blink/renderer/core/dom/container_node.h
index c3582de6bfc..209f085f8e5 100644
--- a/chromium/third_party/blink/renderer/core/dom/container_node.h
+++ b/chromium/third_party/blink/renderer/core/dom/container_node.h
@@ -144,7 +144,7 @@ class CORE_EXPORT ContainerNode : public Node {
void RemoveChildren(
SubtreeModificationAction = kDispatchSubtreeModifiedEvent);
- void CloneChildNodesFrom(const ContainerNode&);
+ void CloneChildNodesFrom(const ContainerNode&, CloneChildrenFlag);
void AttachLayoutTree(AttachContext&) override;
void DetachLayoutTree(bool performing_reattach = false) override;
diff --git a/chromium/third_party/blink/renderer/core/dom/decoded_data_document_parser.cc b/chromium/third_party/blink/renderer/core/dom/decoded_data_document_parser.cc
index 3dcebd41f84..942cd4249fa 100644
--- a/chromium/third_party/blink/renderer/core/dom/decoded_data_document_parser.cc
+++ b/chromium/third_party/blink/renderer/core/dom/decoded_data_document_parser.cc
@@ -29,6 +29,7 @@
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/document_encoding_data.h"
#include "third_party/blink/renderer/core/html/parser/text_resource_decoder.h"
+#include "third_party/blink/renderer/core/xml/document_xslt.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
namespace blink {
@@ -87,7 +88,11 @@ void DecodedDataDocumentParser::Flush() {
}
void DecodedDataDocumentParser::UpdateDocument(String& decoded_data) {
- GetDocument()->SetEncodingData(DocumentEncodingData(*decoder_.get()));
+ // A Document created from XSLT may have changed the encoding of the data
+ // before feeding it to the parser, so don't overwrite the encoding data XSLT
+ // provided about the original encoding.
+ if (!DocumentXSLT::HasTransformSourceDocument(*GetDocument()))
+ GetDocument()->SetEncodingData(DocumentEncodingData(*decoder_.get()));
if (!decoded_data.IsEmpty())
Append(decoded_data);
diff --git a/chromium/third_party/blink/renderer/core/dom/document.cc b/chromium/third_party/blink/renderer/core/dom/document.cc
index f55c90df996..fb101440a37 100644
--- a/chromium/third_party/blink/renderer/core/dom/document.cc
+++ b/chromium/third_party/blink/renderer/core/dom/document.cc
@@ -42,18 +42,18 @@
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "mojo/public/mojom/base/text_direction.mojom-blink.h"
-#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
#include "services/metrics/public/cpp/mojo_ukm_recorder.h"
#include "services/metrics/public/cpp/ukm_builders.h"
#include "services/metrics/public/cpp/ukm_source_id.h"
#include "services/metrics/public/mojom/ukm_interface.mojom-blink.h"
#include "services/network/public/mojom/ip_address_space.mojom-blink.h"
+#include "services/network/public/mojom/trust_tokens.mojom-blink.h"
+#include "services/network/public/mojom/web_sandbox_flags.mojom-blink.h"
#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
#include "third_party/blink/public/common/feature_policy/document_policy_features.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/feature_policy/policy_disposition.mojom-blink.h"
#include "third_party/blink/public/mojom/input/focus_type.mojom-blink.h"
#include "third_party/blink/public/mojom/insecure_input/insecure_input_service.mojom-blink.h"
#include "third_party/blink/public/mojom/ukm/ukm.mojom-blink.h"
@@ -61,6 +61,7 @@
#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/public/platform/web_content_settings_client.h"
#include "third_party/blink/public/platform/web_theme_engine.h"
+#include "third_party/blink/public/web/web_print_page_description.h"
#include "third_party/blink/renderer/bindings/core/v8/html_script_element_or_svg_script_element.h"
#include "third_party/blink/renderer/bindings/core/v8/isolated_world_csp.h"
#include "third_party/blink/renderer/bindings/core/v8/script_controller.h"
@@ -71,6 +72,7 @@
#include "third_party/blink/renderer/bindings/core/v8/v0_custom_element_constructor_builder.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_element_creation_options.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_element_registration_options.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_throw_dom_exception.h"
#include "third_party/blink/renderer/bindings/core/v8/window_proxy.h"
#include "third_party/blink/renderer/core/accessibility/ax_context.h"
#include "third_party/blink/renderer/core/accessibility/ax_object_cache.h"
@@ -99,6 +101,7 @@
#include "third_party/blink/renderer/core/css/style_sheet_contents.h"
#include "third_party/blink/renderer/core/css/style_sheet_list.h"
#include "third_party/blink/renderer/core/display_lock/display_lock_context.h"
+#include "third_party/blink/renderer/core/display_lock/display_lock_document_state.h"
#include "third_party/blink/renderer/core/display_lock/display_lock_utilities.h"
#include "third_party/blink/renderer/core/dom/attr.h"
#include "third_party/blink/renderer/core/dom/beforeunload_event_listener.h"
@@ -160,11 +163,9 @@
#include "third_party/blink/renderer/core/feature_policy/feature_policy_parser.h"
#include "third_party/blink/renderer/core/frame/csp/content_security_policy.h"
#include "third_party/blink/renderer/core/frame/csp/navigation_initiator_impl.h"
-#include "third_party/blink/renderer/core/frame/document_policy_violation_report_body.h"
#include "third_party/blink/renderer/core/frame/dom_timer.h"
#include "third_party/blink/renderer/core/frame/dom_visual_viewport.h"
#include "third_party/blink/renderer/core/frame/event_handler_registry.h"
-#include "third_party/blink/renderer/core/frame/feature_policy_violation_report_body.h"
#include "third_party/blink/renderer/core/frame/frame_console.h"
#include "third_party/blink/renderer/core/frame/history.h"
#include "third_party/blink/renderer/core/frame/intervention.h"
@@ -173,8 +174,6 @@
#include "third_party/blink/renderer/core/frame/local_frame_client.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
#include "third_party/blink/renderer/core/frame/performance_monitor.h"
-#include "third_party/blink/renderer/core/frame/report.h"
-#include "third_party/blink/renderer/core/frame/reporting_context.h"
#include "third_party/blink/renderer/core/frame/settings.h"
#include "third_party/blink/renderer/core/frame/viewport_data.h"
#include "third_party/blink/renderer/core/frame/visual_viewport.h"
@@ -227,8 +226,6 @@
#include "third_party/blink/renderer/core/input/event_handler.h"
#include "third_party/blink/renderer/core/input/touch_list.h"
#include "third_party/blink/renderer/core/inspector/console_message.h"
-#include "third_party/blink/renderer/core/inspector/inspector_issue.h"
-#include "third_party/blink/renderer/core/inspector/inspector_issue_storage.h"
#include "third_party/blink/renderer/core/inspector/inspector_trace_events.h"
#include "third_party/blink/renderer/core/intersection_observer/element_intersection_observer_data.h"
#include "third_party/blink/renderer/core/intersection_observer/intersection_observer_controller.h"
@@ -354,6 +351,16 @@ bool IsInIndeterminateObjectAncestor(const Element* element) {
return false;
}
+// Helper function to notify both `first` and `second` that the priority scroll
+// anchor status changed. This is used when, for example, a focused element
+// changes from `first` to `second`.
+void NotifyPriorityScrollAnchorStatusChanged(Node* first, Node* second) {
+ if (first)
+ first->NotifyPriorityScrollAnchorStatusChanged();
+ if (second)
+ second->NotifyPriorityScrollAnchorStatusChanged();
+}
+
} // namespace
class DocumentOutliveTimeReporter : public BlinkGCObserver {
@@ -662,7 +669,7 @@ Document::Document(const DocumentInit& initializer,
// pointer?
dom_window_(frame_ ? frame_->DomWindow() : nullptr),
imports_controller_(initializer.ImportsController()),
- security_context_(security_initializer, SecurityContext::kLocal),
+ security_context_(security_initializer, SecurityContext::kWindow),
use_counter_during_construction_(initializer.GetUseCounter()),
context_document_(initializer.ContextDocument()),
context_features_(ContextFeatures::DefaultSwitch()),
@@ -719,7 +726,6 @@ Document::Document(const DocumentInit& initializer,
is_srcdoc_document_(initializer.IsSrcdocDocument()),
is_mobile_document_(false),
layout_view_(nullptr),
- has_fullscreen_supplement_(false),
load_event_delay_count_(0),
// We already intentionally fire load event asynchronously and here we use
// kDOMManipulation to ensure that we run onload() in order with other
@@ -763,7 +769,10 @@ Document::Document(const DocumentInit& initializer,
isolated_world_csp_map_(
MakeGarbageCollected<
HeapHashMap<int, Member<ContentSecurityPolicy>>>()),
+ display_lock_document_state_(
+ MakeGarbageCollected<DisplayLockDocumentState>(this)),
permission_service_(GetExecutionContext()),
+ has_trust_tokens_answerer_(GetExecutionContext()),
font_preload_manager_(*this) {
security_initializer.ApplyPendingDataToDocument(*this);
GetOriginTrialContext()->BindExecutionContext(GetExecutionContext());
@@ -978,26 +987,6 @@ ContentSecurityPolicy* Document::GetContentSecurityPolicyForWorld() {
return policy;
}
-// static
-Document& Document::From(ExecutionContext& context) {
- SECURITY_DCHECK(context.IsDocument());
- return *static_cast<LocalDOMWindow&>(context).document();
-}
-
-// static
-const Document& Document::From(const ExecutionContext& context) {
- SECURITY_DCHECK(context.IsDocument());
- return *static_cast<const LocalDOMWindow&>(context).document();
-}
-
-ExecutionContext* Document::ToExecutionContext() {
- return GetExecutionContext();
-}
-
-const ExecutionContext* Document::ToExecutionContext() const {
- return GetExecutionContext();
-}
-
bool Document::FeatureEnabled(OriginTrialFeature feature) const {
return GetOriginTrialContext()->IsFeatureEnabled(feature);
}
@@ -1020,6 +1009,21 @@ bool Document::FeaturePolicyFeatureObserved(
return false;
}
+bool Document::DocumentPolicyFeatureObserved(
+ mojom::blink::DocumentPolicyFeature feature) {
+ wtf_size_t feature_index = static_cast<wtf_size_t>(feature);
+ if (parsed_document_policies_.size() == 0) {
+ parsed_document_policies_.resize(
+ static_cast<wtf_size_t>(
+ mojom::blink::DocumentPolicyFeature::kMaxValue) +
+ 1);
+ } else if (parsed_document_policies_[feature_index]) {
+ return true;
+ }
+ parsed_document_policies_[feature_index] = true;
+ return false;
+}
+
const SecurityOrigin* Document::GetSecurityOrigin() const {
return GetSecurityContext().GetSecurityOrigin();
}
@@ -1032,11 +1036,11 @@ ContentSecurityPolicy* Document::GetContentSecurityPolicy() const {
return GetSecurityContext().GetContentSecurityPolicy();
}
-mojom::blink::WebSandboxFlags Document::GetSandboxFlags() const {
+network::mojom::blink::WebSandboxFlags Document::GetSandboxFlags() const {
return GetSecurityContext().GetSandboxFlags();
}
-bool Document::IsSandboxed(mojom::blink::WebSandboxFlags mask) const {
+bool Document::IsSandboxed(network::mojom::blink::WebSandboxFlags mask) const {
return GetSecurityContext().IsSandboxed(mask);
}
@@ -1093,21 +1097,9 @@ void Document::SetSecureContextModeForTesting(SecureContextMode mode) {
bool Document::IsFeatureEnabled(mojom::blink::FeaturePolicyFeature feature,
ReportOptions report_on_failure,
- const String& message,
- const String& source_file) const {
- return GetExecutionContext() &&
- GetExecutionContext()->IsFeatureEnabled(feature, report_on_failure,
- message, source_file);
-}
-
-bool Document::IsFeatureEnabled(mojom::blink::FeaturePolicyFeature feature,
- PolicyValue threshold_value,
- ReportOptions report_on_failure,
- const String& message,
- const String& source_file) const {
- return GetExecutionContext() &&
- GetExecutionContext()->IsFeatureEnabled(
- feature, threshold_value, report_on_failure, message, source_file);
+ const String& message) const {
+ return GetExecutionContext() && GetExecutionContext()->IsFeatureEnabled(
+ feature, report_on_failure, message);
}
bool Document::IsFeatureEnabled(mojom::blink::DocumentPolicyFeature feature,
@@ -2064,7 +2056,7 @@ void Document::DidChangeVisibilityState() {
*Event::CreateBubble(event_type_names::kWebkitvisibilitychange));
if (IsPageVisible())
- Timeline().SetAllCompositorPending();
+ GetDocumentAnimations().MarkAnimationsCompositorPending();
if (hidden() && canvas_font_cache_)
canvas_font_cache_->PruneAll();
@@ -2510,7 +2502,7 @@ static void AssertLayoutTreeUpdated(Node& root) {
Node* node = &root;
while (node) {
if (auto* element = DynamicTo<Element>(node)) {
- if (RuntimeEnabledFeatures::CSSSubtreeVisibilityEnabled() &&
+ if (RuntimeEnabledFeatures::CSSContentVisibilityEnabled() &&
element->StyleRecalcBlockedByDisplayLock(
DisplayLockLifecycleTarget::kChildren)) {
node = FlatTreeTraversal::NextSkippingChildren(*node);
@@ -2705,7 +2697,7 @@ bool Document::NeedsLayoutTreeUpdateForNode(const Node& node,
bool ignore_adjacent_style) const {
// TODO(rakina): Switch some callers that may need to call
// NeedsLayoutTreeUpdateForNodeIncludingDisplayLocked instead of this.
- if (DisplayLockUtilities::NearestLockedExclusiveAncestor(node)) {
+ if (DisplayLockUtilities::LockedAncestorPreventingStyle(node)) {
// |node| is in a locked-subtree, so we don't need to update it.
return false;
}
@@ -2718,7 +2710,8 @@ bool Document::NeedsLayoutTreeUpdateForNodeIncludingDisplayLocked(
bool ignore_adjacent_style) const {
if (!node.CanParticipateInFlatTree())
return false;
- if (locked_display_lock_count_ == 0 && !NeedsLayoutTreeUpdate())
+ if (GetDisplayLockDocumentState().LockedDisplayLockCount() == 0 &&
+ !NeedsLayoutTreeUpdate())
return false;
if (!node.isConnected())
return false;
@@ -2766,7 +2759,7 @@ void Document::UpdateStyleAndLayoutTreeForNode(const Node* node) {
if (!NeedsLayoutTreeUpdateForNodeIncludingDisplayLocked(*node))
return;
- DisplayLockUtilities::ScopedChainForcedUpdate scoped_update_forced(node);
+ DisplayLockUtilities::ScopedForcedUpdate scoped_update_forced(node);
UpdateStyleAndLayoutTree();
}
@@ -2781,7 +2774,7 @@ void Document::UpdateStyleAndLayoutTreeForSubtree(const Node* node) {
if (NeedsLayoutTreeUpdateForNodeIncludingDisplayLocked(*node) ||
node->ChildNeedsStyleRecalc() || node->ChildNeedsStyleInvalidation()) {
- DisplayLockUtilities::ScopedChainForcedUpdate scoped_update_forced(node);
+ DisplayLockUtilities::ScopedForcedUpdate scoped_update_forced(node);
UpdateStyleAndLayoutTree();
}
}
@@ -2792,7 +2785,7 @@ void Document::UpdateStyleAndLayoutForNode(const Node* node,
if (!node->InActiveDocument())
return;
- DisplayLockUtilities::ScopedChainForcedUpdate scoped_update_forced(node);
+ DisplayLockUtilities::ScopedForcedUpdate scoped_update_forced(node);
UpdateStyleAndLayout(reason);
}
@@ -2800,9 +2793,9 @@ void Document::ApplyScrollRestorationLogic() {
// This function in not re-entrant. However, the places that invoke this are
// re-entrant. Specifically, UpdateStyleAndLayout() calls this, which in turn
// can do a find-in-page for the scroll-to-text feature, which can cause
- // UpdateStyleAndLayout to happen with subtree-visibility, which gets back here
- // and recurses indefinitely. As a result, we ensure to early out from this
- // function if are currently in process of restoring scroll.
+ // UpdateStyleAndLayout to happen with content-visibility, which gets back
+ // here and recurses indefinitely. As a result, we ensure to early out from
+ // this function if are currently in process of restoring scroll.
if (applying_scroll_restoration_logic_)
return;
base::AutoReset<bool> applying_scroll_restoration_logic_scope(
@@ -2885,8 +2878,8 @@ void Document::MarkHasFindInPageRequest() {
had_find_in_page_request_ = true;
}
-void Document::MarkHasFindInPageSubtreeVisibilityActiveMatch() {
- // Note that although find-in-page in subtree-visibility requests happen in
+void Document::MarkHasFindInPageContentVisibilityActiveMatch() {
+ // Note that although find-in-page in content-visibility requests happen in
// non-main frames, we only record the main frame results (per UKM policy).
// Additionally, we only record the event once.
if (had_find_in_page_render_subtree_active_match_ || !IsInMainFrame())
@@ -2951,15 +2944,21 @@ void Document::LayoutUpdated() {
// Plugins can run script inside layout which can detach the page.
// TODO(dcheng): Does it make sense to do any of this work if detached?
- if (GetFrame()) {
- if (GetFrame()->IsMainFrame())
- GetFrame()->GetPage()->GetChromeClient().MainFrameLayoutUpdated();
+ if (auto* frame = GetFrame()) {
+ if (frame->IsMainFrame())
+ frame->GetPage()->GetChromeClient().MainFrameLayoutUpdated();
// We do attach here, during lifecycle update, because until then we
// don't have a good place that has access to its local root's FrameWidget.
// TODO(dcheng): If we create FrameWidget before Frame then we could move
// this to Document::Initialize().
AttachCompositorTimeline(Timeline().CompositorTimeline());
+
+ frame->Client()->DidObserveLayoutNg(
+ layout_blocks_counter_, layout_blocks_counter_ng_,
+ layout_calls_counter_, layout_calls_counter_ng_);
+ layout_blocks_counter_ = layout_blocks_counter_ng_ = layout_calls_counter_ =
+ layout_calls_counter_ng_ = 0;
}
Markers().InvalidateRectsForAllTextMatchMarkers();
@@ -2985,12 +2984,8 @@ void Document::DetachCompositorTimeline(
!GetSettings()->GetAcceleratedCompositingEnabled())
return;
- // This requires detaching all animations from timeline first before detaching
- // timeline.
- if (timeline->GetAnimationTimeline()->IsScrollTimeline() &&
- timeline->GetAnimationTimeline()->HasAnimation())
- return;
-
+ // During Document::Shutdown() the timeline needs to be unconditionally
+ // detached.
GetPage()->GetChromeClient().DetachCompositorAnimationTimeline(timeline,
GetFrame());
}
@@ -3019,7 +3014,7 @@ void Document::EnsurePaintLocationDataValidForNode(
if (!node->InActiveDocument())
return;
- DisplayLockUtilities::ScopedChainForcedUpdate scoped_update_forced(node);
+ DisplayLockUtilities::ScopedForcedUpdate scoped_update_forced(node);
// For all nodes we must have up-to-date style and have performed layout to do
// any location-based calculation.
@@ -3049,16 +3044,12 @@ bool Document::IsPageBoxVisible(int page_index) {
EVisibility::kHidden; // display property doesn't apply to @page.
}
-void Document::PageSizeAndMarginsInPixels(int page_index,
- DoubleSize& page_size,
- int& margin_top,
- int& margin_right,
- int& margin_bottom,
- int& margin_left) {
+void Document::GetPageDescription(int page_index,
+ WebPrintPageDescription* description) {
scoped_refptr<const ComputedStyle> style = StyleForPage(page_index);
- double width = page_size.Width();
- double height = page_size.Height();
+ double width = description->size.Width();
+ double height = description->size.Height();
switch (style->GetPageSizeType()) {
case PageSizeType::kAuto:
break;
@@ -3079,23 +3070,21 @@ void Document::PageSizeAndMarginsInPixels(int page_index,
default:
NOTREACHED();
}
- page_size = DoubleSize(width, height);
+ description->size = WebDoubleSize(width, height);
// The percentage is calculated with respect to the width even for margin top
// and bottom.
// http://www.w3.org/TR/CSS2/box.html#margin-properties
- margin_top = style->MarginTop().IsAuto()
- ? margin_top
- : IntValueForLength(style->MarginTop(), width);
- margin_right = style->MarginRight().IsAuto()
- ? margin_right
- : IntValueForLength(style->MarginRight(), width);
- margin_bottom = style->MarginBottom().IsAuto()
- ? margin_bottom
- : IntValueForLength(style->MarginBottom(), width);
- margin_left = style->MarginLeft().IsAuto()
- ? margin_left
- : IntValueForLength(style->MarginLeft(), width);
+ if (!style->MarginTop().IsAuto())
+ description->margin_top = IntValueForLength(style->MarginTop(), width);
+ if (!style->MarginRight().IsAuto())
+ description->margin_right = IntValueForLength(style->MarginRight(), width);
+ if (!style->MarginBottom().IsAuto()) {
+ description->margin_bottom =
+ IntValueForLength(style->MarginBottom(), width);
+ }
+ if (!style->MarginLeft().IsAuto())
+ description->margin_left = IntValueForLength(style->MarginLeft(), width);
}
void Document::SetIsViewSource(bool is_view_source) {
@@ -3278,7 +3267,6 @@ void Document::Shutdown() {
CancelPendingJavaScriptUrls();
http_refresh_scheduler_->Cancel();
- GetFrame()->CancelFormSubmission();
DetachCompositorTimeline(Timeline().CompositorTimeline());
@@ -4442,8 +4430,8 @@ void Document::write(v8::Isolate* isolate,
StringBuilder builder;
for (const String& string : text)
builder.Append(string);
- String string =
- TrustedTypesCheckForHTML(builder.ToString(), this, exception_state);
+ String string = TrustedTypesCheckForHTML(
+ builder.ToString(), GetExecutionContext(), exception_state);
if (exception_state.HadException())
return;
@@ -4459,8 +4447,8 @@ void Document::writeln(v8::Isolate* isolate,
StringBuilder builder;
for (const String& string : text)
builder.Append(string);
- String string =
- TrustedTypesCheckForHTML(builder.ToString(), this, exception_state);
+ String string = TrustedTypesCheckForHTML(
+ builder.ToString(), GetExecutionContext(), exception_state);
if (exception_state.HadException())
return;
@@ -4689,10 +4677,6 @@ void Document::ProcessBaseElement() {
}
}
-String Document::UserAgent() const {
- return GetFrame() ? GetFrame()->Loader().UserAgent() : String();
-}
-
void Document::DidLoadAllImports() {
if (!HaveScriptBlockingStylesheetsLoaded())
return;
@@ -4775,7 +4759,7 @@ void Document::MaybeHandleHttpRefresh(const String& content,
}
if (http_refresh_type == kHttpRefreshFromMetaTag &&
- IsSandboxed(mojom::blink::WebSandboxFlags::kAutomaticFeatures)) {
+ IsSandboxed(network::mojom::blink::WebSandboxFlags::kAutomaticFeatures)) {
String message =
"Refused to execute the redirect specified via '<meta "
"http-equiv='refresh' content='...'>'. The document is sandboxed, and "
@@ -5045,8 +5029,8 @@ Node* Document::Clone(Document& factory, CloneChildrenFlag flag) const {
<< "Document::Clone() doesn't support importNode mode.";
Document* clone = CloneDocumentWithoutChildren();
clone->CloneDataFromDocument(*this);
- if (flag == CloneChildrenFlag::kClone)
- clone->CloneChildNodesFrom(*this);
+ if (flag != CloneChildrenFlag::kSkip)
+ clone->CloneChildNodesFrom(*this, flag);
return clone;
}
@@ -5393,6 +5377,9 @@ void Document::NotifyFocusedElementChanged(Element* old_focused_element,
if (GetSettings()->GetSpatialNavigationEnabled())
GetPage()->GetSpatialNavigationController().FocusedNodeChanged(this);
}
+
+ blink::NotifyPriorityScrollAnchorStatusChanged(old_focused_element,
+ new_focused_element);
}
void Document::SetSequentialFocusNavigationStartingPoint(Node* node) {
@@ -5895,7 +5882,7 @@ String Document::cookie(ExceptionState& exception_state) const {
CountUse(WebFeature::kCookieGet);
if (!GetSecurityOrigin()->CanAccessCookies()) {
- if (IsSandboxed(mojom::blink::WebSandboxFlags::kOrigin))
+ if (IsSandboxed(network::mojom::blink::WebSandboxFlags::kOrigin))
exception_state.ThrowSecurityError(
"The document is sandboxed and lacks the 'allow-same-origin' flag.");
else if (Url().ProtocolIsData())
@@ -5921,7 +5908,7 @@ void Document::setCookie(const String& value, ExceptionState& exception_state) {
UseCounter::Count(*this, WebFeature::kCookieSet);
if (!GetSecurityOrigin()->CanAccessCookies()) {
- if (IsSandboxed(mojom::blink::WebSandboxFlags::kOrigin))
+ if (IsSandboxed(network::mojom::blink::WebSandboxFlags::kOrigin))
exception_state.ThrowSecurityError(
"The document is sandboxed and lacks the 'allow-same-origin' flag.");
else if (Url().ProtocolIsData())
@@ -5980,7 +5967,7 @@ void Document::setDomain(const String& raw_domain,
return;
}
- if (IsSandboxed(mojom::blink::WebSandboxFlags::kDocumentDomain)) {
+ if (IsSandboxed(network::mojom::blink::WebSandboxFlags::kDocumentDomain)) {
exception_state.ThrowSecurityError(
"Assignment is forbidden for sandboxed iframes.");
return;
@@ -6105,12 +6092,6 @@ String Document::lastModified() const {
exploded.minute, exploded.second);
}
-void Document::SetFindInPageRoot(Element* find_in_page_root) {
- DCHECK(RuntimeEnabledFeatures::InvisibleDOMEnabled());
- DCHECK(!find_in_page_root || !find_in_page_root_);
- find_in_page_root_ = find_in_page_root;
-}
-
scoped_refptr<const SecurityOrigin> Document::TopFrameOrigin() const {
if (!GetFrame())
return scoped_refptr<const SecurityOrigin>();
@@ -6144,12 +6125,13 @@ net::SiteForCookies Document::SiteForCookies() const {
const Frame* current_frame = GetFrame();
while (current_frame) {
- const SecurityOrigin* cur_security_origin =
- current_frame->GetSecurityContext()->GetSecurityOrigin();
- if (!candidate.IsEquivalent(net::SiteForCookies::FromOrigin(
- cur_security_origin->ToUrlOrigin()))) {
+ const url::Origin cur_security_origin =
+ current_frame->GetSecurityContext()->GetSecurityOrigin()->ToUrlOrigin();
+ if (!candidate.IsEquivalent(
+ net::SiteForCookies::FromOrigin(cur_security_origin))) {
return net::SiteForCookies();
}
+ candidate.MarkIfCrossScheme(cur_security_origin);
current_frame = current_frame->Tree().Parent();
}
@@ -6222,6 +6204,110 @@ ScriptPromise Document::requestStorageAccess(ScriptState* script_state) {
return promise;
}
+ScriptPromise Document::hasTrustToken(ScriptState* script_state,
+ const String& issuer,
+ ExceptionState& exception_state) {
+ ScriptPromiseResolver* resolver =
+ MakeGarbageCollected<ScriptPromiseResolver>(script_state);
+
+ ScriptPromise promise = resolver->Promise();
+
+ // Trust Tokens state is keyed by issuer and top-frame origins that
+ // are both (1) HTTP or HTTPS and (2) potentially trustworthy. Consequently,
+ // we can return early if either the issuer or the top-frame origin fails to
+ // satisfy either of these requirements.
+ KURL issuer_url = KURL(issuer);
+ auto issuer_origin = SecurityOrigin::Create(issuer_url);
+ if (!issuer_url.ProtocolIsInHTTPFamily() ||
+ !issuer_origin->IsPotentiallyTrustworthy()) {
+ exception_state.ThrowTypeError(
+ "hasTrustToken: Trust token issuer origins must be both HTTP(S) and "
+ "secure (\"potentially trustworthy\").");
+ resolver->Reject(exception_state);
+ return promise;
+ }
+
+ scoped_refptr<const SecurityOrigin> top_frame_origin = TopFrameOrigin();
+ if (!top_frame_origin) {
+ // Note: One case where there might be no top frame origin is if this
+ // document is destroyed. In this case, this function will return
+ // `undefined`. Still bother adding the exception and rejecting, just in
+ // case there are other situations in which the top frame origin might be
+ // absent.
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
+ "hasTrustToken: Cannot execute in "
+ "documents lacking top-frame origins.");
+ resolver->Reject(exception_state);
+ return promise;
+ }
+
+ if (!top_frame_origin->IsPotentiallyTrustworthy() ||
+ (top_frame_origin->Protocol() != url::kHttpsScheme &&
+ top_frame_origin->Protocol() != url::kHttpScheme)) {
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kNotAllowedError,
+ "hasTrustToken: Cannot execute in "
+ "documents without secure, HTTP(S), top-frame origins.");
+ resolver->Reject(exception_state);
+ return promise;
+ }
+
+ if (!has_trust_tokens_answerer_.is_bound()) {
+ GetBrowserInterfaceBroker().GetInterface(
+ has_trust_tokens_answerer_.BindNewPipeAndPassReceiver(
+ GetExecutionContext()->GetTaskRunner(TaskType::kInternalDefault)));
+ has_trust_tokens_answerer_.set_disconnect_handler(
+ WTF::Bind(&Document::HasTrustTokensAnswererConnectionError,
+ WrapWeakPersistent(this)));
+ }
+
+ pending_has_trust_tokens_resolvers_.insert(resolver);
+
+ has_trust_tokens_answerer_->HasTrustTokens(
+ issuer_origin,
+ WTF::Bind(
+ [](WeakPersistent<ScriptPromiseResolver> resolver,
+ WeakPersistent<Document> document,
+ network::mojom::blink::HasTrustTokensResultPtr result) {
+ // If there was a Mojo connection error, the promise was already
+ // resolved and deleted.
+ if (!base::Contains(document->pending_has_trust_tokens_resolvers_,
+ resolver)) {
+ return;
+ }
+
+ if (result->status ==
+ network::mojom::blink::TrustTokenOperationStatus::kOk) {
+ resolver->Resolve(result->has_trust_tokens);
+ } else {
+ ScriptState* state = resolver->GetScriptState();
+ ScriptState::Scope scope(state);
+ resolver->Reject(V8ThrowDOMException::CreateOrEmpty(
+ state->GetIsolate(), DOMExceptionCode::kOperationError,
+ "Failed to retrieve hasTrustToken response. (Would "
+ "associating the given issuer with this top-level origin "
+ "have exceeded its number-of-issuers limit?)"));
+ }
+
+ document->pending_has_trust_tokens_resolvers_.erase(resolver);
+ },
+ WrapWeakPersistent(resolver), WrapWeakPersistent(this)));
+
+ return promise;
+}
+
+void Document::HasTrustTokensAnswererConnectionError() {
+ has_trust_tokens_answerer_.reset();
+ for (const auto& resolver : pending_has_trust_tokens_resolvers_) {
+ ScriptState* state = resolver->GetScriptState();
+ ScriptState::Scope scope(state);
+ resolver->Reject(V8ThrowDOMException::CreateOrEmpty(
+ state->GetIsolate(), DOMExceptionCode::kOperationError,
+ "Internal error retrieving hasTrustToken response."));
+ }
+ pending_has_trust_tokens_resolvers_.clear();
+}
+
static bool IsValidNameNonASCII(const LChar* characters, unsigned length) {
if (!IsValidNameStart(characters[0]))
return false;
@@ -7082,7 +7168,7 @@ bool Document::CanExecuteScripts(ReasonForCallingCanExecuteScripts reason) {
// However, there is an exception for cases when the script should bypass the
// main world's CSP (such as for privileged isolated worlds). See
// https://crbug.com/811528.
- if (IsSandboxed(mojom::blink::WebSandboxFlags::kScripts) &&
+ if (IsSandboxed(network::mojom::blink::WebSandboxFlags::kScripts) &&
!ContentSecurityPolicy::ShouldBypassMainWorld(domWindow())) {
// FIXME: This message should be moved off the console once a solution to
// https://bugs.webkit.org/show_bug.cgi?id=103274 exists.
@@ -7234,32 +7320,13 @@ Document::EnsureDocumentExplicitRootIntersectionObserverData() {
return *document_explicit_root_intersection_observer_data_;
}
-ResizeObserverController& Document::EnsureResizeObserverController() {
- if (!resize_observer_controller_) {
- resize_observer_controller_ =
- MakeGarbageCollected<ResizeObserverController>();
- }
- return *resize_observer_controller_;
-}
-
void Document::AddConsoleMessage(ConsoleMessage* message,
- bool discard_duplicates) {
+ bool discard_duplicates) const {
// Don't let non-attached Documents spam the console.
if (domWindow())
domWindow()->AddConsoleMessage(message, discard_duplicates);
}
-void Document::AddInspectorIssue(InspectorIssue* issue) {
- Page* page = GetPage();
-
- if (!page) {
- return;
- }
-
- page->GetInspectorIssueStorage().AddInspectorIssue(GetExecutionContext(),
- issue);
-}
-
void Document::AddToTopLayer(Element* element, const Element* before) {
if (element->IsInTopLayer())
return;
@@ -8049,15 +8116,10 @@ void Document::SetShadowCascadeOrder(ShadowCascadeOrder order) {
shadow_cascade_order_ = order;
}
-PropertyRegistry* Document::GetPropertyRegistry() {
- // TODO(timloh): When the flag is removed, return a reference instead.
- if (!property_registry_ && RuntimeEnabledFeatures::CSSVariables2Enabled())
+PropertyRegistry& Document::EnsurePropertyRegistry() {
+ if (!property_registry_)
property_registry_ = MakeGarbageCollected<PropertyRegistry>();
- return property_registry_;
-}
-
-const PropertyRegistry* Document::GetPropertyRegistry() const {
- return const_cast<Document*>(this)->GetPropertyRegistry();
+ return *property_registry_;
}
void Document::MaybeQueueSendDidEditFieldInInsecureContext() {
@@ -8079,13 +8141,6 @@ void Document::MaybeQueueSendDidEditFieldInInsecureContext() {
WrapWeakPersistent(this)));
}
-CoreProbeSink* Document::GetProbeSink() {
- LocalFrame* frame = GetFrame();
- if (!frame && TemplateDocumentHost())
- frame = TemplateDocumentHost()->GetFrame();
- return probe::ToCoreProbeSink(frame);
-}
-
BrowserInterfaceBrokerProxy& Document::GetBrowserInterfaceBroker() {
if (!GetFrame())
return GetEmptyBrowserInterfaceBroker();
@@ -8109,13 +8164,8 @@ FrameOrWorkerScheduler* Document::GetScheduler() {
scoped_refptr<base::SingleThreadTaskRunner> Document::GetTaskRunner(
TaskType type) {
DCHECK(IsMainThread());
-
- if (ContextDocument() && ContextDocument()->GetFrame())
- return ContextDocument()->GetFrame()->GetTaskRunner(type);
- // In most cases, ContextDocument() will get us to a relevant Frame. In some
- // cases, though, there isn't a good candidate (most commonly when either the
- // passed-in document or ContextDocument() used to be attached to a Frame but
- // has since been detached).
+ if (GetExecutionContext())
+ return GetExecutionContext()->GetTaskRunner(type);
return Thread::Current()->GetTaskRunner();
}
@@ -8211,25 +8261,25 @@ void Document::Trace(Visitor* visitor) {
visitor->Trace(canvas_font_cache_);
visitor->Trace(intersection_observer_controller_);
visitor->Trace(snap_coordinator_);
- visitor->Trace(resize_observer_controller_);
visitor->Trace(property_registry_);
visitor->Trace(network_state_observer_);
visitor->Trace(policy_);
visitor->Trace(slot_assignment_engine_);
visitor->Trace(viewport_data_);
- visitor->Trace(display_lock_contexts_);
visitor->Trace(navigation_initiator_);
visitor->Trace(lazy_load_image_observer_);
visitor->Trace(isolated_world_csp_map_);
- visitor->Trace(find_in_page_root_);
visitor->Trace(computed_node_mapping_);
visitor->Trace(mime_handler_view_before_unload_event_listener_);
visitor->Trace(cookie_jar_);
visitor->Trace(synchronous_mutation_observer_list_);
visitor->Trace(element_explicitly_set_attr_elements_map_);
- visitor->Trace(display_lock_activation_observer_);
+ visitor->Trace(display_lock_document_state_);
visitor->Trace(permission_service_);
+ visitor->Trace(has_trust_tokens_answerer_);
+ visitor->Trace(pending_has_trust_tokens_resolvers_);
visitor->Trace(font_preload_manager_);
+ visitor->Trace(find_in_page_active_match_node_);
Supplementable<Document>::Trace(visitor);
TreeScope::Trace(visitor);
ContainerNode::Trace(visitor);
@@ -8305,7 +8355,8 @@ bool Document::IsFocusAllowed() const {
}
WebFeature uma_type;
- bool sandboxed = IsSandboxed(mojom::blink::WebSandboxFlags::kNavigation);
+ bool sandboxed =
+ IsSandboxed(network::mojom::blink::WebSandboxFlags::kNavigation);
bool ad = frame_->IsAdSubframe();
if (sandboxed) {
uma_type = ad ? WebFeature::kFocusWithoutUserActivationSandboxedAdFrame
@@ -8342,243 +8393,10 @@ WindowAgent& Document::GetWindowAgent() {
return *static_cast<WindowAgent*>(GetAgent());
}
-void Document::CountPotentialFeaturePolicyViolation(
- mojom::blink::FeaturePolicyFeature feature) const {
- wtf_size_t index = static_cast<wtf_size_t>(feature);
- if (potentially_violated_features_.size() == 0) {
- potentially_violated_features_.resize(
- static_cast<wtf_size_t>(mojom::blink::FeaturePolicyFeature::kMaxValue) +
- 1);
- } else if (potentially_violated_features_[index]) {
- return;
- }
- potentially_violated_features_[index] = true;
- UMA_HISTOGRAM_ENUMERATION("Blink.UseCounter.FeaturePolicy.PotentialViolation",
- feature);
-}
-void Document::ReportFeaturePolicyViolation(
- mojom::blink::FeaturePolicyFeature feature,
- mojom::blink::PolicyDisposition disposition,
- const String& message,
- const String& source_file) const {
- if (!RuntimeEnabledFeatures::FeaturePolicyReportingEnabled(this))
- return;
- LocalFrame* frame = GetFrame();
- if (!frame)
- return;
-
- // Construct the feature policy violation report.
- const String& feature_name = GetNameForFeature(feature);
- const String& disp_str =
- (disposition == mojom::blink::PolicyDisposition::kReport ? "report"
- : "enforce");
-
- FeaturePolicyViolationReportBody* body =
- source_file.IsEmpty()
- ? MakeGarbageCollected<FeaturePolicyViolationReportBody>(
- feature_name, "Feature policy violation", disp_str)
- : MakeGarbageCollected<FeaturePolicyViolationReportBody>(
- feature_name, "Feature policy violation", disp_str,
- source_file);
-
- Report* report = MakeGarbageCollected<Report>(
- ReportType::kFeaturePolicyViolation, Url().GetString(), body);
-
- // Send the feature policy violation report to any ReportingObservers.
- auto* reporting_context = ReportingContext::From(domWindow());
- reporting_context->QueueReport(report);
-
- // TODO(iclelland): Report something different in report-only mode
- if (disposition == mojom::blink::PolicyDisposition::kEnforce) {
- frame->Console().AddMessage(MakeGarbageCollected<ConsoleMessage>(
- mojom::ConsoleMessageSource::kViolation,
- mojom::ConsoleMessageLevel::kError,
- (message.IsEmpty() ? ("Feature policy violation: " + feature_name +
- " is not allowed in this document.")
- : message)));
- }
-}
-
-void Document::ReportDocumentPolicyViolation(
- mojom::blink::DocumentPolicyFeature feature,
- mojom::blink::PolicyDisposition disposition,
- const String& message,
- const String& source_file) const {
- LocalFrame* frame = GetFrame();
- if (!frame)
- return;
-
- // Construct the document policy violation report.
- const String& feature_name =
- GetDocumentPolicyFeatureInfoMap().at(feature).feature_name.c_str();
- bool is_report_only = disposition == mojom::blink::PolicyDisposition::kReport;
- const String& disp_str = is_report_only ? "report" : "enforce";
- const DocumentPolicy* relevant_document_policy =
- is_report_only ? GetSecurityContext().GetReportOnlyDocumentPolicy()
- : GetSecurityContext().GetDocumentPolicy();
-
- DocumentPolicyViolationReportBody* body =
- source_file.IsEmpty()
- ? MakeGarbageCollected<DocumentPolicyViolationReportBody>(
- feature_name, "Document policy violation", disp_str)
- : MakeGarbageCollected<DocumentPolicyViolationReportBody>(
- feature_name, "Document policy violation", disp_str,
- source_file);
-
- Report* report = MakeGarbageCollected<Report>(
- ReportType::kDocumentPolicyViolation, Url().GetString(), body);
-
- // Send the document policy violation report to any ReportingObservers.
- auto* reporting_context = ReportingContext::From(domWindow());
- const base::Optional<std::string> endpoint =
- relevant_document_policy->GetFeatureEndpoint(feature);
-
- reporting_context->QueueReport(
- report, endpoint ? Vector<String>{endpoint->c_str()} : Vector<String>{});
-
- // TODO(iclelland): Report something different in report-only mode
- if (!is_report_only) {
- frame->Console().AddMessage(MakeGarbageCollected<ConsoleMessage>(
- mojom::blink::ConsoleMessageSource::kViolation,
- mojom::blink::ConsoleMessageLevel::kError,
- (message.IsEmpty() ? ("Document policy violation: " + feature_name +
- " is not allowed in this document.")
- : message)));
- }
-}
-
void Document::IncrementNumberOfCanvases() {
num_canvases_++;
}
-void Document::IncrementDisplayLockBlockingAllActivation() {
- ++display_lock_blocking_all_activation_count_;
-}
-
-void Document::DecrementDisplayLockBlockingAllActivation() {
- DCHECK_GT(display_lock_blocking_all_activation_count_, 0);
- --display_lock_blocking_all_activation_count_;
-}
-
-int Document::DisplayLockBlockingAllActivationCount() const {
- return display_lock_blocking_all_activation_count_;
-}
-
-void Document::AddLockedDisplayLock() {
- ++locked_display_lock_count_;
- TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("blink.debug.display_lock"),
- "LockedDisplayLockCount", TRACE_ID_LOCAL(this),
- locked_display_lock_count_);
-}
-
-void Document::RemoveLockedDisplayLock() {
- DCHECK_GT(locked_display_lock_count_, 0);
- --locked_display_lock_count_;
- TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("blink.debug.display_lock"),
- "LockedDisplayLockCount", TRACE_ID_LOCAL(this),
- locked_display_lock_count_);
-}
-
-int Document::LockedDisplayLockCount() const {
- return locked_display_lock_count_;
-}
-
-void Document::AddDisplayLockContext(DisplayLockContext* context) {
- display_lock_contexts_.insert(context);
-}
-
-void Document::RemoveDisplayLockContext(DisplayLockContext* context) {
- display_lock_contexts_.erase(context);
-}
-
-int Document::DisplayLockCount() const {
- return display_lock_contexts_.size();
-}
-
-void Document::NotifySelectionRemovedFromDisplayLocks() {
- for (auto context : display_lock_contexts_)
- context->NotifySubtreeLostSelection();
-}
-
-Document::ScopedForceActivatableDisplayLocks
-Document::GetScopedForceActivatableLocks() {
- return ScopedForceActivatableDisplayLocks(this);
-}
-
-Document::ScopedForceActivatableDisplayLocks::
- ScopedForceActivatableDisplayLocks(Document* document)
- : document_(document) {
- if (++document_->activatable_display_locks_forced_ == 1) {
- for (auto context : document_->display_lock_contexts_)
- context->DidForceActivatableDisplayLocks();
- }
-}
-
-Document::ScopedForceActivatableDisplayLocks::
- ScopedForceActivatableDisplayLocks(
- ScopedForceActivatableDisplayLocks&& other)
- : document_(other.document_) {
- other.document_ = nullptr;
-}
-
-Document::ScopedForceActivatableDisplayLocks&
-Document::ScopedForceActivatableDisplayLocks::operator=(
- ScopedForceActivatableDisplayLocks&& other) {
- document_ = other.document_;
- other.document_ = nullptr;
- return *this;
-}
-
-Document::ScopedForceActivatableDisplayLocks::
- ~ScopedForceActivatableDisplayLocks() {
- if (!document_)
- return;
- DCHECK(document_->activatable_display_locks_forced_);
- --document_->activatable_display_locks_forced_;
-}
-
-void Document::RegisterDisplayLockActivationObservation(Element* element) {
- EnsureDisplayLockActivationObserver().observe(element);
-}
-
-void Document::UnregisterDisplayLockActivationObservation(Element* element) {
- EnsureDisplayLockActivationObserver().unobserve(element);
-}
-
-IntersectionObserver& Document::EnsureDisplayLockActivationObserver() {
- if (!display_lock_activation_observer_) {
- // Use kPostTaskToDeliver method, since a commit can dirty layout, and we
- // want to avoid dirtying layout during post-lifecycle steps.
- // Note that we use 50% margin (on the viewport) so that we get the
- // observation before the element enters the viewport.
- display_lock_activation_observer_ = IntersectionObserver::Create(
- {Length::Percent(50.f)}, {std::numeric_limits<float>::min()}, this,
- WTF::BindRepeating(&Document::ProcessDisplayLockActivationObservation,
- WrapWeakPersistent(this)),
- IntersectionObserver::kDeliverDuringPostLifecycleSteps);
- }
- return *display_lock_activation_observer_;
-}
-
-void Document::ProcessDisplayLockActivationObservation(
- const HeapVector<Member<IntersectionObserverEntry>>& entries) {
- DCHECK(View());
- for (auto& entry : entries) {
- auto* context = entry->target()->GetDisplayLockContext();
- DCHECK(context);
- if (entry->isIntersecting()) {
- View()->EnqueueStartOfLifecycleTask(
- WTF::Bind(&DisplayLockContext::NotifyIsIntersectingViewport,
- WrapWeakPersistent(context)));
- } else {
- View()->EnqueueStartOfLifecycleTask(
- WTF::Bind(&DisplayLockContext::NotifyIsNotIntersectingViewport,
- WrapWeakPersistent(context)));
- }
- }
- View()->ScheduleAnimation();
-}
-
void Document::ExecuteJavaScriptUrls() {
DCHECK(frame_);
Vector<PendingJavascriptUrl> urls_to_execute;
@@ -8608,6 +8426,10 @@ void Document::ProcessJavaScriptUrl(
}
}
+DisplayLockDocumentState& Document::GetDisplayLockDocumentState() const {
+ return *display_lock_document_state_;
+}
+
void Document::CancelPendingJavaScriptUrls() {
if (javascript_url_task_handle_.IsActive())
javascript_url_task_handle_.Cancel();
@@ -8687,18 +8509,6 @@ bool Document::InForcedColorsMode() const {
return in_forced_colors_mode_ && !Printing();
}
-bool Document::IsCrossSiteSubframe() const {
- // It'd be nice to avoid the url::Origin temporaries, but that would require
- // exposing the net internal helper.
- // TODO: If the helper gets exposed, we could do this without any new
- // allocations using StringUTF8Adaptor.
- return TopFrameOrigin() &&
- !net::registry_controlled_domains::SameDomainOrHost(
- TopFrameOrigin()->ToUrlOrigin(),
- GetSecurityOrigin()->ToUrlOrigin(),
- net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
-}
-
void Document::CountUse(mojom::WebFeature feature) const {
if (use_counter_during_construction_)
use_counter_during_construction_->CountUse(feature);
@@ -8807,6 +8617,16 @@ void Document::FontPreloadingFinishedOrTimedOut() {
}
}
+void Document::SetFindInPageActiveMatchNode(Node* node) {
+ blink::NotifyPriorityScrollAnchorStatusChanged(
+ find_in_page_active_match_node_, node);
+ find_in_page_active_match_node_ = node;
+}
+
+const Node* Document::GetFindInPageActiveMatchNode() const {
+ return find_in_page_active_match_node_;
+}
+
template class CORE_TEMPLATE_EXPORT Supplement<Document>;
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/dom/document.h b/chromium/third_party/blink/renderer/core/dom/document.h
index 6733851f425..41f485b9aa1 100644
--- a/chromium/third_party/blink/renderer/core/dom/document.h
+++ b/chromium/third_party/blink/renderer/core/dom/document.h
@@ -38,10 +38,13 @@
#include "base/timer/elapsed_timer.h"
#include "net/cookies/site_for_cookies.h"
#include "services/metrics/public/cpp/ukm_source_id.h"
+#include "services/network/public/mojom/trust_tokens.mojom-blink.h"
+#include "services/network/public/mojom/web_sandbox_flags.mojom-blink-forward.h"
#include "third_party/blink/public/common/metrics/document_update_reason.h"
#include "third_party/blink/public/mojom/input/focus_type.mojom-blink-forward.h"
#include "third_party/blink/public/mojom/permissions/permission.mojom-blink.h"
#include "third_party/blink/public/mojom/scroll/scrollbar_mode.mojom-blink.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
#include "third_party/blink/renderer/core/accessibility/axid.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/css/media_value_change.h"
@@ -101,13 +104,12 @@ class ChromeClient;
class Comment;
class CompositorAnimationTimeline;
class ComputedAccessibleNode;
-class DisplayLockContext;
+class DisplayLockDocumentState;
class ElementIntersectionObserverData;
class WindowAgent;
class WindowAgentFactory;
class ComputedStyle;
class ConsoleMessage;
-class InspectorIssue;
class ContextFeatures;
class CookieJar;
class V0CustomElementMicrotaskRunQueue;
@@ -127,7 +129,6 @@ class DocumentAnimations;
class DocumentTimeline;
class DocumentType;
class DOMFeaturePolicy;
-class DoubleSize;
class Element;
class ElementDataCache;
class ElementRegistrationOptions;
@@ -155,9 +156,7 @@ class HTMLScriptElementOrSVGScriptElement;
class HitTestRequest;
class HttpRefreshScheduler;
class IdleRequestOptions;
-class IntersectionObserver;
class IntersectionObserverController;
-class IntersectionObserverEntry;
class LayoutView;
class LazyLoadImageObserver;
class LiveNodeListBase;
@@ -178,7 +177,6 @@ class ProcessingInstruction;
class PropertyRegistry;
class QualifiedName;
class Range;
-class ResizeObserverController;
class ResourceFetcher;
class RootScrollerController;
class ScriptValue;
@@ -217,6 +215,7 @@ struct AnnotatedRegionValue;
struct FocusParams;
struct IconURL;
struct PhysicalOffset;
+struct WebPrintPageDescription;
using MouseEventWithHitTestResults = EventWithHitTestResults<WebMouseEvent>;
@@ -308,34 +307,11 @@ class CORE_EXPORT Document : public ContainerNode,
// should move to LocalDOMWindow.
ContentSecurityPolicy* GetContentSecurityPolicyForWorld();
LocalDOMWindow* ExecutingWindow() const;
- String UserAgent() const;
- // TODO(https://crbug.com/880986): Implement Document's HTTPS state in more
- // spec-conformant way.
- HttpsState GetHttpsState() const {
- return CalculateHttpsState(GetSecurityOrigin());
- }
bool CanExecuteScripts(ReasonForCallingCanExecuteScripts);
String OutgoingReferrer() const;
network::mojom::ReferrerPolicy GetReferrerPolicy() const;
- CoreProbeSink* GetProbeSink();
BrowserInterfaceBrokerProxy& GetBrowserInterfaceBroker();
FrameOrWorkerScheduler* GetScheduler();
- void CountPotentialFeaturePolicyViolation(
- mojom::blink::FeaturePolicyFeature) const;
- void ReportFeaturePolicyViolation(
- mojom::blink::FeaturePolicyFeature,
- mojom::blink::PolicyDisposition,
- const String& message = g_empty_string,
- // If source_file is set to empty string,
- // current JS file would be used as source_file instead.
- const String& source_file = g_empty_string) const;
- void ReportDocumentPolicyViolation(
- mojom::blink::DocumentPolicyFeature,
- mojom::blink::PolicyDisposition disposition,
- const String& message = g_empty_string,
- // If source_file is set to empty string,
- // current JS file would be used as source_file instead.
- const String& source_file = g_empty_string) const;
// FeaturePolicyParserDelegate override
// TODO(crbug.com/1029822) FeaturePolicyParserDelegate overrides, these
@@ -345,48 +321,22 @@ class CORE_EXPORT Document : public ContainerNode,
bool FeaturePolicyFeatureObserved(
mojom::blink::FeaturePolicyFeature feature) override;
+ bool DocumentPolicyFeatureObserved(
+ mojom::blink::DocumentPolicyFeature feature);
+
SecurityContext& GetSecurityContext() { return security_context_; }
const SecurityContext& GetSecurityContext() const {
return security_context_;
}
- // TODO(crbug.com/1029822): Temporary cast helpers while ExecutionContext is
- // migrating to LocalDOMWindow. Callsite that permanently need to convert a
- // Document to an ExecutionContext should use either GetExecutionContext() as
- // inherited from Node, or domWindow().
- // Downcasts will cast to a LocalDOMWindow, then use
- // LocalDOMWindow::document() if the Document is what is actually needed.
- ExecutionContext* ToExecutionContext();
- const ExecutionContext* ToExecutionContext() const;
- static Document* From(ExecutionContext* context) {
- return context ? &From(*context) : nullptr;
- }
- static Document& From(ExecutionContext& context);
- static const Document* From(const ExecutionContext* context) {
- return context ? &From(*context) : nullptr;
- }
- static const Document& From(const ExecutionContext& context);
- static Document* DynamicFrom(ExecutionContext* context) {
- return context && context->IsDocument() ? From(context) : nullptr;
- }
- static Document* DynamicFrom(ExecutionContext& context) {
- return context.IsDocument() ? &From(context) : nullptr;
- }
- static const Document* DynamicFrom(const ExecutionContext* context) {
- return context && context->IsDocument() ? From(context) : nullptr;
- }
- static const Document* DynamicFrom(const ExecutionContext& context) {
- return context.IsDocument() ? &From(context) : nullptr;
- }
-
// TODO(crbug.com/1029822): Temporary helpers to access ExecutionContext
// methods. These will need to be audited. Some might be useful permanent
// helpers.
const SecurityOrigin* GetSecurityOrigin() const;
SecurityOrigin* GetMutableSecurityOrigin();
ContentSecurityPolicy* GetContentSecurityPolicy() const;
- mojom::blink::WebSandboxFlags GetSandboxFlags() const;
- bool IsSandboxed(mojom::blink::WebSandboxFlags mask) const;
+ network::mojom::blink::WebSandboxFlags GetSandboxFlags() const;
+ bool IsSandboxed(network::mojom::blink::WebSandboxFlags mask) const;
PublicURLManager& GetPublicURLManager();
bool IsContextPaused() const;
bool IsContextDestroyed() const;
@@ -402,14 +352,7 @@ class CORE_EXPORT Document : public ContainerNode,
bool IsFeatureEnabled(
mojom::blink::FeaturePolicyFeature,
ReportOptions report_on_failure = ReportOptions::kDoNotReport,
- const String& message = g_empty_string,
- const String& source_file = g_empty_string) const;
- bool IsFeatureEnabled(
- mojom::blink::FeaturePolicyFeature,
- PolicyValue threshold_value,
- ReportOptions report_on_failure = ReportOptions::kDoNotReport,
- const String& message = g_empty_string,
- const String& source_file = g_empty_string) const;
+ const String& message = g_empty_string) const;
bool IsFeatureEnabled(
mojom::blink::DocumentPolicyFeature,
ReportOptions report_option = ReportOptions::kDoNotReport,
@@ -679,6 +622,11 @@ class CORE_EXPORT Document : public ContainerNode,
kRunPostLayoutTasksSynchronously,
};
void UpdateStyleAndLayoutForNode(const Node*, DocumentUpdateReason);
+ void IncLayoutCallsCounter() { ++layout_calls_counter_; }
+ void IncLayoutCallsCounterNG() { ++layout_calls_counter_ng_; }
+ void IncLayoutBlockCounter() { ++layout_blocks_counter_; }
+ void IncLayoutBlockCounterNG() { ++layout_blocks_counter_ng_; }
+
scoped_refptr<const ComputedStyle> StyleForPage(int page_index);
// Ensures that location-based data will be valid for a given node.
@@ -695,16 +643,11 @@ class CORE_EXPORT Document : public ContainerNode,
// Returns true if page box (margin boxes and page borders) is visible.
bool IsPageBoxVisible(int page_index);
- // Returns the preferred page size and margins in pixels, assuming 96
- // pixels per inch. pageSize, marginTop, marginRight, marginBottom,
- // marginLeft must be initialized to the default values that are used if
- // auto is specified.
- void PageSizeAndMarginsInPixels(int page_index,
- DoubleSize& page_size,
- int& margin_top,
- int& margin_right,
- int& margin_bottom,
- int& margin_left);
+ // Gets the description for the specified page. This includes preferred page
+ // size and margins in pixels, assuming 96 pixels per inch. The size and
+ // margins must be initialized to the default values that are used if auto is
+ // specified.
+ void GetPageDescription(int page_index, WebPrintPageDescription*);
ResourceFetcher* Fetcher() const { return fetcher_.Get(); }
@@ -1079,11 +1022,6 @@ class CORE_EXPORT Document : public ContainerNode,
ElementIntersectionObserverData&
EnsureDocumentExplicitRootIntersectionObserverData();
- ResizeObserverController* GetResizeObserverController() const {
- return resize_observer_controller_;
- }
- ResizeObserverController& EnsureResizeObserverController();
-
// Returns the owning element in the parent document. Returns nullptr if
// this is the top level document or the owner is remote.
HTMLFrameOwnerElement* LocalOwner() const;
@@ -1117,10 +1055,6 @@ class CORE_EXPORT Document : public ContainerNode,
}
String lastModified() const;
- Element* FindInPageRoot() const { return find_in_page_root_.Get(); }
-
- void SetFindInPageRoot(Element* find_in_page_root);
-
// The cookieURL is used to query the cookie database for this document's
// cookies. For example, if the cookie URL is http://example.com, we'll
// use the non-Secure cookies for example.com when computing
@@ -1134,6 +1068,7 @@ class CORE_EXPORT Document : public ContainerNode,
const KURL& CookieURL() const { return cookie_url_; }
void SetCookieURL(const KURL& url) { cookie_url_ = url; }
+ // Returns null if the document is not attached to a frame.
scoped_refptr<const SecurityOrigin> TopFrameOrigin() const;
net::SiteForCookies SiteForCookies() const;
@@ -1149,6 +1084,15 @@ class CORE_EXPORT Document : public ContainerNode,
ScriptPromise hasStorageAccess(ScriptState* script_state) const;
ScriptPromise requestStorageAccess(ScriptState* script_state);
+ // Sends a query via Mojo to ask whether the user has any trust tokens. This
+ // can reject on permissions errors (e.g. associating |issuer| with the
+ // top-level origin would exceed the top-level origin's limit on the number of
+ // associated issuers) or on other internal errors (e.g. the network service
+ // is unavailable).
+ ScriptPromise hasTrustToken(ScriptState* script_state,
+ const String& issuer,
+ ExceptionState&);
+
// The following implements the rule from HTML 4 for what valid names are.
// To get this right for all the XML cases, we probably have to improve this
// or move it and make it sensitive to the type of document.
@@ -1334,9 +1278,6 @@ class CORE_EXPORT Document : public ContainerNode,
void DispatchEventsForPrinting();
- bool HasFullscreenSupplement() const { return has_fullscreen_supplement_; }
- void SetHasFullscreenSupplement() { has_fullscreen_supplement_ = true; }
-
void exitPointerLock();
Element* PointerLockElement() const;
@@ -1450,8 +1391,7 @@ class CORE_EXPORT Document : public ContainerNode,
void DidAssociateFormControl(Element*);
void AddConsoleMessage(ConsoleMessage* message,
- bool discard_duplicates = false);
- void AddInspectorIssue(InspectorIssue*);
+ bool discard_duplicates = false) const;
LocalFrame* ExecutingFrame();
@@ -1525,8 +1465,10 @@ class CORE_EXPORT Document : public ContainerNode,
bool IsInMainFrame() const;
- const PropertyRegistry* GetPropertyRegistry() const;
- PropertyRegistry* GetPropertyRegistry();
+ const PropertyRegistry* GetPropertyRegistry() const {
+ return property_registry_;
+ }
+ PropertyRegistry& EnsurePropertyRegistry();
// Used to notify the embedder when the user edits the value of a
// text field in a non-secure context.
@@ -1624,45 +1566,7 @@ class CORE_EXPORT Document : public ContainerNode,
void ProcessJavaScriptUrl(const KURL&, network::mojom::CSPDisposition);
- // Functions to keep count of display locks in this document.
- void IncrementDisplayLockBlockingAllActivation();
- void DecrementDisplayLockBlockingAllActivation();
- int DisplayLockBlockingAllActivationCount() const;
-
- void AddLockedDisplayLock();
- void RemoveLockedDisplayLock();
- int LockedDisplayLockCount() const;
-
- void AddDisplayLockContext(DisplayLockContext*);
- void RemoveDisplayLockContext(DisplayLockContext*);
- int DisplayLockCount() const;
- void NotifySelectionRemovedFromDisplayLocks();
-
- // Manage the element's observation for display lock activation.
- void RegisterDisplayLockActivationObservation(Element*);
- void UnregisterDisplayLockActivationObservation(Element*);
-
- class ScopedForceActivatableDisplayLocks {
- STACK_ALLOCATED();
-
- public:
- ScopedForceActivatableDisplayLocks(ScopedForceActivatableDisplayLocks&&);
- ~ScopedForceActivatableDisplayLocks();
-
- ScopedForceActivatableDisplayLocks& operator=(
- ScopedForceActivatableDisplayLocks&&);
-
- private:
- friend Document;
- ScopedForceActivatableDisplayLocks(Document*);
-
- Document* document_;
- };
-
- ScopedForceActivatableDisplayLocks GetScopedForceActivatableLocks();
- bool ActivatableDisplayLocksForced() const {
- return activatable_display_locks_forced_ > 0;
- }
+ DisplayLockDocumentState& GetDisplayLockDocumentState() const;
// Deferred compositor commits are disallowed by default, and are only allowed
// for same-origin navigations to an html document fetched with http.
@@ -1729,11 +1633,6 @@ class CORE_EXPORT Document : public ContainerNode,
void UpdateForcedColors();
bool InForcedColorsMode() const;
- // Returns true if the subframe document is cross-site to the main frame. If
- // we can't tell whether the document was ever cross-site or not (e.g. it is
- // not the active Document in a browsing context), return false.
- bool IsCrossSiteSubframe() const;
-
// Capture the toggle event during parsing either by HTML parser or XML
// parser.
void SetToggleDuringParsing(bool toggle_during_parsing) {
@@ -1769,7 +1668,7 @@ class CORE_EXPORT Document : public ContainerNode,
void ApplyScrollRestorationLogic();
void MarkHasFindInPageRequest();
- void MarkHasFindInPageSubtreeVisibilityActiveMatch();
+ void MarkHasFindInPageContentVisibilityActiveMatch();
void CancelPendingJavaScriptUrls();
@@ -1787,6 +1686,9 @@ class CORE_EXPORT Document : public ContainerNode,
FontPreloadManager& GetFontPreloadManager() { return font_preload_manager_; }
void FontPreloadingFinishedOrTimedOut();
+ void SetFindInPageActiveMatchNode(Node*);
+ const Node* GetFindInPageActiveMatchNode() const;
+
protected:
void ClearXMLVersion() { xml_version_ = String(); }
@@ -1798,6 +1700,7 @@ class CORE_EXPORT Document : public ContainerNode,
}
private:
+ friend class DocumentTest;
friend class IgnoreDestructiveWriteCountIncrementer;
friend class ThrowOnDynamicMarkupInsertionCountIncrementer;
friend class IgnoreOpensDuringUnloadCountIncrementer;
@@ -1933,10 +1836,9 @@ class CORE_EXPORT Document : public ContainerNode,
Element* new_focused_element);
void DisplayNoneChangedForFrame();
- IntersectionObserver& EnsureDisplayLockActivationObserver();
-
- void ProcessDisplayLockActivationObservation(
- const HeapVector<Member<IntersectionObserverEntry>>&);
+ // Handles a connection error to |has_trust_tokens_answerer_| by rejecting all
+ // pending promises created by |hasTrustToken|.
+ void HasTrustTokensAnswererConnectionError();
DocumentLifecycle lifecycle_;
@@ -1971,11 +1873,6 @@ class CORE_EXPORT Document : public ContainerNode,
bool well_formed_;
- // When doing find-in-page and we need to calculate style & layout tree for
- // invisible nodes, this variable will be set with the invisible root for
- // the currently processed block in find-in-page.
- WeakMember<Element> find_in_page_root_;
-
// Document URLs.
KURL url_; // Document.URL: The URL from which this document was retrieved.
KURL base_url_; // Node.baseURI: The URL to use when resolving relative URLs.
@@ -2149,9 +2046,6 @@ class CORE_EXPORT Document : public ContainerNode,
LayoutView* layout_view_;
- // For early return in Fullscreen::fromIfExists()
- bool has_fullscreen_supplement_;
-
// The last element in |top_layer_elements_| is topmost in the top layer
// stack and is thus the one that will be visually on top.
HeapVector<Member<Element>> top_layer_elements_;
@@ -2201,7 +2095,6 @@ class CORE_EXPORT Document : public ContainerNode,
Member<CanvasFontCache> canvas_font_cache_;
Member<IntersectionObserverController> intersection_observer_controller_;
- Member<ResizeObserverController> resize_observer_controller_;
int node_count_;
@@ -2248,14 +2141,19 @@ class CORE_EXPORT Document : public ContainerNode,
// The number of canvas elements on the document
int num_canvases_ = 0;
- // Number of display locks in this document that block all activation.
- int display_lock_blocking_all_activation_count_ = 0;
- // Number of locked display locks in the document.
- int locked_display_lock_count_ = 0;
- // All of this document's display lock contexts.
- HeapHashSet<WeakMember<DisplayLockContext>> display_lock_contexts_;
- // If non-zero, then the activatable locks have been globally forced.
- int activatable_display_locks_forced_ = 0;
+ // The number of LayoutObject::UpdateLayout() calls for both of the legacy
+ // layout and LayoutNG.
+ uint32_t layout_calls_counter_ = 0;
+
+ // The number of LayoutObject::UpdateLayout() calls for LayoutNG.
+ uint32_t layout_calls_counter_ng_ = 0;
+
+ // The number of LayoutBlock instances for both of the legacy layout
+ // and LayoutNG.
+ uint32_t layout_blocks_counter_ = 0;
+
+ // The number of LayoutNGMixin<LayoutBlock> instances
+ uint32_t layout_blocks_counter_ng_ = 0;
bool deferred_compositor_commit_is_allowed_ = false;
@@ -2267,18 +2165,13 @@ class CORE_EXPORT Document : public ContainerNode,
#if DCHECK_IS_ON()
// Allow traversal of Shadow DOM V0 traversal with dirty distribution.
- // Required for marking ancestors style-child-dirty for FlatTreeStyleRecalc.
+ // Required for marking ancestors style-child-dirty.
bool allow_dirty_shadow_v0_traversal_ = false;
#endif
Member<NavigationInitiatorImpl> navigation_initiator_;
Member<LazyLoadImageObserver> lazy_load_image_observer_;
- // Tracks which features have already been potentially violated in this
- // document. This helps to count them only once per page load.
- // We don't use std::bitset to avoid to include feature_policy.mojom-blink.h.
- mutable Vector<bool> potentially_violated_features_;
-
// Pending feature policy headers to send to browser after DidCommitNavigation
// IPC.
ParsedFeaturePolicy pending_fp_headers_;
@@ -2295,6 +2188,8 @@ class CORE_EXPORT Document : public ContainerNode,
// The size of this vector is 0 until FeaturePolicyFeatureObserved is called.
Vector<bool> parsed_feature_policies_;
+ Vector<bool> parsed_document_policies_;
+
AtomicString override_last_modified_;
// Map from isolated world IDs to their ContentSecurityPolicy instances.
@@ -2332,7 +2227,7 @@ class CORE_EXPORT Document : public ContainerNode,
HeapObserverList<SynchronousMutationObserver>
synchronous_mutation_observer_list_;
- Member<IntersectionObserver> display_lock_activation_observer_;
+ Member<DisplayLockDocumentState> display_lock_document_state_;
bool in_forced_colors_mode_;
@@ -2346,7 +2241,25 @@ class CORE_EXPORT Document : public ContainerNode,
// storage or not.
HeapMojoRemote<mojom::blink::PermissionService> permission_service_;
+ // Mojo remote used to answer API calls asking whether the user has trust
+ // tokens (https://github.com/wicg/trust-token-api). The other endpoint
+ // is in the network service, which may crash and restart. To handle this:
+ // 1. |pending_has_trust_tokens_resolvers_| keeps track of promises
+ // depending on |has_trust_tokens_answerer_|'s answers;
+ // 2. |HasTrustTokensAnswererConnectionError| handles connection errors by
+ // rejecting all pending promises and clearing the pending set.
+ HeapMojoRemote<network::mojom::blink::HasTrustTokensAnswerer>
+ has_trust_tokens_answerer_;
+
+ // In order to be able to answer promises when the Mojo remote disconnects,
+ // maintain all pending promises here, deleting them on successful completion
+ // or on connection error, whichever comes first.
+ HeapHashSet<Member<ScriptPromiseResolver>>
+ pending_has_trust_tokens_resolvers_;
+
FontPreloadManager font_preload_manager_;
+
+ WeakMember<Node> find_in_page_active_match_node_;
};
extern template class CORE_EXTERN_TEMPLATE_EXPORT Supplement<Document>;
diff --git a/chromium/third_party/blink/renderer/core/dom/document.idl b/chromium/third_party/blink/renderer/core/dom/document.idl
index a8025f5cf65..efce87b4f66 100644
--- a/chromium/third_party/blink/renderer/core/dom/document.idl
+++ b/chromium/third_party/blink/renderer/core/dom/document.idl
@@ -200,6 +200,9 @@ typedef (HTMLScriptElement or SVGScriptElement) HTMLOrSVGScriptElement;
[MeasureAs=PrefixedPageVisibility, ImplementedAs=visibilityState] readonly attribute DOMString webkitVisibilityState;
[MeasureAs=PrefixedPageVisibility, ImplementedAs=hidden] readonly attribute boolean webkitHidden;
+ // Trust Token API (https://github.com/wicg/trust-token-api)
+ [CallWith=ScriptState, Measure, RaisesException, NewObject, SecureContext, RuntimeEnabled=TrustTokens] Promise<boolean> hasTrustToken(USVString issuer);
+
// Event handler attributes
attribute EventHandler onbeforecopy;
attribute EventHandler onbeforecut;
diff --git a/chromium/third_party/blink/renderer/core/dom/document_fragment.cc b/chromium/third_party/blink/renderer/core/dom/document_fragment.cc
index b32f0044c32..0cd276b9e5d 100644
--- a/chromium/third_party/blink/renderer/core/dom/document_fragment.cc
+++ b/chromium/third_party/blink/renderer/core/dom/document_fragment.cc
@@ -62,8 +62,8 @@ bool DocumentFragment::ChildTypeAllowed(NodeType type) const {
Node* DocumentFragment::Clone(Document& factory, CloneChildrenFlag flag) const {
DocumentFragment* clone = Create(factory);
- if (flag == CloneChildrenFlag::kClone)
- clone->CloneChildNodesFrom(*this);
+ if (flag != CloneChildrenFlag::kSkip)
+ clone->CloneChildNodesFrom(*this, flag);
return clone;
}
diff --git a/chromium/third_party/blink/renderer/core/dom/document_init.cc b/chromium/third_party/blink/renderer/core/dom/document_init.cc
index c9c761dd34e..8d1802954e2 100644
--- a/chromium/third_party/blink/renderer/core/dom/document_init.cc
+++ b/chromium/third_party/blink/renderer/core/dom/document_init.cc
@@ -29,6 +29,8 @@
#include "third_party/blink/renderer/core/dom/document_init.h"
+#include "services/network/public/cpp/web_sandbox_flags.h"
+#include "services/network/public/mojom/web_sandbox_flags.mojom-blink.h"
#include "third_party/blink/public/mojom/security_context/insecure_request_policy.mojom-blink.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/dom_implementation.h"
@@ -61,28 +63,21 @@ static Document* ParentDocument(DocumentLoader* loader) {
return &owner_element->GetDocument();
}
+// static
DocumentInit DocumentInit::Create() {
- return DocumentInit(nullptr);
+ return DocumentInit();
}
-DocumentInit DocumentInit::CreateWithImportsController(
- HTMLImportsController* controller) {
- DCHECK(controller);
- Document* master = controller->Master();
- return DocumentInit(controller)
- .WithContextDocument(master->ContextDocument())
- .WithRegistrationContext(master->RegistrationContext());
-}
-
-DocumentInit::DocumentInit(HTMLImportsController* imports_controller)
- : imports_controller_(imports_controller),
- create_new_registration_context_(false),
- content_security_policy_from_context_doc_(false) {}
-
DocumentInit::DocumentInit(const DocumentInit&) = default;
DocumentInit::~DocumentInit() = default;
+DocumentInit& DocumentInit::WithImportsController(
+ HTMLImportsController* controller) {
+ imports_controller_ = controller;
+ return *this;
+}
+
bool DocumentInit::ShouldSetURL() const {
DocumentLoader* loader = MasterDocumentLoader();
return (loader && loader->GetFrame()->Tree().Parent()) || !url_.IsEmpty();
@@ -105,8 +100,8 @@ DocumentLoader* DocumentInit::MasterDocumentLoader() const {
return nullptr;
}
-mojom::blink::WebSandboxFlags DocumentInit::GetSandboxFlags() const {
- mojom::blink::WebSandboxFlags flags = sandbox_flags_;
+network::mojom::blink::WebSandboxFlags DocumentInit::GetSandboxFlags() const {
+ network::mojom::blink::WebSandboxFlags flags = sandbox_flags_;
if (DocumentLoader* loader = MasterDocumentLoader())
flags |= loader->GetFrame()->Loader().EffectiveSandboxFlags();
// If the load was blocked by CSP, force the Document's origin to be unique,
@@ -114,7 +109,7 @@ mojom::blink::WebSandboxFlags DocumentInit::GetSandboxFlags() const {
// document's load per CSP spec:
// https://www.w3.org/TR/CSP3/#directive-frame-ancestors.
if (blocked_by_csp_)
- flags |= mojom::blink::WebSandboxFlags::kOrigin;
+ flags |= network::mojom::blink::WebSandboxFlags::kOrigin;
return flags;
}
@@ -162,80 +157,90 @@ UseCounter* DocumentInit::GetUseCounter() const {
return document_loader_;
}
-DocumentInit& DocumentInit::WithTypeFrom(const String& type) {
- mime_type_ = type;
-
- if (GetFrame() && GetFrame()->InViewSourceMode()) {
- type_ = Type::kViewSource;
- return *this;
- }
+// static
+DocumentInit::Type DocumentInit::ComputeDocumentType(
+ LocalFrame* frame,
+ const KURL& url,
+ const String& mime_type,
+ bool* is_for_external_handler) {
+ if (frame && frame->InViewSourceMode())
+ return Type::kViewSource;
// Plugins cannot take HTML and XHTML from us, and we don't even need to
// initialize the plugin database for those.
- if (type == "text/html") {
- type_ = Type::kHTML;
- return *this;
- }
- if (type == "application/xhtml+xml") {
- type_ = Type::kXHTML;
- return *this;
- }
+ if (mime_type == "text/html")
+ return Type::kHTML;
+
+ if (mime_type == "application/xhtml+xml")
+ return Type::kXHTML;
+
// multipart/x-mixed-replace is only supported for images.
- if (MIMETypeRegistry::IsSupportedImageResourceMIMEType(type) ||
- type == "multipart/x-mixed-replace") {
- type_ = Type::kImage;
- return *this;
- }
- if (HTMLMediaElement::GetSupportsType(ContentType(type))) {
- type_ = Type::kMedia;
- return *this;
+ if (MIMETypeRegistry::IsSupportedImageResourceMIMEType(mime_type) ||
+ mime_type == "multipart/x-mixed-replace") {
+ return Type::kImage;
}
- PluginData* plugin_data = nullptr;
- if (GetFrame() && GetFrame()->GetPage() &&
- GetFrame()->Loader().AllowPlugins(kNotAboutToInstantiatePlugin)) {
- // If the document is being created for the main frame,
- // frame()->tree().top()->securityContext() returns nullptr.
- // For that reason, the origin must be retrieved directly from url().
- if (GetFrame()->IsMainFrame()) {
- scoped_refptr<const SecurityOrigin> origin =
- SecurityOrigin::Create(Url());
- plugin_data = GetFrame()->GetPage()->GetPluginData(origin.get());
- } else {
- auto* top_security_origin =
- GetFrame()->Tree().Top().GetSecurityContext()->GetSecurityOrigin();
- plugin_data = GetFrame()->GetPage()->GetPluginData(top_security_origin);
+ if (HTMLMediaElement::GetSupportsType(ContentType(mime_type)))
+ return Type::kMedia;
+
+ if (frame && frame->GetPage() &&
+ frame->Loader().AllowPlugins(kNotAboutToInstantiatePlugin)) {
+ PluginData* plugin_data = GetPluginData(frame, url);
+
+ // Everything else except text/plain can be overridden by plugins.
+ // Disallowing plugins to use text/plain prevents plugins from hijacking a
+ // fundamental type that the browser is expected to handle, and also serves
+ // as an optimization to prevent loading the plugin database in the common
+ // case.
+ if (mime_type != "text/plain" && plugin_data &&
+ plugin_data->SupportsMimeType(mime_type)) {
+ // Plugins handled by MimeHandlerView do not create a PluginDocument. They
+ // are rendered inside cross-process frames and the notion of a PluginView
+ // (which is associated with PluginDocument) is irrelevant here.
+ if (plugin_data->IsExternalPluginMimeType(mime_type)) {
+ if (is_for_external_handler)
+ *is_for_external_handler = true;
+ return Type::kHTML;
+ }
+
+ return Type::kPlugin;
}
}
- // Everything else except text/plain can be overridden by plugins.
- // Disallowing plugins to use text/plain prevents plugins from hijacking a
- // fundamental type that the browser is expected to handle, and also serves as
- // an optimization to prevent loading the plugin database in the common case.
- if (type != "text/plain" && plugin_data &&
- plugin_data->SupportsMimeType(type)) {
- // Plugins handled by MimeHandlerView do not create a PluginDocument. They
- // are rendered inside cross-process frames and the notion of a PluginView
- // (which is associated with PluginDocument) is irrelevant here.
- if (plugin_data->IsExternalPluginMimeType(type)) {
- type_ = Type::kHTML;
- is_for_external_handler_ = true;
- } else {
- type_ = Type::kPlugin;
- plugin_background_color_ =
- plugin_data->PluginBackgroundColorForMimeType(type);
- }
- return *this;
- }
+ if (DOMImplementation::IsTextMIMEType(mime_type))
+ return Type::kText;
- if (DOMImplementation::IsTextMIMEType(type))
- type_ = Type::kText;
- else if (type == "image/svg+xml")
- type_ = Type::kSVG;
- else if (DOMImplementation::IsXMLMIMEType(type))
- type_ = Type::kXML;
- else
- type_ = Type::kHTML;
+ if (mime_type == "image/svg+xml")
+ return Type::kSVG;
+
+ if (DOMImplementation::IsXMLMIMEType(mime_type))
+ return Type::kXML;
+
+ return Type::kHTML;
+}
+
+// static
+PluginData* DocumentInit::GetPluginData(LocalFrame* frame, const KURL& url) {
+ // If the document is being created for the main frame,
+ // frame()->tree().top()->securityContext() returns nullptr.
+ // For that reason, the origin must be retrieved directly from |url|.
+ if (frame->IsMainFrame())
+ return frame->GetPage()->GetPluginData(SecurityOrigin::Create(url).get());
+
+ const SecurityOrigin* main_frame_origin =
+ frame->Tree().Top().GetSecurityContext()->GetSecurityOrigin();
+ return frame->GetPage()->GetPluginData(main_frame_origin);
+}
+
+DocumentInit& DocumentInit::WithTypeFrom(const String& mime_type) {
+ mime_type_ = mime_type;
+ type_ = ComputeDocumentType(GetFrame(), Url(), mime_type_,
+ &is_for_external_handler_);
+ if (type_ == Type::kPlugin) {
+ plugin_background_color_ =
+ GetPluginData(GetFrame(), Url())
+ ->PluginBackgroundColorForMimeType(mime_type_);
+ }
return *this;
}
@@ -365,7 +370,7 @@ DocumentInit& DocumentInit::WithOriginTrialsHeader(const String& header) {
}
DocumentInit& DocumentInit::WithSandboxFlags(
- mojom::blink::WebSandboxFlags flags) {
+ network::mojom::blink::WebSandboxFlags flags) {
// Only allow adding more sandbox flags.
sandbox_flags_ |= flags;
return *this;
@@ -437,17 +442,14 @@ WindowAgentFactory* DocumentInit::GetWindowAgentFactory() const {
// If we are a page popup in LayoutTests ensure we use the popup
// owner's frame for looking up the Agent so the tests can possibly
// access the document via internals API.
- if (IsPagePopupRunningInWebTest(GetFrame())) {
- auto* frame = GetFrame()->PagePopupOwner()->GetDocument().GetFrame();
- return &frame->window_agent_factory();
- }
- if (GetFrame())
- return &GetFrame()->window_agent_factory();
- if (Document* context_document = ContextDocument())
+ LocalFrame* frame = nullptr;
+ if (IsPagePopupRunningInWebTest(GetFrame()))
+ frame = GetFrame()->PagePopupOwner()->GetDocument().GetFrame();
+ else if (GetFrame())
+ frame = GetFrame();
+ else if (Document* context_document = ContextDocument())
return context_document->GetWindowAgentFactory();
- if (const Document* owner_document = OwnerDocument())
- return owner_document->GetWindowAgentFactory();
- return nullptr;
+ return frame ? &frame->window_agent_factory() : nullptr;
}
Settings* DocumentInit::GetSettingsForWindowAgentFactory() const {
@@ -458,8 +460,6 @@ Settings* DocumentInit::GetSettingsForWindowAgentFactory() const {
frame = GetFrame();
else if (Document* context_document = ContextDocument())
frame = context_document->GetFrame();
- else if (const Document* owner_document = OwnerDocument())
- frame = owner_document->GetFrame();
return frame ? frame->GetSettings() : nullptr;
}
diff --git a/chromium/third_party/blink/renderer/core/dom/document_init.h b/chromium/third_party/blink/renderer/core/dom/document_init.h
index 7a7da46660d..45eb8b5f1ab 100644
--- a/chromium/third_party/blink/renderer/core/dom/document_init.h
+++ b/chromium/third_party/blink/renderer/core/dom/document_init.h
@@ -31,12 +31,12 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_DOCUMENT_INIT_H_
#include "services/network/public/mojom/ip_address_space.mojom-shared.h"
+#include "services/network/public/mojom/web_sandbox_flags.mojom-blink.h"
#include "third_party/blink/public/common/frame/frame_policy.h"
#include "third_party/blink/public/mojom/feature_policy/feature_policy.mojom-blink.h"
#include "third_party/blink/public/mojom/security_context/insecure_request_policy.mojom-blink-forward.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/execution_context/security_context.h"
-#include "third_party/blink/renderer/core/frame/sandbox_flags.h"
#include "third_party/blink/renderer/core/html/custom/v0_custom_element_registration_context.h"
#include "third_party/blink/renderer/platform/graphics/color.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
@@ -47,8 +47,9 @@ namespace blink {
class ContentSecurityPolicy;
class Document;
class DocumentLoader;
-class LocalFrame;
class HTMLImportsController;
+class LocalFrame;
+class PluginData;
class Settings;
class UseCounter;
class WindowAgentFactory;
@@ -69,7 +70,6 @@ class CORE_EXPORT DocumentInit final {
// .WithURL(url);
// Document* document = MakeGarbageCollected<Document>(init);
static DocumentInit Create();
- static DocumentInit CreateWithImportsController(HTMLImportsController*);
DocumentInit(const DocumentInit&);
~DocumentInit();
@@ -87,6 +87,7 @@ class CORE_EXPORT DocumentInit final {
kUnspecified
};
+ DocumentInit& WithImportsController(HTMLImportsController*);
HTMLImportsController* ImportsController() const {
return imports_controller_;
}
@@ -94,7 +95,7 @@ class CORE_EXPORT DocumentInit final {
bool HasSecurityContext() const { return MasterDocumentLoader(); }
bool IsSrcdocDocument() const;
bool ShouldSetURL() const;
- mojom::blink::WebSandboxFlags GetSandboxFlags() const;
+ network::mojom::blink::WebSandboxFlags GetSandboxFlags() const;
mojom::blink::InsecureRequestPolicy GetInsecureRequestPolicy() const;
const SecurityContext::InsecureNavigationsSet* InsecureNavigationsToUpgrade()
const;
@@ -106,7 +107,17 @@ class CORE_EXPORT DocumentInit final {
LocalFrame* GetFrame() const;
UseCounter* GetUseCounter() const;
- DocumentInit& WithTypeFrom(const String& type);
+ // Compute the type of document to be loaded inside a |frame|, given its |url|
+ // and its |mime_type|.
+ //
+ // In case of plugin handled by MimeHandlerview (which do not create a
+ // PluginDocument), the type is Type::KHTML and |is_for_external_handler| is
+ // set to true.
+ static Type ComputeDocumentType(LocalFrame* frame,
+ const KURL& url,
+ const String& mime_type,
+ bool* is_for_external_handler = nullptr);
+ DocumentInit& WithTypeFrom(const String& mime_type);
Type GetType() const { return type_; }
const String& GetMimeType() const { return mime_type_; }
bool IsForExternalHandler() const { return is_for_external_handler_; }
@@ -162,7 +173,7 @@ class CORE_EXPORT DocumentInit final {
DocumentInit& WithOriginTrialsHeader(const String& header);
const String& OriginTrialsHeader() const { return origin_trials_header_; }
- DocumentInit& WithSandboxFlags(mojom::blink::WebSandboxFlags flags);
+ DocumentInit& WithSandboxFlags(network::mojom::blink::WebSandboxFlags flags);
DocumentInit& WithContentSecurityPolicy(ContentSecurityPolicy* policy);
DocumentInit& WithContentSecurityPolicyFromContextDoc();
@@ -192,7 +203,7 @@ class CORE_EXPORT DocumentInit final {
Settings* GetSettingsForWindowAgentFactory() const;
private:
- DocumentInit(HTMLImportsController*);
+ DocumentInit() = default;
// For a Document associated directly with a frame, this will be the
// DocumentLoader driving the commit. For an import, XSLT-generated
@@ -200,6 +211,8 @@ class CORE_EXPORT DocumentInit final {
// of its owning Document.
DocumentLoader* MasterDocumentLoader() const;
+ static PluginData* GetPluginData(LocalFrame* frame, const KURL& url);
+
Type type_ = Type::kUnspecified;
String mime_type_;
@@ -244,7 +257,7 @@ class CORE_EXPORT DocumentInit final {
bool grant_load_local_resources_ = false;
V0CustomElementRegistrationContext* registration_context_ = nullptr;
- bool create_new_registration_context_;
+ bool create_new_registration_context_ = false;
// The feature policy set via response header.
String feature_policy_header_;
@@ -254,12 +267,12 @@ class CORE_EXPORT DocumentInit final {
String origin_trials_header_;
// Additional sandbox flags
- mojom::blink::WebSandboxFlags sandbox_flags_ =
- mojom::blink::WebSandboxFlags::kNone;
+ network::mojom::blink::WebSandboxFlags sandbox_flags_ =
+ network::mojom::blink::WebSandboxFlags::kNone;
// Loader's CSP
ContentSecurityPolicy* content_security_policy_ = nullptr;
- bool content_security_policy_from_context_doc_;
+ bool content_security_policy_from_context_doc_ = false;
network::mojom::IPAddressSpace ip_address_space_ =
network::mojom::IPAddressSpace::kUnknown;
diff --git a/chromium/third_party/blink/renderer/core/dom/document_lifecycle.h b/chromium/third_party/blink/renderer/core/dom/document_lifecycle.h
index 62ce22ed6e2..a590ce09993 100644
--- a/chromium/third_party/blink/renderer/core/dom/document_lifecycle.h
+++ b/chromium/third_party/blink/renderer/core/dom/document_lifecycle.h
@@ -222,7 +222,6 @@ class CORE_EXPORT DocumentLifecycle {
bool StateAllowsTreeMutations() const;
bool StateAllowsLayoutTreeMutations() const;
bool StateAllowsDetach() const;
- bool StateAllowsLayoutInvalidation() const;
bool StateAllowsLayoutTreeNotifications() const;
void AdvanceTo(LifecycleState);
@@ -293,11 +292,6 @@ inline bool DocumentLifecycle::StateAllowsDetach() const {
state_ == kStopping || state_ == kInactive;
}
-inline bool DocumentLifecycle::StateAllowsLayoutInvalidation() const {
- return state_ != kInPerformLayout && state_ != kInCompositingUpdate &&
- state_ != kInPrePaint && state_ != kInPaint;
-}
-
} // namespace blink
#endif
diff --git a/chromium/third_party/blink/renderer/core/dom/document_test.cc b/chromium/third_party/blink/renderer/core/dom/document_test.cc
index 5d3721c6624..e908501969a 100644
--- a/chromium/third_party/blink/renderer/core/dom/document_test.cc
+++ b/chromium/third_party/blink/renderer/core/dom/document_test.cc
@@ -38,11 +38,16 @@
#include "services/network/public/mojom/referrer_policy.mojom-blink.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
#include "third_party/blink/public/common/feature_policy/document_policy_features.h"
#include "third_party/blink/public/mojom/feature_policy/feature_policy_feature.mojom-blink.h"
+#include "third_party/blink/public/web/web_print_page_description.h"
#include "third_party/blink/renderer/bindings/core/v8/isolated_world_csp.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_promise_tester.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_dom_exception.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_throw_dom_exception.h"
#include "third_party/blink/renderer/core/css/media_query_list_listener.h"
#include "third_party/blink/renderer/core/css/media_query_matcher.h"
#include "third_party/blink/renderer/core/dom/document_fragment.h"
@@ -82,6 +87,12 @@ using network::mojom::ContentSecurityPolicySource;
using network::mojom::ContentSecurityPolicyType;
class DocumentTest : public PageTestBase {
+ public:
+ static void SimulateHasTrustTokensAnswererConnectionError(
+ Document* document) {
+ document->HasTrustTokensAnswererConnectionError();
+ }
+
protected:
void TearDown() override {
ThreadState::Current()->CollectAllGarbageForTesting();
@@ -329,6 +340,19 @@ class PrefersColorSchemeTestListener final : public MediaQueryListListener {
bool notified_ = false;
};
+bool IsDOMException(ScriptState* script_state,
+ ScriptValue value,
+ DOMExceptionCode code) {
+ auto* dom_exception = V8DOMException::ToImplWithTypeCheck(
+ script_state->GetIsolate(), value.V8Value());
+ if (!dom_exception)
+ return false;
+
+ // Unfortunately, it's not enough to check |dom_exception->code() == code|,
+ // as DOMException::code is only populated for the DOMExceptionCodes with
+ // "legacy code" numeric values.
+ return dom_exception->name() == DOMException(code).name();
+}
} // anonymous namespace
TEST_F(DocumentTest, CreateRangeAdjustedToTreeScopeWithPositionInShadowTree) {
@@ -1180,9 +1204,9 @@ TEST_F(DocumentTest, FindInPageUkm) {
EXPECT_FALSE(ukm::TestUkmRecorder::EntryHasMetric(
entries[0], "DidHaveRenderSubtreeMatch"));
- GetDocument().MarkHasFindInPageSubtreeVisibilityActiveMatch();
+ GetDocument().MarkHasFindInPageContentVisibilityActiveMatch();
EXPECT_EQ(recorder->entries_count(), 2u);
- GetDocument().MarkHasFindInPageSubtreeVisibilityActiveMatch();
+ GetDocument().MarkHasFindInPageContentVisibilityActiveMatch();
EXPECT_EQ(recorder->entries_count(), 2u);
entries = recorder->GetEntriesByName("Blink.FindInPage");
EXPECT_EQ(entries.size(), 2u);
@@ -1209,14 +1233,185 @@ TEST_F(DocumentTest, AtPageMarginWithDeviceScaleFactor) {
GetDocument().GetFrame()->StartPrinting(initial_page_size, initial_page_size);
GetDocument().View()->UpdateLifecyclePhasesForPrinting();
- DoubleSize page_size;
- int margin[4];
- GetDocument().PageSizeAndMarginsInPixels(0, page_size, margin[0], margin[1],
- margin[2], margin[3]);
+ WebPrintPageDescription description;
+ GetDocument().GetPageDescription(0, &description);
+
+ EXPECT_EQ(50, description.margin_top);
+ EXPECT_EQ(50, description.margin_right);
+ EXPECT_EQ(50, description.margin_bottom);
+ EXPECT_EQ(50, description.margin_left);
+ EXPECT_EQ(WebDoubleSize(400, 960), description.size);
+}
+
+TEST(Document, HandlesDisconnectDuringHasTrustToken) {
+ // Check that a Mojo handle disconnecting during hasTrustToken operation
+ // execution results in the promise getting rejected with the proper
+ // exception.
+ V8TestingScope scope(KURL("https://trusttoken.example"));
+
+ Document& document = scope.GetDocument();
+
+ auto promise =
+ document.hasTrustToken(scope.GetScriptState(), "https://issuer.example",
+ scope.GetExceptionState());
+ DocumentTest::SimulateHasTrustTokensAnswererConnectionError(&document);
+
+ ASSERT_TRUE(promise.IsAssociatedWith(scope.GetScriptState()));
+
+ ScriptPromiseTester promise_tester(scope.GetScriptState(), promise);
+ promise_tester.WaitUntilSettled();
+ EXPECT_TRUE(promise_tester.IsRejected());
+ EXPECT_TRUE(IsDOMException(scope.GetScriptState(), promise_tester.Value(),
+ DOMExceptionCode::kOperationError));
+}
+
+TEST(Document, RejectsHasTrustTokenCallFromNonHttpNonHttpsDocument) {
+ // Check that hasTrustToken getting called from a secure, but
+ // non-http/non-https, document results in an exception being thrown.
+ V8TestingScope scope(KURL("file:///trusttoken.txt"));
+
+ Document& document = scope.GetDocument();
+ ScriptState* script_state = scope.GetScriptState();
+ ExceptionState exception_state(script_state->GetIsolate(),
+ ExceptionState::kExecutionContext, "Document",
+ "hasTrustToken");
+
+ auto promise = document.hasTrustToken(script_state, "https://issuer.example",
+ exception_state);
+
+ ScriptPromiseTester promise_tester(script_state, promise);
+ promise_tester.WaitUntilSettled();
+ EXPECT_TRUE(promise_tester.IsRejected());
+ EXPECT_TRUE(IsDOMException(script_state, promise_tester.Value(),
+ DOMExceptionCode::kNotAllowedError));
+}
+
+namespace {
+class MockHasTrustTokensAnswerer
+ : public network::mojom::blink::HasTrustTokensAnswerer {
+ public:
+ enum Outcome { kError, kTrue, kFalse };
+ explicit MockHasTrustTokensAnswerer(Outcome outcome) : outcome_(outcome) {}
+
+ void HasTrustTokens(
+ const ::scoped_refptr<const ::blink::SecurityOrigin>& issuer,
+ HasTrustTokensCallback callback) override {
+ auto result = network::mojom::blink::HasTrustTokensResult::New();
+ result->status = network::mojom::blink::TrustTokenOperationStatus::kOk;
+ switch (outcome_) {
+ case kTrue: {
+ result->has_trust_tokens = true;
+ std::move(callback).Run(std::move(result));
+ return;
+ }
+ case kFalse: {
+ result->has_trust_tokens = false;
+ std::move(callback).Run(std::move(result));
+ return;
+ }
+ case kError: {
+ result->status =
+ network::mojom::blink::TrustTokenOperationStatus::kUnknownError;
+ std::move(callback).Run(std::move(result));
+ }
+ }
+ }
+
+ void Bind(mojo::ScopedMessagePipeHandle handle) {
+ receiver_.Bind(
+ mojo::PendingReceiver<network::mojom::blink::HasTrustTokensAnswerer>(
+ std::move(handle)));
+ }
+
+ private:
+ Outcome outcome_;
+ mojo::Receiver<network::mojom::blink::HasTrustTokensAnswerer> receiver_{this};
+};
+} // namespace
+
+TEST(Document, HasTrustTokenSuccess) {
+ V8TestingScope scope(KURL("https://secure.example"));
+
+ MockHasTrustTokensAnswerer answerer(MockHasTrustTokensAnswerer::kTrue);
+
+ Document& document = scope.GetDocument();
+ document.GetFrame()->GetBrowserInterfaceBroker().SetBinderForTesting(
+ network::mojom::blink::HasTrustTokensAnswerer::Name_,
+ WTF::BindRepeating(&MockHasTrustTokensAnswerer::Bind,
+ WTF::Unretained(&answerer)));
+
+ ScriptState* script_state = scope.GetScriptState();
+ ExceptionState exception_state(script_state->GetIsolate(),
+ ExceptionState::kExecutionContext, "Document",
+ "hasTrustToken");
- for (int side_margin : margin)
- EXPECT_EQ(50, side_margin);
- EXPECT_EQ(DoubleSize(400, 960), page_size);
+ auto promise = document.hasTrustToken(script_state, "https://issuer.example",
+ exception_state);
+
+ ScriptPromiseTester promise_tester(script_state, promise);
+ promise_tester.WaitUntilSettled();
+ EXPECT_TRUE(promise_tester.IsFulfilled());
+ EXPECT_TRUE(promise_tester.Value().V8Value()->IsTrue());
+
+ document.GetFrame()->GetBrowserInterfaceBroker().SetBinderForTesting(
+ network::mojom::blink::HasTrustTokensAnswerer::Name_, {});
+}
+
+TEST(Document, HasTrustTokenSuccessWithFalseValue) {
+ V8TestingScope scope(KURL("https://secure.example"));
+
+ MockHasTrustTokensAnswerer answerer(MockHasTrustTokensAnswerer::kFalse);
+
+ Document& document = scope.GetDocument();
+ document.GetFrame()->GetBrowserInterfaceBroker().SetBinderForTesting(
+ network::mojom::blink::HasTrustTokensAnswerer::Name_,
+ WTF::BindRepeating(&MockHasTrustTokensAnswerer::Bind,
+ WTF::Unretained(&answerer)));
+
+ ScriptState* script_state = scope.GetScriptState();
+ ExceptionState exception_state(script_state->GetIsolate(),
+ ExceptionState::kExecutionContext, "Document",
+ "hasTrustToken");
+
+ auto promise = document.hasTrustToken(script_state, "https://issuer.example",
+ exception_state);
+
+ ScriptPromiseTester promise_tester(script_state, promise);
+ promise_tester.WaitUntilSettled();
+ EXPECT_TRUE(promise_tester.IsFulfilled());
+ EXPECT_TRUE(promise_tester.Value().V8Value()->IsFalse());
+
+ document.GetFrame()->GetBrowserInterfaceBroker().SetBinderForTesting(
+ network::mojom::blink::HasTrustTokensAnswerer::Name_, {});
+}
+
+TEST(Document, HasTrustTokenOperationError) {
+ V8TestingScope scope(KURL("https://secure.example"));
+
+ MockHasTrustTokensAnswerer answerer(MockHasTrustTokensAnswerer::kError);
+
+ Document& document = scope.GetDocument();
+ document.GetFrame()->GetBrowserInterfaceBroker().SetBinderForTesting(
+ network::mojom::blink::HasTrustTokensAnswerer::Name_,
+ WTF::BindRepeating(&MockHasTrustTokensAnswerer::Bind,
+ WTF::Unretained(&answerer)));
+
+ ScriptState* script_state = scope.GetScriptState();
+ ExceptionState exception_state(script_state->GetIsolate(),
+ ExceptionState::kExecutionContext, "Document",
+ "hasTrustToken");
+
+ auto promise = document.hasTrustToken(script_state, "https://issuer.example",
+ exception_state);
+
+ ScriptPromiseTester promise_tester(script_state, promise);
+ promise_tester.WaitUntilSettled();
+ EXPECT_TRUE(promise_tester.IsRejected());
+ EXPECT_TRUE(IsDOMException(script_state, promise_tester.Value(),
+ DOMExceptionCode::kOperationError));
+
+ document.GetFrame()->GetBrowserInterfaceBroker().SetBinderForTesting(
+ network::mojom::blink::HasTrustTokensAnswerer::Name_, {});
}
/**
@@ -1237,22 +1432,6 @@ class ViewportFitDocumentTest : public DocumentTest,
}
};
-// Test both meta and @viewport present but no viewport-fit.
-TEST_F(ViewportFitDocumentTest, MetaCSSViewportButNoFit) {
- SetHtmlInnerHTML(
- "<style>@viewport { min-width: 100px; }</style>"
- "<meta name='viewport' content='initial-scale=1'>");
-
- EXPECT_EQ(mojom::ViewportFit::kAuto, GetViewportFit());
-}
-
-// Test @viewport present but no viewport-fit.
-TEST_F(ViewportFitDocumentTest, CSSViewportButNoFit) {
- SetHtmlInnerHTML("<style>@viewport { min-width: 100px; }</style>");
-
- EXPECT_EQ(mojom::ViewportFit::kAuto, GetViewportFit());
-}
-
// Test meta viewport present but no viewport-fit.
TEST_F(ViewportFitDocumentTest, MetaViewportButNoFit) {
SetHtmlInnerHTML("<meta name='viewport' content='initial-scale=1'>");
@@ -1280,8 +1459,7 @@ TEST_F(ViewportFitDocumentTest, ForceExpandIntoCutout) {
// This is a test case for testing a combination of viewport-fit meta value,
// viewport CSS value and the expected outcome.
-using ViewportTestCase =
- std::tuple<const char*, const char*, mojom::ViewportFit>;
+using ViewportTestCase = std::tuple<const char*, mojom::ViewportFit>;
class ParameterizedViewportFitDocumentTest
: public ViewportFitDocumentTest,
@@ -1289,15 +1467,8 @@ class ParameterizedViewportFitDocumentTest
protected:
void LoadTestHTML() {
const char* kMetaValue = std::get<0>(GetParam());
- const char* kCSSValue = std::get<1>(GetParam());
StringBuilder html;
- if (kCSSValue) {
- html.Append("<style>@viewport { viewport-fit: ");
- html.Append(kCSSValue);
- html.Append("; }</style>");
- }
-
if (kMetaValue) {
html.Append("<meta name='viewport' content='viewport-fit=");
html.Append(kMetaValue);
@@ -1311,7 +1482,7 @@ class ParameterizedViewportFitDocumentTest
TEST_P(ParameterizedViewportFitDocumentTest, EffectiveViewportFit) {
LoadTestHTML();
- EXPECT_EQ(std::get<2>(GetParam()), GetViewportFit());
+ EXPECT_EQ(std::get<1>(GetParam()), GetViewportFit());
}
INSTANTIATE_TEST_SUITE_P(
@@ -1319,19 +1490,11 @@ INSTANTIATE_TEST_SUITE_P(
ParameterizedViewportFitDocumentTest,
testing::Values(
// Test the default case.
- ViewportTestCase(nullptr, nullptr, mojom::ViewportFit::kAuto),
- // Test the different values set through CSS.
- ViewportTestCase(nullptr, "auto", mojom::ViewportFit::kAuto),
- ViewportTestCase(nullptr, "contain", mojom::ViewportFit::kContain),
- ViewportTestCase(nullptr, "cover", mojom::ViewportFit::kCover),
- ViewportTestCase(nullptr, "invalid", mojom::ViewportFit::kAuto),
+ ViewportTestCase(nullptr, mojom::ViewportFit::kAuto),
// Test the different values set through the meta tag.
- ViewportTestCase("auto", nullptr, mojom::ViewportFit::kAuto),
- ViewportTestCase("contain", nullptr, mojom::ViewportFit::kContain),
- ViewportTestCase("cover", nullptr, mojom::ViewportFit::kCover),
- ViewportTestCase("invalid", nullptr, mojom::ViewportFit::kAuto),
- // Test that the CSS should override the meta tag.
- ViewportTestCase("cover", "auto", mojom::ViewportFit::kAuto),
- ViewportTestCase("cover", "contain", mojom::ViewportFit::kContain)));
+ ViewportTestCase("auto", mojom::ViewportFit::kAuto),
+ ViewportTestCase("contain", mojom::ViewportFit::kContain),
+ ViewportTestCase("cover", mojom::ViewportFit::kCover),
+ ViewportTestCase("invalid", mojom::ViewportFit::kAuto)));
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/dom/dom_implementation.cc b/chromium/third_party/blink/renderer/core/dom/dom_implementation.cc
index 7c1a0d0f2cf..141dc77b6bf 100644
--- a/chromium/third_party/blink/renderer/core/dom/dom_implementation.cc
+++ b/chromium/third_party/blink/renderer/core/dom/dom_implementation.cc
@@ -219,7 +219,8 @@ Document* DOMImplementation::createDocument(const DocumentInit& init) {
// replace it with a SinkDocument when plugins are sanboxed. If we move
// final sandbox flag calcuation earlier, we could construct the
// SinkDocument directly.
- if (document->IsSandboxed(mojom::blink::WebSandboxFlags::kPlugins))
+ if (document->IsSandboxed(
+ network::mojom::blink::WebSandboxFlags::kPlugins))
document = MakeGarbageCollected<SinkDocument>(init);
return document;
}
diff --git a/chromium/third_party/blink/renderer/core/dom/element.cc b/chromium/third_party/blink/renderer/core/dom/element.cc
index 9801e9a3cf8..bb0519270fa 100644
--- a/chromium/third_party/blink/renderer/core/dom/element.cc
+++ b/chromium/third_party/blink/renderer/core/dom/element.cc
@@ -38,6 +38,7 @@
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
#include "third_party/blink/renderer/bindings/core/v8/scroll_into_view_options_or_boolean.h"
#include "third_party/blink/renderer/bindings/core/v8/string_or_trusted_html_or_trusted_script_or_trusted_script_url.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_get_inner_html_options.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_pointer_lock_options.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_scroll_into_view_options.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_scroll_to_options.h"
@@ -63,6 +64,7 @@
#include "third_party/blink/renderer/core/css/style_engine.h"
#include "third_party/blink/renderer/core/css_value_keywords.h"
#include "third_party/blink/renderer/core/display_lock/display_lock_context.h"
+#include "third_party/blink/renderer/core/display_lock/display_lock_document_state.h"
#include "third_party/blink/renderer/core/display_lock/display_lock_utilities.h"
#include "third_party/blink/renderer/core/display_lock/render_subtree_activation_event.h"
#include "third_party/blink/renderer/core/dom/attr.h"
@@ -131,7 +133,6 @@
#include "third_party/blink/renderer/core/inspector/console_message.h"
#include "third_party/blink/renderer/core/intersection_observer/element_intersection_observer_data.h"
#include "third_party/blink/renderer/core/intersection_observer/intersection_observer_controller.h"
-#include "third_party/blink/renderer/core/invisible_dom/activate_invisible_event.h"
#include "third_party/blink/renderer/core/layout/adjust_for_absolute_zoom.h"
#include "third_party/blink/renderer/core/layout/layout_text_fragment.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
@@ -173,6 +174,8 @@ enum class ClassStringContent { kEmpty, kWhiteSpaceOnly, kHasClasses };
namespace {
class DisplayLockStyleScope {
+ STACK_ALLOCATED();
+
public:
explicit DisplayLockStyleScope(Element* element) : element_(element) {
// Note that we don't store context as a member of this scope, since it may
@@ -198,10 +201,15 @@ class DisplayLockStyleScope {
context->ShouldStyle(DisplayLockLifecycleTarget::kChildren);
}
void DidUpdateChildStyle() { did_update_children_ = true; }
- void DidUpdateSelfStyle() {
+ // Returns true if the element was force unlocked due to missing requirements.
+ bool DidUpdateSelfStyle() {
DCHECK(should_update_self_);
- if (auto* context = element_->GetDisplayLockContext())
+ if (auto* context = element_->GetDisplayLockContext()) {
+ bool was_locked = context->IsLocked();
context->DidStyle(DisplayLockLifecycleTarget::kSelf);
+ return was_locked && !context->IsLocked();
+ }
+ return false;
}
void NotifyUpdateWasBlocked(DisplayLockContext::StyleType style) {
@@ -212,8 +220,16 @@ class DisplayLockStyleScope {
element_->GetDisplayLockContext()->NotifyStyleRecalcWasBlocked(style);
}
+ StyleRecalcChange AdjustStyleRecalcChangeForChildren(
+ StyleRecalcChange change) {
+ DCHECK(element_->GetDisplayLockContext());
+ DCHECK(!element_->GetDisplayLockContext()->IsLocked());
+ return element_->GetDisplayLockContext()
+ ->AdjustStyleRecalcChangeForChildren(change);
+ }
+
private:
- UntracedMember<Element> element_;
+ Element* element_;
bool should_update_self_ = false;
bool did_update_children_ = false;
};
@@ -316,7 +332,7 @@ bool DefinitelyNewFormattingContext(const Node& node,
bool CalculateStyleShouldForceLegacyLayout(const Element& element,
const ComputedStyle& style) {
- const Document& document = element.GetDocument();
+ Document& document = element.GetDocument();
if (style.Display() == EDisplay::kLayoutCustom ||
style.Display() == EDisplay::kInlineLayoutCustom)
@@ -325,26 +341,35 @@ bool CalculateStyleShouldForceLegacyLayout(const Element& element,
// TODO(layout-dev): Once LayoutNG handles inline content editable, we
// should get rid of following code fragment.
if (!RuntimeEnabledFeatures::EditingNGEnabled()) {
- if (style.UserModify() != EUserModify::kReadOnly || document.InDesignMode())
+ if (style.UserModify() != EUserModify::kReadOnly ||
+ document.InDesignMode()) {
+ UseCounter::Count(document, WebFeature::kLegacyLayoutByEditing);
return true;
+ }
}
if (style.IsDeprecatedWebkitBox() &&
(!style.IsDeprecatedWebkitBoxWithVerticalLineClamp() ||
!RuntimeEnabledFeatures::BlockFlowHandlesWebkitLineClampEnabled())) {
+ UseCounter::Count(
+ document, WebFeature::kLegacyLayoutByWebkitBoxWithoutVerticalLineClamp);
return true;
}
if (!RuntimeEnabledFeatures::LayoutNGBlockFragmentationEnabled()) {
// Disable NG for the entire subtree if we're establishing a multicol
// container.
- if (style.SpecifiesColumns())
+ if (style.SpecifiesColumns()) {
+ UseCounter::Count(document, WebFeature::kLegacyLayoutByMultiCol);
return true;
+ }
}
// No printing support in LayoutNG yet.
- if (document.Printing() && element == document.documentElement())
+ if (document.Printing() && element == document.documentElement()) {
+ UseCounter::Count(document, WebFeature::kLegacyLayoutByPrinting);
return true;
+ }
// Fall back to legacy layout for frameset documents. The frameset itself (and
// the frames) can only create legacy layout objects anyway (no NG counterpart
@@ -353,12 +378,16 @@ bool CalculateStyleShouldForceLegacyLayout(const Element& element,
// layout (because of the above check), which would re-attach all layout
// objects, which would cause the frameset to lose state of some sort, leaving
// everything blank when printed.
- if (document.IsFrameSet())
+ if (document.IsFrameSet()) {
+ UseCounter::Count(document, WebFeature::kLegacyLayoutByFrameSet);
return true;
+ }
// 'text-combine-upright' property is not supported yet.
- if (style.HasTextCombine() && !style.IsHorizontalWritingMode())
+ if (style.HasTextCombine() && !style.IsHorizontalWritingMode()) {
+ UseCounter::Count(document, WebFeature::kLegacyLayoutByTextCombine);
return true;
+ }
if (style.InsideNGFragmentationContext()) {
// If we're inside an NG block fragmentation context, all fragmentable boxes
@@ -367,8 +396,13 @@ bool CalculateStyleShouldForceLegacyLayout(const Element& element,
// on). Inline display types end up on a line, and are therefore monolithic,
// so we can allow those.
if (!style.IsDisplayInlineType()) {
- if (style.IsDisplayTableType() || style.IsDisplayFlexibleOrGridBox())
+ if (style.IsDisplayTableType() || style.IsDisplayFlexibleOrGridBox()) {
+ UseCounter::Count(
+ document,
+ WebFeature::
+ kLegacyLayoutByTableFlexGridBlockInNGFragmentationContext);
return true;
+ }
}
}
@@ -479,7 +513,8 @@ void EnqueueAutofocus(Element& element) {
// 4. If target's active sandboxing flag set has the sandboxed automatic
// features browsing context flag, then return.
- if (doc.IsSandboxed(mojom::blink::WebSandboxFlags::kAutomaticFeatures)) {
+ if (doc.IsSandboxed(
+ network::mojom::blink::WebSandboxFlags::kAutomaticFeatures)) {
doc.AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>(
mojom::ConsoleMessageSource::kSecurity,
mojom::ConsoleMessageLevel::kError,
@@ -568,6 +603,15 @@ int Element::DefaultTabIndex() const {
}
bool Element::IsFocusableStyle() const {
+ // TODO(vmpstr): Note that this may be called by accessibility during layout
+ // tree attachment, at which point we might not have cleared all of the dirty
+ // bits to ensure that the layout tree doesn't need an update. This should be
+ // fixable by deferring AX tree updates as a separate phase after layout tree
+ // attachment has happened. At that point `InStyleRecalc()` portion of the
+ // following DCHECK can be removed.
+ DCHECK(
+ !GetDocument().IsActive() || GetDocument().InStyleRecalc() ||
+ !GetDocument().NeedsLayoutTreeUpdateForNodeIncludingDisplayLocked(*this));
// Elements in canvas fallback content are not rendered, but they are allowed
// to be focusable as long as their canvas is displayed and visible.
if (IsInCanvasSubtree()) {
@@ -579,20 +623,6 @@ bool Element::IsFocusableStyle() const {
EVisibility::kVisible;
}
- // Update style if we're in a display-locked subtree, because it isn't
- // included in the normal style updates. We also need to update the layout
- // here because some callers expect the layout stays clean.
- if (DisplayLockUtilities::NearestLockedExclusiveAncestor(*this)) {
- GetDocument().UpdateStyleAndLayoutForNode(
- this, DocumentUpdateReason::kDisplayLock);
- }
-
- if (IsInsideInvisibleSubtree()) {
- const ComputedStyle* style =
- const_cast<Element*>(this)->EnsureComputedStyle();
- return style->Visibility() == EVisibility::kVisible &&
- style->Display() != EDisplay::kNone;
- }
// FIXME: Even if we are not visible, we might have a child that is visible.
// Hyatt wants to fix that some day with a "has visible content" flag or the
// like.
@@ -601,8 +631,36 @@ bool Element::IsFocusableStyle() const {
}
Node* Element::Clone(Document& factory, CloneChildrenFlag flag) const {
- return flag == CloneChildrenFlag::kClone ? &CloneWithChildren(&factory)
- : &CloneWithoutChildren(&factory);
+ if (flag == CloneChildrenFlag::kSkip)
+ return &CloneWithoutChildren(&factory);
+ Element* copy = &CloneWithChildren(&factory);
+ // 7. If node is a shadow host and the clone shadows flag is set, run these
+ // steps:
+ if (flag == CloneChildrenFlag::kCloneWithShadows) {
+ DCHECK(RuntimeEnabledFeatures::DeclarativeShadowDOMEnabled());
+ auto* shadow_root = GetShadowRoot();
+ if (shadow_root && (shadow_root->GetType() == ShadowRootType::kOpen ||
+ shadow_root->GetType() == ShadowRootType::kClosed)) {
+ // 7.1 Run attach a shadow root with shadow host equal to copy, mode equal
+ // to node’s shadow root’s mode, and delegates focus equal to node’s
+ // shadow root’s delegates focus.
+ ShadowRoot& cloned_shadow_root = copy->AttachShadowRootInternal(
+ shadow_root->GetType(),
+ shadow_root->delegatesFocus() ? FocusDelegation::kDelegateFocus
+ : FocusDelegation::kNone,
+ shadow_root->GetSlotAssignmentMode());
+ // 7.2 If node’s shadow root’s "is declarative shadow root" is true, then
+ // set copy’s shadow root’s "is declarative shadow root" property to true.
+ cloned_shadow_root.SetIsDeclarativeShadowRoot(
+ shadow_root->IsDeclarativeShadowRoot());
+ // 7.3 If the clone children flag is set, clone all the children of node’s
+ // shadow root and append them to copy’s shadow root, with document as
+ // specified, the clone children flag being set, and the clone shadows
+ // flag being set.
+ cloned_shadow_root.CloneChildNodesFrom(*shadow_root, flag);
+ }
+ }
+ return copy;
}
Element& Element::CloneWithChildren(Document* nullable_factory) const {
@@ -614,7 +672,7 @@ Element& Element::CloneWithChildren(Document* nullable_factory) const {
clone.CloneAttributesFrom(*this);
clone.CloneNonAttributePropertiesFrom(*this, CloneChildrenFlag::kClone);
- clone.CloneChildNodesFrom(*this);
+ clone.CloneChildNodesFrom(*this, CloneChildrenFlag::kClone);
return clone;
}
@@ -820,16 +878,6 @@ void Element::SetElementArrayAttribute(
element_attribute_map->Set(name, elements);
}
-void Element::SetElementArrayAttribute(
- const QualifiedName& name,
- HeapVector<Member<Element>> given_elements,
- bool is_null) {
- if (is_null)
- SetElementArrayAttribute(name, base::nullopt);
- else
- SetElementArrayAttribute(name, std::move(given_elements));
-}
-
base::Optional<HeapVector<Member<Element>>> Element::GetElementArrayAttribute(
const QualifiedName& name) {
HeapVector<Member<Element>>* explicitly_set_elements =
@@ -866,14 +914,6 @@ base::Optional<HeapVector<Member<Element>>> Element::GetElementArrayAttribute(
return content_elements;
}
-HeapVector<Member<Element>> Element::GetElementArrayAttribute(
- const QualifiedName& name,
- bool& is_null) {
- const auto& result = GetElementArrayAttribute(name);
- is_null = !result.has_value();
- return result.value_or(HeapVector<Member<Element>>());
-}
-
NamedNodeMap* Element::attributesForBindings() const {
ElementRareData& rare_data =
const_cast<Element*>(this)->EnsureElementRareData();
@@ -950,8 +990,8 @@ void Element::SynchronizeAllAttributes() const {
DCHECK(IsStyledElement());
SynchronizeStyleAttributeInternal();
}
- if (GetElementData()->animated_svg_attributes_are_dirty())
- To<SVGElement>(this)->SynchronizeAnimatedSVGAttribute(AnyQName());
+ if (GetElementData()->svg_attributes_are_dirty())
+ To<SVGElement>(this)->SynchronizeSVGAttribute(AnyQName());
}
inline void Element::SynchronizeAttribute(const QualifiedName& name) const {
@@ -963,15 +1003,15 @@ inline void Element::SynchronizeAttribute(const QualifiedName& name) const {
SynchronizeStyleAttributeInternal();
return;
}
- if (UNLIKELY(GetElementData()->animated_svg_attributes_are_dirty())) {
+ if (UNLIKELY(GetElementData()->svg_attributes_are_dirty())) {
// See comment in the AtomicString version of SynchronizeAttribute()
// also.
- To<SVGElement>(this)->SynchronizeAnimatedSVGAttribute(name);
+ To<SVGElement>(this)->SynchronizeSVGAttribute(name);
}
}
void Element::SynchronizeAttribute(const AtomicString& local_name) const {
- // This version of synchronizeAttribute() is streamlined for the case where
+ // This version of SynchronizeAttribute() is streamlined for the case where
// you don't have a full QualifiedName, e.g when called from DOM API.
if (!GetElementData())
return;
@@ -981,20 +1021,17 @@ void Element::SynchronizeAttribute(const AtomicString& local_name) const {
SynchronizeStyleAttributeInternal();
return;
}
- if (GetElementData()->animated_svg_attributes_are_dirty()) {
- // We're not passing a namespace argument on purpose. SVGNames::*Attr are
- // defined w/o namespaces as well.
-
- // FIXME: this code is called regardless of whether name is an
- // animated SVG Attribute. It would seem we should only call this method
- // if SVGElement::isAnimatableAttribute is true, but the list of
- // animatable attributes in isAnimatableAttribute does not suffice to
- // pass all web tests. Also, animated_svg_attributes_are_dirty_ stays
- // dirty unless SynchronizeAnimatedSVGAttribute is called with
- // AnyQName(). This means that even if Element::SynchronizeAttribute()
- // is called on all attributes, animated_svg_attributes_are_dirty_ remains
- // true.
- To<SVGElement>(this)->SynchronizeAnimatedSVGAttribute(
+ if (GetElementData()->svg_attributes_are_dirty()) {
+ // We're passing a null namespace argument. svg_names::k*Attr are defined in
+ // the null namespace, but for attributes that are not (like 'href' in the
+ // XLink NS), this will not do the right thing.
+
+ // TODO(fs): svg_attributes_are_dirty_ stays dirty unless
+ // SynchronizeSVGAttribute is called with AnyQName(). This means that even
+ // if Element::SynchronizeAttribute() is called on all attributes,
+ // svg_attributes_are_dirty_ remains true. This information is available in
+ // the attribute->property map in SVGElement.
+ To<SVGElement>(this)->SynchronizeSVGAttribute(
QualifiedName(g_null_atom, local_name, g_null_atom));
}
}
@@ -2043,98 +2080,6 @@ AccessibleNode* Element::accessibleNode() {
return rare_data.EnsureAccessibleNode(this);
}
-InvisibleState Element::Invisible() const {
- const AtomicString& value = FastGetAttribute(html_names::kInvisibleAttr);
- if (value.IsNull())
- return InvisibleState::kMissing;
- if (EqualIgnoringASCIICase(value, "static"))
- return InvisibleState::kStatic;
- return InvisibleState::kInvisible;
-}
-
-bool Element::HasInvisibleAttribute() const {
- return Invisible() != InvisibleState::kMissing;
-}
-
-void Element::DispatchActivateInvisibleEventIfNeeded() {
- if (!RuntimeEnabledFeatures::InvisibleDOMEnabled())
- return;
- // Traverse all inclusive flat-tree ancestor and send activateinvisible
- // on the ones that have the invisible attribute. Default event handler
- // will remove invisible attribute of all invisible element if the event is
- // not canceled, making this element and all ancestors visible again.
- // We're saving them and the retargeted activated element as DOM structure
- // may change due to event handlers.
- HeapVector<Member<Element>> invisible_ancestors;
- HeapVector<Member<Element>> activated_elements;
- for (Node& ancestor : FlatTreeTraversal::InclusiveAncestorsOf(*this)) {
- auto* ancestor_element = DynamicTo<Element>(ancestor);
- if (ancestor_element &&
- ancestor_element->Invisible() != InvisibleState::kMissing) {
- invisible_ancestors.push_back(ancestor_element);
- activated_elements.push_back(ancestor.GetTreeScope().Retarget(*this));
- }
- }
- auto* activated_element_iterator = activated_elements.begin();
- for (Element* ancestor : invisible_ancestors) {
- DCHECK(activated_element_iterator != activated_elements.end());
- ancestor->DispatchEvent(*MakeGarbageCollected<ActivateInvisibleEvent>(
- *activated_element_iterator));
- ++activated_element_iterator;
- }
-}
-
-bool Element::IsInsideInvisibleStaticSubtree() const {
- if (!RuntimeEnabledFeatures::InvisibleDOMEnabled())
- return false;
- for (Node& ancestor : FlatTreeTraversal::InclusiveAncestorsOf(*this)) {
- auto* ancestor_element = DynamicTo<Element>(ancestor);
- if (ancestor_element &&
- ancestor_element->Invisible() == InvisibleState::kStatic)
- return true;
- }
- return false;
-}
-
-bool Element::IsInsideInvisibleSubtree() const {
- if (!RuntimeEnabledFeatures::InvisibleDOMEnabled() ||
- !CanParticipateInFlatTree())
- return false;
- for (Node& ancestor : FlatTreeTraversal::InclusiveAncestorsOf(*this)) {
- auto* ancestor_element = DynamicTo<Element>(ancestor);
- if (ancestor_element &&
- ancestor_element->Invisible() != InvisibleState::kMissing)
- return true;
- }
- return false;
-}
-
-void Element::InvisibleAttributeChanged(const AtomicString& old_value,
- const AtomicString& new_value) {
- if (old_value.IsNull() != new_value.IsNull()) {
- SetNeedsStyleRecalc(kLocalStyleChange,
- StyleChangeReasonForTracing::Create(
- style_change_reason::kInvisibleChange));
- }
- if (EqualIgnoringASCIICase(old_value, "static") &&
- !IsInsideInvisibleStaticSubtree()) {
- // This element and its descendants are not in an invisible="static" tree
- // anymore.
- CustomElement::Registry(*this)->upgrade(this);
- }
-}
-
-void Element::DefaultEventHandler(Event& event) {
- if (RuntimeEnabledFeatures::InvisibleDOMEnabled() &&
- event.type() == event_type_names::kActivateinvisible &&
- event.target() == this) {
- removeAttribute(html_names::kInvisibleAttr);
- event.SetDefaultHandled();
- return;
- }
- ContainerNode::DefaultEventHandler(event);
-}
-
bool Element::toggleAttribute(const AtomicString& qualified_name,
ExceptionState& exception_state) {
// https://dom.spec.whatwg.org/#dom-element-toggleattribute
@@ -2458,10 +2403,6 @@ void Element::AttributeChanged(const AttributeModificationParams& params) {
GetElementData()->SetPresentationAttributeStyleIsDirty(true);
SetNeedsStyleRecalc(kLocalStyleChange,
StyleChangeReasonForTracing::FromAttribute(name));
- } else if (RuntimeEnabledFeatures::InvisibleDOMEnabled() &&
- name == html_names::kInvisibleAttr &&
- params.old_value != params.new_value) {
- InvisibleAttributeChanged(params.old_value, params.new_value);
}
}
@@ -2983,8 +2924,7 @@ void Element::DetachLayoutTree(bool performing_reattach) {
GetDocument().GetStyleEngine().ClearNeedsWhitespaceReattachmentFor(this);
}
-scoped_refptr<ComputedStyle> Element::StyleForLayoutObject(
- bool calc_invisible) {
+scoped_refptr<ComputedStyle> Element::StyleForLayoutObject() {
DCHECK(GetDocument().InStyleRecalc());
// FIXME: Instead of clearing updates that may have been added from calls to
@@ -2993,14 +2933,6 @@ scoped_refptr<ComputedStyle> Element::StyleForLayoutObject(
if (ElementAnimations* element_animations = GetElementAnimations())
element_animations->CssAnimations().ClearPendingUpdate();
- if (RuntimeEnabledFeatures::InvisibleDOMEnabled() &&
- FastHasAttribute(html_names::kInvisibleAttr) && !calc_invisible) {
- auto style =
- GetDocument().GetStyleResolver()->InitialStyleForElement(GetDocument());
- style->SetDisplay(EDisplay::kNone);
- return style;
- }
-
scoped_refptr<ComputedStyle> style = HasCustomStyleCallbacks()
? CustomStyleForLayoutObject()
: OriginalStyleForLayoutObject();
@@ -3061,7 +2993,16 @@ void Element::RecalcStyle(const StyleRecalcChange change) {
}
// We're done with self style, notify the display lock.
- display_lock_style_scope.DidUpdateSelfStyle();
+ bool did_unlock = display_lock_style_scope.DidUpdateSelfStyle();
+
+ // If the update to self style caused the display-lock to unlock, then we
+ // should adjust `child_change` with whatever deferred dirty bits the context
+ // had. This ensures that during this call, we will recurse into children for
+ // layout changes (if needed).
+ if (did_unlock) {
+ child_change = display_lock_style_scope.AdjustStyleRecalcChangeForChildren(
+ child_change);
+ }
if (!display_lock_style_scope.ShouldUpdateChildStyle()) {
if (child_change.RecalcChildren()) {
@@ -3095,20 +3036,14 @@ void Element::RecalcStyle(const StyleRecalcChange change) {
To<V0InsertionPoint>(this)->RecalcStyleForInsertionPointChildren(
child_change);
} else if (ShadowRoot* root = GetShadowRoot()) {
- if (RuntimeEnabledFeatures::FlatTreeStyleRecalcEnabled()) {
- root->RecalcDescendantStyles(child_change);
- // Sad panda. This is only to clear ensured ComputedStyles for elements
- // outside the flat tree for getComputedStyle() in the cases where we
- // kSubtreeStyleChange. Style invalidation and kLocalStyleChange will
- // make sure we clear out-of-date ComputedStyles outside the flat tree
- // in Element::EnsureComputedStyle().
- if (child_change.RecalcDescendants())
- RecalcDescendantStyles(StyleRecalcChange::kClearEnsured);
- } else {
- if (child_change.TraverseChild(*root))
- root->RecalcStyle(child_change);
+ root->RecalcDescendantStyles(child_change);
+ // Sad panda. This is only to clear ensured ComputedStyles for elements
+ // outside the flat tree for getComputedStyle() in the cases where we
+ // kSubtreeStyleChange. Style invalidation and kLocalStyleChange will
+ // make sure we clear out-of-date ComputedStyles outside the flat tree
+ // in Element::EnsureComputedStyle().
+ if (child_change.RecalcDescendants())
RecalcDescendantStyles(StyleRecalcChange::kClearEnsured);
- }
} else if (auto* slot = ToHTMLSlotElementIfSupportsAssignmentOrNull(this)) {
slot->RecalcStyleForSlotChildren(child_change);
} else {
@@ -3144,7 +3079,8 @@ scoped_refptr<ComputedStyle> Element::PropagateInheritedProperties() {
const ComputedStyle* parent_style = ParentComputedStyle();
DCHECK(parent_style);
const ComputedStyle* style = GetComputedStyle();
- if (!style || style->Animations() || style->Transitions())
+ if (!style || style->Animations() || style->Transitions() ||
+ style->HasVariableReference() || style->HasVariableDeclaration())
return nullptr;
scoped_refptr<ComputedStyle> new_style = ComputedStyle::Clone(*style);
new_style->PropagateIndependentInheritedProperties(*parent_style);
@@ -3199,11 +3135,6 @@ StyleRecalcChange Element::RecalcOwnStyle(const StyleRecalcChange change) {
StyleRecalcChange child_change = change.ForChildren();
- // If we are on the find-in-page root, we need to calculate style for
- // invisible nodes in this subtree.
- if (!child_change.CalcInvisible() && this == GetDocument().FindInPageRoot())
- child_change = child_change.ForceCalcInvisible();
-
if (ParentComputedStyle()) {
if (old_style && change.IndependentInherit()) {
// When propagating inherited changes, we don't need to do a full style
@@ -3212,7 +3143,7 @@ StyleRecalcChange Element::RecalcOwnStyle(const StyleRecalcChange change) {
new_style = PropagateInheritedProperties();
}
if (!new_style)
- new_style = StyleForLayoutObject(child_change.CalcInvisible());
+ new_style = StyleForLayoutObject();
if (new_style && !ShouldStoreComputedStyle(*new_style))
new_style = nullptr;
}
@@ -3492,24 +3423,6 @@ ShadowRoot& Element::CreateAndAttachShadowRoot(ShadowRootType type) {
return *shadow_root;
}
-void Element::AttachDeclarativeShadowRoot(HTMLTemplateElement* template_element,
- ShadowRootType type,
- FocusDelegation focus_delegation,
- SlotAssignmentMode slot_assignment) {
- DCHECK(template_element);
- DCHECK(type == ShadowRootType::kOpen || type == ShadowRootType::kClosed);
- if (!CanAttachShadowRoot()) {
- // TODO(masonfreed): Eventually, this should be a DOMException.
- LOG(ERROR) << "Invalid shadow root host element";
- return;
- }
- ShadowRoot* shadow_root = &AttachShadowRootInternal(
- type, focus_delegation == FocusDelegation::kDelegateFocus,
- slot_assignment == SlotAssignmentMode::kManual);
- shadow_root->appendChild(template_element->content());
- template_element->remove();
-}
-
ShadowRoot* Element::GetShadowRoot() const {
return HasRareData() ? GetElementRareData()->GetShadowRoot() : nullptr;
}
@@ -3618,6 +3531,7 @@ ElementInternals& Element::EnsureElementInternals() {
}
ShadowRoot* Element::createShadowRoot(ExceptionState& exception_state) {
+ DCHECK(RuntimeEnabledFeatures::ShadowDOMV0Enabled(&GetDocument()));
if (ShadowRoot* root = GetShadowRoot()) {
if (root->IsUserAgent()) {
exception_state.ThrowDOMException(
@@ -3651,6 +3565,15 @@ ShadowRoot* Element::createShadowRoot(ExceptionState& exception_state) {
return &CreateShadowRootInternal();
}
+ShadowRoot& Element::CreateShadowRootInternal() {
+ DCHECK(RuntimeEnabledFeatures::ShadowDOMV0Enabled(&GetDocument()));
+ DCHECK(!ClosedShadowRoot());
+ DCHECK(AreAuthorShadowsAllowed());
+ DCHECK(!AlwaysCreateUserAgentShadowRoot());
+ GetDocument().SetShadowCascadeOrder(ShadowCascadeOrder::kShadowCascadeV0);
+ return CreateAndAttachShadowRoot(ShadowRootType::V0);
+}
+
bool Element::CanAttachShadowRoot() const {
const AtomicString& tag_name = localName();
// Checking Is{V0}CustomElement() here is just an optimization
@@ -3670,17 +3593,26 @@ bool Element::CanAttachShadowRoot() const {
tag_name == html_names::kSpanTag;
}
-ShadowRoot* Element::attachShadow(const ShadowRootInit* shadow_root_init_dict,
- ExceptionState& exception_state) {
- DCHECK(shadow_root_init_dict->hasMode());
+const char* Element::ErrorMessageForAttachShadow() const {
+ // https://dom.spec.whatwg.org/#concept-attach-a-shadow-root
+ // 1. If shadow host’s namespace is not the HTML namespace, then throw a
+ // "NotSupportedError" DOMException.
+ // 2. If shadow host’s local name is not a valid custom element name,
+ // "article", "aside", "blockquote", "body", "div", "footer", "h1", "h2",
+ // "h3", "h4", "h5", "h6", "header", "main", "nav", "p", "section", or "span",
+ // then throw a "NotSupportedError" DOMException.
if (!CanAttachShadowRoot()) {
- exception_state.ThrowDOMException(
- DOMExceptionCode::kNotSupportedError,
- "This element does not support attachShadow");
- return nullptr;
+ return "This element does not support attachShadow";
}
- // Checking IsCustomElement() here is just an optimization because
+ // 3. If shadow host’s local name is a valid custom element name, or shadow
+ // host’s is value is not null, then:
+ // 3.1 Let definition be the result of looking up a custom element
+ // definition given shadow host’s node document, its namespace, its local
+ // name, and its is value.
+ // 3.2 If definition is not null and definition’s
+ // disable shadow is true, then throw a "NotSupportedError" DOMException.
+ // Note: Checking IsCustomElement() is just an optimization because
// IsValidName() is not cheap.
if (IsCustomElement() &&
(CustomElement::IsValidName(localName()) || !IsValue().IsNull())) {
@@ -3690,42 +3622,73 @@ ShadowRoot* Element::attachShadow(const ShadowRootInit* shadow_root_init_dict,
: IsValue())
: nullptr;
if (definition && definition->DisableShadow()) {
- exception_state.ThrowDOMException(
- DOMExceptionCode::kNotSupportedError,
- "attachShadow() is disabled by disabledFeatures static field.");
- return nullptr;
+ return "attachShadow() is disabled by disabledFeatures static field.";
}
}
- if (GetShadowRoot()) {
- exception_state.ThrowDOMException(DOMExceptionCode::kNotSupportedError,
- "Shadow root cannot be created on a host "
- "which already hosts a shadow tree.");
- return nullptr;
+ // 4. If shadow host has a non-null shadow root whose "is declarative shadow
+ // root" property is false, then throw an "NotSupportedError" DOMException.
+ if (GetShadowRoot() && !GetShadowRoot()->IsDeclarativeShadowRoot()) {
+ return "Shadow root cannot be created on a host "
+ "which already hosts a shadow tree.";
}
+ return nullptr;
+}
+ShadowRoot* Element::attachShadow(const ShadowRootInit* shadow_root_init_dict,
+ ExceptionState& exception_state) {
+ DCHECK(shadow_root_init_dict->hasMode());
ShadowRootType type = shadow_root_init_dict->mode() == "open"
? ShadowRootType::kOpen
: ShadowRootType::kClosed;
-
if (type == ShadowRootType::kOpen)
UseCounter::Count(GetDocument(), WebFeature::kElementAttachShadowOpen);
else
UseCounter::Count(GetDocument(), WebFeature::kElementAttachShadowClosed);
- DCHECK(!shadow_root_init_dict->hasMode() || !GetShadowRoot());
- bool delegates_focus = shadow_root_init_dict->hasDelegatesFocus() &&
- shadow_root_init_dict->delegatesFocus();
- bool manual_slotting = shadow_root_init_dict->slotAssignment() == "manual";
- return &AttachShadowRootInternal(type, delegates_focus, manual_slotting);
+ auto focus_delegation = (shadow_root_init_dict->hasDelegatesFocus() &&
+ shadow_root_init_dict->delegatesFocus())
+ ? FocusDelegation::kDelegateFocus
+ : FocusDelegation::kNone;
+ auto slot_assignment = (shadow_root_init_dict->hasSlotAssignment() &&
+ shadow_root_init_dict->slotAssignment() == "manual")
+ ? SlotAssignmentMode::kManual
+ : SlotAssignmentMode::kAuto;
+
+ if (const char* error_message = ErrorMessageForAttachShadow()) {
+ exception_state.ThrowDOMException(DOMExceptionCode::kNotSupportedError,
+ error_message);
+ return nullptr;
+ }
+ return &AttachShadowRootInternal(type, focus_delegation, slot_assignment);
}
-ShadowRoot& Element::CreateShadowRootInternal() {
- DCHECK(!ClosedShadowRoot());
- DCHECK(AreAuthorShadowsAllowed());
- DCHECK(!AlwaysCreateUserAgentShadowRoot());
- GetDocument().SetShadowCascadeOrder(ShadowCascadeOrder::kShadowCascadeV0);
- return CreateAndAttachShadowRoot(ShadowRootType::V0);
+void Element::AttachDeclarativeShadowRoot(HTMLTemplateElement* template_element,
+ ShadowRootType type,
+ FocusDelegation focus_delegation,
+ SlotAssignmentMode slot_assignment) {
+ DCHECK(template_element);
+ DCHECK(type == ShadowRootType::kOpen || type == ShadowRootType::kClosed);
+
+ // 12. Run attach a shadow root with shadow host equal to declarative shadow
+ // host element, mode equal to declarative shadow mode, and delegates focus
+ // equal to declarative shadow delegates focus. If an exception was thrown by
+ // attach a shadow root, catch it, and report the exception.
+ if (const char* error_message = ErrorMessageForAttachShadow()) {
+ // TODO(1067488): Fire this exception at Window.
+ LOG(ERROR) << error_message;
+ return;
+ }
+ ShadowRoot& shadow_root =
+ AttachShadowRootInternal(type, focus_delegation, slot_assignment);
+ // 13.1. Set declarative shadow host element's shadow host's "is declarative
+ // shadow root" property to true.
+ shadow_root.SetIsDeclarativeShadowRoot(true);
+ // 13.2. Append the declarative template element's DocumentFragment to the
+ // newly-created shadow root.
+ shadow_root.appendChild(template_element->DeclarativeShadowContent());
+ // 13.3. Remove the declarative template element from the document.
+ template_element->remove();
}
ShadowRoot& Element::CreateUserAgentShadowRoot() {
@@ -3733,9 +3696,10 @@ ShadowRoot& Element::CreateUserAgentShadowRoot() {
return CreateAndAttachShadowRoot(ShadowRootType::kUserAgent);
}
-ShadowRoot& Element::AttachShadowRootInternal(ShadowRootType type,
- bool delegates_focus,
- bool manual_slotting) {
+ShadowRoot& Element::AttachShadowRootInternal(
+ ShadowRootType type,
+ FocusDelegation focus_delegation,
+ SlotAssignmentMode slot_assignment_mode) {
// SVG <use> is a special case for using this API to create a closed shadow
// root.
DCHECK(CanAttachShadowRoot() || IsA<SVGUseElement>(*this));
@@ -3744,11 +3708,26 @@ ShadowRoot& Element::AttachShadowRootInternal(ShadowRootType type,
DCHECK(!AlwaysCreateUserAgentShadowRoot());
GetDocument().SetShadowCascadeOrder(ShadowCascadeOrder::kShadowCascadeV1);
+
+ if (auto* shadow_root = GetShadowRoot()) {
+ // 5. If shadow host has a non-null shadow root whose "is declarative shadow
+ // root property is true, then remove all of shadow root’s children, in tree
+ // order. Return shadow host’s shadow root.
+ DCHECK(shadow_root->IsDeclarativeShadowRoot());
+ shadow_root->RemoveChildren();
+ return *shadow_root;
+ }
+
+ // 6. Let shadow be a new shadow root whose node document is shadow host’s
+ // node document, host is shadow host, and mode is mode.
+ // 9. Set shadow host’s shadow root to shadow.
ShadowRoot& shadow_root = CreateAndAttachShadowRoot(type);
- shadow_root.SetDelegatesFocus(delegates_focus);
- shadow_root.SetSlotAssignmentMode(manual_slotting
- ? SlotAssignmentMode::kManual
- : SlotAssignmentMode::kAuto);
+ // 7. Set shadow’s delegates focus to delegates focus.
+ shadow_root.SetDelegatesFocus(focus_delegation ==
+ FocusDelegation::kDelegateFocus);
+ // 8. Set shadow’s "is declarative shadow root" property to false.
+ shadow_root.SetIsDeclarativeShadowRoot(false);
+ shadow_root.SetSlotAssignmentMode(slot_assignment_mode);
return shadow_root;
}
@@ -4176,8 +4155,8 @@ void Element::focus(const FocusParams& params) {
frame_owner_element->contentDocument()->UnloadStarted())
return;
- DisplayLockUtilities::ScopedChainForcedUpdate scoped_update_forced(this);
- GetDocument().UpdateStyleAndLayoutTree();
+ // Ensure we have clean style (including forced display locks).
+ GetDocument().UpdateStyleAndLayoutTreeForNode(this);
// https://html.spec.whatwg.org/C/#focusing-steps
//
@@ -4200,18 +4179,6 @@ void Element::focus(const FocusParams& params) {
ActivateDisplayLockIfNeeded(params.type == mojom::blink::FocusType::kNone
? DisplayLockActivationReason::kScriptFocus
: DisplayLockActivationReason::kUserFocus);
- DispatchActivateInvisibleEventIfNeeded();
- if (IsInsideInvisibleSubtree()) {
- // The element stays invisible because the default event action is
- // prevented.If this is navigating to the next focusable element,
- // we need to find a replacement and focus on it instead.
- Element* found =
- GetDocument().GetPage()->GetFocusController().FindFocusableElementAfter(
- *this, params.type);
- if (found)
- found->focus(params);
- return;
- }
if (!GetDocument().GetPage()->GetFocusController().SetFocusedElement(
this, GetDocument().GetFrame(), params))
@@ -4359,12 +4326,24 @@ bool Element::IsFocusable() const {
return Element::IsMouseFocusable() || Element::IsKeyboardFocusable();
}
+bool Element::IsFocusableStyleAfterUpdate() const {
+ // In order to check focusable style, we use the existence of LayoutObjects
+ // as a proxy for determining whether the element would have a display mode
+ // that restricts visibility (such as display: none). However, with
+ // display-locking, it is possible that we deferred such LayoutObject
+ // creation. We need to ensure to update style and layout tree to have
+ // up-to-date information.
+ //
+ // Note that this isn't a part of `IsFocusableStyle()` because there are
+ // callers of that function which cannot do a layout tree update (e.g.
+ // accessibility).
+ if (RuntimeEnabledFeatures::CSSContentVisibilityEnabled())
+ GetDocument().UpdateStyleAndLayoutTreeForNode(this);
+ return IsFocusableStyle();
+}
+
bool Element::IsKeyboardFocusable() const {
- // No point in checking NeedsLayoutTreeUpdateForNode when the document
- // isn't active (style can't be invalidated in a non-active document).
- DCHECK(!GetDocument().IsActive() ||
- !GetDocument().NeedsLayoutTreeUpdateForNode(*this));
- return isConnected() && !IsInert() && IsFocusableStyle() &&
+ return isConnected() && !IsInert() && IsFocusableStyleAfterUpdate() &&
((SupportsFocus() &&
GetIntegralAttribute(html_names::kTabindexAttr, 0) >= 0) ||
(RuntimeEnabledFeatures::KeyboardFocusableScrollersEnabled() &&
@@ -4374,11 +4353,8 @@ bool Element::IsKeyboardFocusable() const {
}
bool Element::IsMouseFocusable() const {
- // No point in checking NeedsLayoutTreeUpdateForNode when the document
- // isn't active (style can't be invalidated in a non-active document).
- DCHECK(!GetDocument().IsActive() ||
- !GetDocument().NeedsLayoutTreeUpdateForNode(*this));
- return isConnected() && !IsInert() && IsFocusableStyle() && SupportsFocus() &&
+ return isConnected() && !IsInert() && IsFocusableStyleAfterUpdate() &&
+ SupportsFocus() &&
!DisplayLockPreventsActivation(
DisplayLockActivationReason::kUserFocus);
}
@@ -4391,9 +4367,11 @@ bool Element::IsAutofocusable() const {
}
bool Element::ActivateDisplayLockIfNeeded(DisplayLockActivationReason reason) {
- if (!RuntimeEnabledFeatures::CSSSubtreeVisibilityEnabled() ||
- GetDocument().LockedDisplayLockCount() ==
- GetDocument().DisplayLockBlockingAllActivationCount())
+ if (!RuntimeEnabledFeatures::CSSContentVisibilityEnabled() ||
+ GetDocument().GetDisplayLockDocumentState().LockedDisplayLockCount() ==
+ GetDocument()
+ .GetDisplayLockDocumentState()
+ .DisplayLockBlockingAllActivationCount())
return false;
const_cast<Element*>(this)->UpdateDistributionForFlatTreeTraversal();
@@ -4428,10 +4406,10 @@ bool Element::ActivateDisplayLockIfNeeded(DisplayLockActivationReason reason) {
bool Element::DisplayLockPreventsActivation(
DisplayLockActivationReason reason) const {
- if (!RuntimeEnabledFeatures::CSSSubtreeVisibilityEnabled())
+ if (!RuntimeEnabledFeatures::CSSContentVisibilityEnabled())
return false;
- if (GetDocument().LockedDisplayLockCount() == 0)
+ if (GetDocument().GetDisplayLockDocumentState().LockedDisplayLockCount() == 0)
return false;
const_cast<Element*>(this)->UpdateDistributionForFlatTreeTraversal();
@@ -4657,10 +4635,10 @@ void Element::setInnerHTML(const String& html,
}
}
-String Element::getInnerHTML(bool include_shadow_roots) const {
+String Element::getInnerHTML(const GetInnerHTMLOptions* options) const {
return CreateMarkup(
this, kChildrenOnly, kDoNotResolveURLs,
- include_shadow_roots ? kIncludeShadowRoots : kNoShadowRoots);
+ options->includeShadowRoots() ? kIncludeShadowRoots : kNoShadowRoots);
}
void Element::setOuterHTML(const String& html,
@@ -4781,7 +4759,7 @@ Element::EnsureResizeObserverData() {
}
DisplayLockContext* Element::GetDisplayLockContext() const {
- if (!RuntimeEnabledFeatures::CSSSubtreeVisibilityEnabled())
+ if (!RuntimeEnabledFeatures::CSSContentVisibilityEnabled())
return nullptr;
return HasRareData() ? GetElementRareData()->GetDisplayLockContext()
: nullptr;
@@ -4999,8 +4977,8 @@ const ComputedStyle* Element::EnsureComputedStyle(
// part of EnsureComputedStyle in an ancestor chain.
// (see CSSComputedStyleDeclarationTest::NeedsAdjacentStyleRecalc). It is OK
// that it happens, but we need to ignore the effect on
- // NeedsLayoutTreeUpdateForNode here.
- DCHECK(!GetDocument().NeedsLayoutTreeUpdateForNode(
+ // NeedsLayoutTreeUpdateForNodeIncludingDisplayLocked here.
+ DCHECK(!GetDocument().NeedsLayoutTreeUpdateForNodeIncludingDisplayLocked(
*this, true /* ignore_adjacent_style */));
// FIXME: Find and use the layoutObject from the pseudo element instead of the
@@ -5015,21 +4993,19 @@ const ComputedStyle* Element::EnsureComputedStyle(
if (element_style)
element_style = GetComputedStyle();
}
- if (RuntimeEnabledFeatures::FlatTreeStyleRecalcEnabled()) {
- if (element_style && NeedsStyleRecalc()) {
- // RecalcStyle() will not traverse into connected elements outside the
- // flat tree and we may have a dirty element or ancestors if this
- // element is not in the flat tree. If we don't need a style recalc,
- // we can just re-use the ComputedStyle from the last
- // getComputedStyle(). Otherwise, we need to clear the ensured styles
- // for the uppermost dirty ancestor and all of its descendants. If
- // this element was not the uppermost dirty element, we would not end
- // up here because a dirty ancestor would have cleared the
- // ComputedStyle in the recursive call above and element_style would
- // have been null.
- GetDocument().GetStyleEngine().ClearEnsuredDescendantStyles(*this);
- element_style = nullptr;
- }
+ if (element_style && NeedsStyleRecalc()) {
+ // RecalcStyle() will not traverse into connected elements outside the
+ // flat tree and we may have a dirty element or ancestors if this
+ // element is not in the flat tree. If we don't need a style recalc,
+ // we can just re-use the ComputedStyle from the last
+ // getComputedStyle(). Otherwise, we need to clear the ensured styles
+ // for the uppermost dirty ancestor and all of its descendants. If
+ // this element was not the uppermost dirty element, we would not end
+ // up here because a dirty ancestor would have cleared the
+ // ComputedStyle in the recursive call above and element_style would
+ // have been null.
+ GetDocument().GetStyleEngine().ClearEnsuredDescendantStyles(*this);
+ element_style = nullptr;
}
} else {
element_style = nullptr;
@@ -6263,6 +6239,17 @@ void Element::UpdatePresentationAttributeStyle() {
ComputePresentationAttributeStyle(*this);
}
+CSSPropertyValueSet* Element::CreatePresentationAttributeStyle() {
+ auto* style = MakeGarbageCollected<MutableCSSPropertyValueSet>(
+ IsSVGElement() ? kSVGAttributeMode : kHTMLStandardMode);
+ AttributeCollection attributes = AttributesWithoutUpdate();
+ for (const Attribute& attr : attributes)
+ CollectStyleForPresentationAttribute(attr.GetName(), attr.Value(), style);
+ if (IsSVGElement())
+ To<SVGElement>(this)->CollectStyleForAnimatedPresentationAttributes(style);
+ return style;
+}
+
void Element::AddPropertyToPresentationAttributeStyle(
MutableCSSPropertyValueSet* style,
CSSPropertyID property_id,
diff --git a/chromium/third_party/blink/renderer/core/dom/element.h b/chromium/third_party/blink/renderer/core/dom/element.h
index 541b0321bd1..7e952657c13 100644
--- a/chromium/third_party/blink/renderer/core/dom/element.h
+++ b/chromium/third_party/blink/renderer/core/dom/element.h
@@ -65,6 +65,7 @@ class ElementRareData;
class ExceptionState;
class FloatQuad;
class FloatSize;
+class GetInnerHTMLOptions;
class HTMLTemplateElement;
class Image;
class InputDeviceCapabilities;
@@ -113,8 +114,9 @@ enum class ElementFlags {
};
enum class ShadowRootType;
-enum class FocusDelegation;
-enum class SlotAssignmentMode;
+
+enum class SlotAssignmentMode { kManual, kAuto };
+enum class FocusDelegation { kNone, kDelegateFocus };
enum class SelectionBehaviorOnFocus {
kReset,
@@ -130,12 +132,6 @@ enum class NamedItemType {
kNameOrIdWithName,
};
-enum class InvisibleState {
- kMissing,
- kStatic,
- kInvisible,
-};
-
struct FocusParams {
STACK_ALLOCATED();
@@ -176,6 +172,7 @@ class CORE_EXPORT Element : public ContainerNode, public Animatable {
DEFINE_ATTRIBUTE_EVENT_LISTENER(beforecut, kBeforecut)
DEFINE_ATTRIBUTE_EVENT_LISTENER(beforepaste, kBeforepaste)
DEFINE_ATTRIBUTE_EVENT_LISTENER(search, kSearch)
+ DEFINE_ATTRIBUTE_EVENT_LISTENER(beforematch, kBeforematch)
bool hasAttribute(const QualifiedName&) const;
const AtomicString& getAttribute(const QualifiedName&) const;
@@ -219,17 +216,9 @@ class CORE_EXPORT Element : public ContainerNode, public Animatable {
void SetElementAttribute(const QualifiedName&, Element*);
base::Optional<HeapVector<Member<Element>>> GetElementArrayAttribute(
const QualifiedName& name);
- // TODO(crbug.com/1060971): Remove |is_null| version.
- HeapVector<Member<Element>> GetElementArrayAttribute( // DEPRECATED
- const QualifiedName& name,
- bool& is_null);
void SetElementArrayAttribute(
const QualifiedName&,
const base::Optional<HeapVector<Member<Element>>>&);
- // TODO(crbug.com/1060971): Remove |is_null| version.
- void SetElementArrayAttribute(const QualifiedName&, // DEPRECATED
- HeapVector<Member<Element>>,
- bool is_null);
// Call this to get the value of an attribute that is known not to be the
// style attribute or one of the SVG animatable attributes.
@@ -311,8 +300,7 @@ class CORE_EXPORT Element : public ContainerNode, public Animatable {
// return value should be cached for performance.
AttributeCollection Attributes() const;
// This variant will not update the potentially invalid attributes. To be used
- // when not interested in style attribute or one of the SVG animation
- // attributes.
+ // when not interested in style attribute or one of the SVG attributes.
AttributeCollection AttributesWithoutUpdate() const;
void scrollIntoView(ScrollIntoViewOptionsOrBoolean);
@@ -362,15 +350,6 @@ class CORE_EXPORT Element : public ContainerNode, public Animatable {
AccessibleNode* ExistingAccessibleNode() const;
AccessibleNode* accessibleNode();
- InvisibleState Invisible() const;
- bool HasInvisibleAttribute() const;
-
- void DispatchActivateInvisibleEventIfNeeded();
- bool IsInsideInvisibleSubtree() const;
- bool IsInsideInvisibleStaticSubtree() const;
-
- void DefaultEventHandler(Event&) override;
-
void DidMoveToNewDocument(Document&) override;
void removeAttribute(const AtomicString& name);
@@ -565,6 +544,7 @@ class CORE_EXPORT Element : public ContainerNode, public Animatable {
// throws an exception. Multiple shadow roots are allowed only when
// createShadowRoot() is used without any parameters from JavaScript.
ShadowRoot* createShadowRoot(ExceptionState&);
+
ShadowRoot* attachShadow(const ShadowRootInit*, ExceptionState&);
void AttachDeclarativeShadowRoot(HTMLTemplateElement*,
@@ -576,9 +556,10 @@ class CORE_EXPORT Element : public ContainerNode, public Animatable {
return CreateShadowRootInternal();
}
ShadowRoot& CreateUserAgentShadowRoot();
- ShadowRoot& AttachShadowRootInternal(ShadowRootType,
- bool delegates_focus = false,
- bool manual_slotting = false);
+ ShadowRoot& AttachShadowRootInternal(
+ ShadowRootType,
+ FocusDelegation focus_delegation = FocusDelegation::kNone,
+ SlotAssignmentMode slot_assignment_mode = SlotAssignmentMode::kAuto);
// Returns the shadow root attached to this element if it is a shadow host.
ShadowRoot* GetShadowRoot() const;
@@ -720,7 +701,7 @@ class CORE_EXPORT Element : public ContainerNode, public Animatable {
String innerHTML() const;
String outerHTML() const;
void setInnerHTML(const String&, ExceptionState& = ASSERT_NO_EXCEPTION);
- String getInnerHTML(bool include_shadow_roots) const;
+ String getInnerHTML(const GetInnerHTMLOptions* options) const;
void setOuterHTML(const String&, ExceptionState& = ASSERT_NO_EXCEPTION);
void setPointerCapture(PointerId poinetr_id, ExceptionState&);
@@ -866,8 +847,7 @@ class CORE_EXPORT Element : public ContainerNode, public Animatable {
bool IsSpellCheckingEnabled() const;
// FIXME: public for LayoutTreeBuilder, we shouldn't expose this though.
- scoped_refptr<ComputedStyle> StyleForLayoutObject(
- bool calc_invisible = false);
+ scoped_refptr<ComputedStyle> StyleForLayoutObject();
bool HasID() const;
bool HasClass() const;
@@ -897,6 +877,8 @@ class CORE_EXPORT Element : public ContainerNode, public Animatable {
MutableCSSPropertyValueSet& EnsureMutableInlineStyle();
void ClearMutableInlineStyleIfEmpty();
+ CSSPropertyValueSet* CreatePresentationAttributeStyle();
+
void setTabIndex(int);
int tabIndex() const;
@@ -985,6 +967,9 @@ class CORE_EXPORT Element : public ContainerNode, public Animatable {
// This method cannot be moved to LayoutObject because some focusable nodes
// don't have layoutObjects. e.g., HTMLOptionElement.
virtual bool IsFocusableStyle() const;
+ // Similar to above, except that it will ensure that any deferred work to
+ // create layout objects is completed (e.g. in display-locked trees).
+ bool IsFocusableStyleAfterUpdate() const;
// classAttributeChanged() exists to share code between
// parseAttribute (called via setAttribute()) and
@@ -1012,6 +997,8 @@ class CORE_EXPORT Element : public ContainerNode, public Animatable {
void HideNonce();
private:
+ friend class AXObject;
+
void ScrollLayoutBoxBy(const ScrollToOptions*);
void ScrollLayoutBoxTo(const ScrollToOptions*);
void ScrollFrameBy(const ScrollToOptions*);
@@ -1031,8 +1018,9 @@ class CORE_EXPORT Element : public ContainerNode, public Animatable {
bool IsDocumentNode() const =
delete; // This will catch anyone doing an unnecessary check.
- bool CanAttachShadowRoot() const;
ShadowRoot& CreateShadowRootInternal();
+ bool CanAttachShadowRoot() const;
+ const char* ErrorMessageForAttachShadow() const;
void StyleAttributeChanged(const AtomicString& new_style_string,
AttributeModificationReason);
@@ -1042,9 +1030,6 @@ class CORE_EXPORT Element : public ContainerNode, public Animatable {
void InlineStyleChanged();
void SetInlineStyleFromString(const AtomicString&);
- void InvisibleAttributeChanged(const AtomicString& old_value,
- const AtomicString& new_value);
-
// If the only inherited changes in the parent element are independent,
// these changes can be directly propagated to this element (the child).
// If these conditions are met, propagates the changes to the current style
diff --git a/chromium/third_party/blink/renderer/core/dom/element.idl b/chromium/third_party/blink/renderer/core/dom/element.idl
index 5ed1c0311d6..b83ed0eab06 100644
--- a/chromium/third_party/blink/renderer/core/dom/element.idl
+++ b/chromium/third_party/blink/renderer/core/dom/element.idl
@@ -97,7 +97,7 @@ callback ScrollStateCallback = void (ScrollState scrollState);
[CEReactions, CustomElementCallbacks, RaisesException] void insertAdjacentHTML(DOMString position, HTMLString text);
// Declarative Shadow DOM getInnerHTML() function.
- [RuntimeEnabled=DeclarativeShadowDOM, RuntimeCallStatsCounter=ElementGetInnerHTML] HTMLString getInnerHTML(boolean includeShadowRoots);
+ [RuntimeEnabled=DeclarativeShadowDOM, RuntimeCallStatsCounter=ElementGetInnerHTML] HTMLString getInnerHTML(optional GetInnerHTMLOptions options = {});
// Pointer Lock
// https://w3c.github.io/pointerlock/#extensions-to-the-element-interface
@@ -143,13 +143,12 @@ callback ScrollStateCallback = void (ScrollState scrollState);
// Accessibility Object Model
[RuntimeEnabled=AccessibilityObjectModel] readonly attribute AccessibleNode? accessibleNode;
- [RuntimeEnabled=InvisibleDOM, CEReactions, CustomElementCallbacks, Reflect, ReflectOnly=("static","invisible"), ReflectEmpty="invisible", ReflectInvalid="invisible"] attribute DOMString invisible;
-
// Event handler attributes
attribute EventHandler onbeforecopy;
attribute EventHandler onbeforecut;
attribute EventHandler onbeforepaste;
attribute EventHandler onsearch;
+ [RuntimeEnabled=BeforeMatchEvent] attribute EventHandler onbeforematch;
// Element Timing
[Affects=Nothing, CEReactions, Reflect=elementtiming] attribute DOMString elementTiming;
diff --git a/chromium/third_party/blink/renderer/core/dom/element_data.cc b/chromium/third_party/blink/renderer/core/dom/element_data.cc
index cb990d551b0..f9cca268d29 100644
--- a/chromium/third_party/blink/renderer/core/dom/element_data.cc
+++ b/chromium/third_party/blink/renderer/core/dom/element_data.cc
@@ -55,13 +55,13 @@ ElementData::ElementData()
: bit_field_(IsUniqueFlag::encode(true) | ArraySize::encode(0) |
PresentationAttributeStyleIsDirty::encode(false) |
StyleAttributeIsDirty::encode(false) |
- AnimatedSvgAttributesAreDirty::encode(false)) {}
+ SvgAttributesAreDirty::encode(false)) {}
ElementData::ElementData(unsigned array_size)
: bit_field_(IsUniqueFlag::encode(false) | ArraySize::encode(array_size) |
PresentationAttributeStyleIsDirty::encode(false) |
StyleAttributeIsDirty::encode(false) |
- AnimatedSvgAttributesAreDirty::encode(false)) {}
+ SvgAttributesAreDirty::encode(false)) {}
ElementData::ElementData(const ElementData& other, bool is_unique)
: bit_field_(
@@ -71,8 +71,8 @@ ElementData::ElementData(const ElementData& other, bool is_unique)
other.bit_field_.get<PresentationAttributeStyleIsDirty>()) |
StyleAttributeIsDirty::encode(
other.bit_field_.get<StyleAttributeIsDirty>()) |
- AnimatedSvgAttributesAreDirty::encode(
- other.bit_field_.get<AnimatedSvgAttributesAreDirty>())),
+ SvgAttributesAreDirty::encode(
+ other.bit_field_.get<SvgAttributesAreDirty>())),
class_names_(other.class_names_),
id_for_style_resolution_(other.id_for_style_resolution_) {
// NOTE: The inline style is copied by the subclass copy constructor since we
diff --git a/chromium/third_party/blink/renderer/core/dom/element_data.h b/chromium/third_party/blink/renderer/core/dom/element_data.h
index bda30301170..ad658e442bc 100644
--- a/chromium/third_party/blink/renderer/core/dom/element_data.h
+++ b/chromium/third_party/blink/renderer/core/dom/element_data.h
@@ -93,8 +93,7 @@ class ElementData : public GarbageCollected<ElementData> {
using PresentationAttributeStyleIsDirty = ArraySize::DefineNextValue<bool, 1>;
using StyleAttributeIsDirty =
PresentationAttributeStyleIsDirty::DefineNextValue<bool, 1>;
- using AnimatedSvgAttributesAreDirty =
- StyleAttributeIsDirty::DefineNextValue<bool, 1>;
+ using SvgAttributesAreDirty = StyleAttributeIsDirty::DefineNextValue<bool, 1>;
ElementData();
explicit ElementData(unsigned array_size);
@@ -106,8 +105,8 @@ class ElementData : public GarbageCollected<ElementData> {
bool style_attribute_is_dirty() const {
return bit_field_.get<StyleAttributeIsDirty>();
}
- bool animated_svg_attributes_are_dirty() const {
- return bit_field_.get<AnimatedSvgAttributesAreDirty>();
+ bool svg_attributes_are_dirty() const {
+ return bit_field_.get<SvgAttributesAreDirty>();
}
// Following 3 fields are meant to be mutable and can change even when const.
@@ -121,10 +120,9 @@ class ElementData : public GarbageCollected<ElementData> {
const_cast<BitField*>(&bit_field_)
->set<StyleAttributeIsDirty>(style_attribute_is_dirty);
}
- void SetAnimatedSvgAttributesAreDirty(
- bool animated_svg_attributes_are_dirty) const {
+ void SetSvgAttributesAreDirty(bool svg_attributes_are_dirty) const {
const_cast<BitField*>(&bit_field_)
- ->set<AnimatedSvgAttributesAreDirty>(animated_svg_attributes_are_dirty);
+ ->set<SvgAttributesAreDirty>(svg_attributes_are_dirty);
}
BitField bit_field_;
diff --git a/chromium/third_party/blink/renderer/core/dom/events/custom_event.cc b/chromium/third_party/blink/renderer/core/dom/events/custom_event.cc
index 95b79fbcd94..9da77b8f300 100644
--- a/chromium/third_party/blink/renderer/core/dom/events/custom_event.cc
+++ b/chromium/third_party/blink/renderer/core/dom/events/custom_event.cc
@@ -36,9 +36,19 @@ CustomEvent::CustomEvent(ScriptState* script_state,
const AtomicString& type,
const CustomEventInit* initializer)
: Event(type, initializer) {
+ // TODO(crbug.com/1070964): Remove this existence check. There is a bug that
+ // the current code generator does not initialize a ScriptValue with the
+ // v8::Null value despite that the dictionary member has the default value of
+ // IDL null. |hasDetail| guard is necessary here.
if (initializer->hasDetail()) {
- detail_.SetAcrossWorld(script_state->GetIsolate(),
- initializer->detail().V8Value());
+ v8::Local<v8::Value> detail = initializer->detail().V8Value();
+ // TODO(crbug.com/1070871): Remove the following IsNullOrUndefined() check.
+ // This null/undefined check fills the gap between the new and old bindings
+ // code. The new behavior is preferred in a long term, and we'll switch to
+ // the new behavior once the migration to the new bindings gets settled.
+ if (!detail->IsNullOrUndefined()) {
+ detail_.SetAcrossWorld(script_state->GetIsolate(), detail);
+ }
}
}
diff --git a/chromium/third_party/blink/renderer/core/dom/events/event_target.cc b/chromium/third_party/blink/renderer/core/dom/events/event_target.cc
index 2c506ac3266..a38b4bde76e 100644
--- a/chromium/third_party/blink/renderer/core/dom/events/event_target.cc
+++ b/chromium/third_party/blink/renderer/core/dom/events/event_target.cc
@@ -299,9 +299,7 @@ EventTarget* EventTarget::Create(ScriptState* script_state) {
}
inline LocalDOMWindow* EventTarget::ExecutingWindow() {
- if (ExecutionContext* context = GetExecutionContext())
- return context->ExecutingWindow();
- return nullptr;
+ return DynamicTo<LocalDOMWindow>(GetExecutionContext());
}
bool EventTarget::IsTopLevelNode() {
@@ -342,8 +340,7 @@ void EventTarget::SetDefaultAddEventListenerOptions(
}
}
- if (RuntimeEnabledFeatures::PassiveDocumentEventListenersEnabled() &&
- IsTouchScrollBlockingEvent(event_type)) {
+ if (IsTouchScrollBlockingEvent(event_type)) {
if (!options->hasPassive() && IsTopLevelNode()) {
options->setPassive(true);
options->SetPassiveForcedForDocumentTarget(true);
@@ -366,11 +363,9 @@ void EventTarget::SetDefaultAddEventListenerOptions(
executing_window->document(),
WebFeature::kAddDocumentLevelPassiveDefaultWheelEventListener);
}
- if (RuntimeEnabledFeatures::PassiveDocumentWheelEventListenersEnabled()) {
- options->setPassive(true);
- options->SetPassiveForcedForDocumentTarget(true);
- return;
- }
+ options->setPassive(true);
+ options->SetPassiveForcedForDocumentTarget(true);
+ return;
}
}
diff --git a/chromium/third_party/blink/renderer/core/dom/events/listener_leak_test.cc b/chromium/third_party/blink/renderer/core/dom/events/listener_leak_test.cc
index d2d8e5dcef2..7a6abf6e49f 100644
--- a/chromium/third_party/blink/renderer/core/dom/events/listener_leak_test.cc
+++ b/chromium/third_party/blink/renderer/core/dom/events/listener_leak_test.cc
@@ -97,8 +97,7 @@ class ListenerLeakTest : public testing::Test {
WebString::FromUTF8(base_url), blink::test::CoreTestDataPath(),
WebString::FromUTF8(file_name));
web_view_helper.InitializeAndLoad(base_url + file_name);
- V8GCController::CollectAllGarbageForTesting(
- isolate(), v8::EmbedderHeapTracer::EmbedderStackState::kEmpty);
+ ThreadState::Current()->CollectAllGarbageForTesting();
}
v8::Isolate* isolate() const {
diff --git a/chromium/third_party/blink/renderer/core/dom/get_inner_html_options.idl b/chromium/third_party/blink/renderer/core/dom/get_inner_html_options.idl
new file mode 100644
index 00000000000..47b06446229
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/dom/get_inner_html_options.idl
@@ -0,0 +1,7 @@
+// 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.
+
+dictionary GetInnerHTMLOptions {
+ boolean includeShadowRoots = true;
+};
diff --git a/chromium/third_party/blink/renderer/core/dom/global_event_handlers.h b/chromium/third_party/blink/renderer/core/dom/global_event_handlers.h
index c92b4ed1cd6..ba4d55ea4ec 100644
--- a/chromium/third_party/blink/renderer/core/dom/global_event_handlers.h
+++ b/chromium/third_party/blink/renderer/core/dom/global_event_handlers.h
@@ -44,7 +44,6 @@ class GlobalEventHandlers {
DEFINE_STATIC_ATTRIBUTE_EVENT_LISTENER(animationiteration,
kAnimationiteration)
DEFINE_STATIC_ATTRIBUTE_EVENT_LISTENER(animationstart, kAnimationstart)
- DEFINE_STATIC_ATTRIBUTE_EVENT_LISTENER(activateinvisible, kActivateinvisible)
DEFINE_STATIC_ATTRIBUTE_EVENT_LISTENER(auxclick, kAuxclick)
DEFINE_STATIC_ATTRIBUTE_EVENT_LISTENER(blur, kBlur)
DEFINE_STATIC_ATTRIBUTE_EVENT_LISTENER(cancel, kCancel)
diff --git a/chromium/third_party/blink/renderer/core/dom/global_event_handlers.idl b/chromium/third_party/blink/renderer/core/dom/global_event_handlers.idl
index e5ea3133cd1..7fb4221167b 100644
--- a/chromium/third_party/blink/renderer/core/dom/global_event_handlers.idl
+++ b/chromium/third_party/blink/renderer/core/dom/global_event_handlers.idl
@@ -33,7 +33,6 @@
LegacyTreatAsPartialInterface
] interface mixin GlobalEventHandlers {
attribute EventHandler onabort;
- [RuntimeEnabled=InvisibleDOM] attribute EventHandler onactivateinvisible;
attribute EventHandler onblur;
attribute EventHandler oncancel;
attribute EventHandler oncanplay;
@@ -55,8 +54,7 @@
attribute EventHandler ondurationchange;
attribute EventHandler onemptied;
attribute EventHandler onended;
- // FIXME: onerror should be an OnErrorEventHandler.
- attribute EventHandler onerror;
+ attribute OnErrorEventHandler onerror;
attribute EventHandler onfocus;
attribute EventHandler onformdata;
attribute EventHandler oninput;
@@ -82,7 +80,7 @@
attribute EventHandler onplaying;
attribute EventHandler onprogress;
attribute EventHandler onratechange;
- [RuntimeEnabled=CSSSubtreeVisibilityActivationEvent] attribute EventHandler onrendersubtreeactivation;
+ [RuntimeEnabled=CSSContentVisibilityActivationEvent] attribute EventHandler onrendersubtreeactivation;
attribute EventHandler onreset;
attribute EventHandler onresize;
attribute EventHandler onscroll;
diff --git a/chromium/third_party/blink/renderer/core/dom/idle_deadline.h b/chromium/third_party/blink/renderer/core/dom/idle_deadline.h
index d37bdc308e7..a38bac11aee 100644
--- a/chromium/third_party/blink/renderer/core/dom/idle_deadline.h
+++ b/chromium/third_party/blink/renderer/core/dom/idle_deadline.h
@@ -19,12 +19,9 @@ class CORE_EXPORT IdleDeadline : public ScriptWrappable {
DEFINE_WRAPPERTYPEINFO();
public:
- // These values are persisted to logs. Entries should not be renumbered and
- // numeric values should never be reused.
enum class CallbackType {
- kCalledWhenIdle = 0,
- kCalledByTimeout = 1,
- kMaxValue = kCalledByTimeout
+ kCalledWhenIdle,
+ kCalledByTimeout,
};
IdleDeadline(base::TimeTicks deadline, CallbackType);
diff --git a/chromium/third_party/blink/renderer/core/dom/layout_tree_builder_traversal.cc b/chromium/third_party/blink/renderer/core/dom/layout_tree_builder_traversal.cc
index c023f6557b3..3ef1701dd42 100644
--- a/chromium/third_party/blink/renderer/core/dom/layout_tree_builder_traversal.cc
+++ b/chromium/third_party/blink/renderer/core/dom/layout_tree_builder_traversal.cc
@@ -109,18 +109,18 @@ Node* LayoutTreeBuilderTraversal::NextSibling(const Node& node) {
if (Node* next = FlatTreeTraversal::NextSibling(node))
return next;
parent_element = DynamicTo<Element>(FlatTreeTraversal::Parent(node));
+ if (!parent_element)
+ return nullptr;
}
- if (parent_element) {
- if (Node* next = parent_element->GetPseudoElement(kPseudoIdAfter))
- return next;
- }
+ if (Node* next = parent_element->GetPseudoElement(kPseudoIdAfter))
+ return next;
FALLTHROUGH;
case kPseudoIdAfter:
- break;
+ return nullptr;
default:
NOTREACHED();
+ return nullptr;
}
- return nullptr;
}
Node* LayoutTreeBuilderTraversal::PreviousSibling(const Node& node) {
@@ -140,24 +140,22 @@ Node* LayoutTreeBuilderTraversal::PreviousSibling(const Node& node) {
if (Node* previous = FlatTreeTraversal::PreviousSibling(node))
return previous;
parent_element = DynamicTo<Element>(FlatTreeTraversal::Parent(node));
+ if (!parent_element)
+ return nullptr;
}
- if (parent_element) {
- if (Node* previous = parent_element->GetPseudoElement(kPseudoIdBefore))
- return previous;
- }
+ if (Node* previous = parent_element->GetPseudoElement(kPseudoIdBefore))
+ return previous;
FALLTHROUGH;
case kPseudoIdBefore:
- if (parent_element) {
- if (Node* previous = parent_element->GetPseudoElement(kPseudoIdMarker))
- return previous;
- }
+ if (Node* previous = parent_element->GetPseudoElement(kPseudoIdMarker))
+ return previous;
FALLTHROUGH;
case kPseudoIdMarker:
- break;
+ return nullptr;
default:
NOTREACHED();
+ return nullptr;
}
- return nullptr;
}
Node* LayoutTreeBuilderTraversal::LastChild(const Node& node) {
diff --git a/chromium/third_party/blink/renderer/core/dom/live_node_list_registry.cc b/chromium/third_party/blink/renderer/core/dom/live_node_list_registry.cc
index 6366cf6595d..343ba669ba0 100644
--- a/chromium/third_party/blink/renderer/core/dom/live_node_list_registry.cc
+++ b/chromium/third_party/blink/renderer/core/dom/live_node_list_registry.cc
@@ -42,7 +42,7 @@ void LiveNodeListRegistry::RecomputeMask() {
mask_ = mask;
}
-void LiveNodeListRegistry::ProcessCustomWeakness(const WeakCallbackInfo& info) {
+void LiveNodeListRegistry::ProcessCustomWeakness(const LivenessBroker& info) {
auto* it = std::remove_if(data_.begin(), data_.end(), [info](Entry entry) {
return !info.IsHeapObjectAlive(entry.first);
});
diff --git a/chromium/third_party/blink/renderer/core/dom/live_node_list_registry.h b/chromium/third_party/blink/renderer/core/dom/live_node_list_registry.h
index 8299c9df44d..d93b1bc2bda 100644
--- a/chromium/third_party/blink/renderer/core/dom/live_node_list_registry.h
+++ b/chromium/third_party/blink/renderer/core/dom/live_node_list_registry.h
@@ -32,8 +32,6 @@ enum NodeListInvalidationType : int;
class CORE_EXPORT LiveNodeListRegistry {
DISALLOW_NEW();
- using Entry = std::pair<UntracedMember<const LiveNodeListBase>, unsigned>;
-
public:
LiveNodeListRegistry() = default;
void Add(const LiveNodeListBase*, NodeListInvalidationType);
@@ -57,9 +55,13 @@ class CORE_EXPORT LiveNodeListRegistry {
// Removes any entries corresponding to node lists which have been collected
// by the GC, and updates the mask accordingly.
- void ProcessCustomWeakness(const WeakCallbackInfo&);
+ void ProcessCustomWeakness(const LivenessBroker&);
+ // We use UntracedMember<> here to recalculate the mask in
+ // |ProcessCustomWeakness()|.
+ using Entry = std::pair<UntracedMember<const LiveNodeListBase>, unsigned>;
Vector<Entry> data_;
+
unsigned mask_ = 0;
DISALLOW_COPY_AND_ASSIGN(LiveNodeListRegistry);
};
diff --git a/chromium/third_party/blink/renderer/core/dom/node.cc b/chromium/third_party/blink/renderer/core/dom/node.cc
index 371f39cbed5..87bf4f19bb6 100644
--- a/chromium/third_party/blink/renderer/core/dom/node.cc
+++ b/chromium/third_party/blink/renderer/core/dom/node.cc
@@ -37,6 +37,7 @@
#include "third_party/blink/renderer/core/css/resolver/style_resolver.h"
#include "third_party/blink/renderer/core/css/style_change_reason.h"
#include "third_party/blink/renderer/core/css/style_engine.h"
+#include "third_party/blink/renderer/core/display_lock/display_lock_document_state.h"
#include "third_party/blink/renderer/core/display_lock/display_lock_utilities.h"
#include "third_party/blink/renderer/core/dom/attr.h"
#include "third_party/blink/renderer/core/dom/attribute.h"
@@ -965,18 +966,24 @@ void Node::remove() {
Node* Node::cloneNode(bool deep, ExceptionState& exception_state) const {
// https://dom.spec.whatwg.org/#dom-node-clonenode
- // 1. If context object is a shadow root, then throw a
- // "NotSupportedError" DOMException.
+ // 1. If this is a shadow root, then throw a "NotSupportedError" DOMException.
if (IsShadowRoot()) {
exception_state.ThrowDOMException(DOMExceptionCode::kNotSupportedError,
"ShadowRoot nodes are not clonable.");
return nullptr;
}
- // 2. Return a clone of the context object, with the clone children
- // flag set if deep is true.
+ // 2. Return a clone of this, with the clone children flag set if deep is
+ // true, and the clone shadows flag set if this is a DocumentFragment whose
+ // host is an HTML template element.
+ auto* fragment = DynamicTo<DocumentFragment>(this);
+ bool clone_shadows_flag =
+ fragment && fragment->IsTemplateContent() &&
+ RuntimeEnabledFeatures::DeclarativeShadowDOMEnabled();
return Clone(GetDocument(),
- deep ? CloneChildrenFlag::kClone : CloneChildrenFlag::kSkip);
+ deep ? (clone_shadows_flag ? CloneChildrenFlag::kCloneWithShadows
+ : CloneChildrenFlag::kClone)
+ : CloneChildrenFlag::kSkip);
}
Node* Node::cloneNode(bool deep) const {
@@ -1294,8 +1301,6 @@ bool Node::ShouldSkipMarkingStyleDirty() const {
parent = parent->GetStyleRecalcParent();
return !parent || !parent->GetComputedStyle();
}
- if (!RuntimeEnabledFeatures::FlatTreeStyleRecalcEnabled())
- return false;
// If this is the root element, and it does not have a computed style, we
// still need to mark it for style recalc since it may change from
// display:none. Otherwise, the node is not in the flat tree, and we can
@@ -1318,7 +1323,7 @@ void Node::MarkAncestorsWithChildNeedsStyleRecalc() {
break;
// If we reach a locked ancestor, we should abort since the ancestor marking
// will be done when the lock is committed.
- if (RuntimeEnabledFeatures::CSSSubtreeVisibilityEnabled()) {
+ if (RuntimeEnabledFeatures::CSSContentVisibilityEnabled()) {
auto* ancestor_element = DynamicTo<Element>(ancestor);
if (ancestor_element && ancestor_element->StyleRecalcBlockedByDisplayLock(
DisplayLockLifecycleTarget::kChildren)) {
@@ -1332,21 +1337,18 @@ void Node::MarkAncestorsWithChildNeedsStyleRecalc() {
// early return here is a performance optimization.
if (parent_dirty)
return;
- // If we are outside the flat tree and FlatTreeStyleRecalc is enabled, we
- // should not update the recalc root because we should not traverse those
- // nodes from StyleEngine::RecalcStyle().
- if (RuntimeEnabledFeatures::FlatTreeStyleRecalcEnabled()) {
- if (const ComputedStyle* current_style = GetComputedStyle()) {
- if (current_style->IsEnsuredOutsideFlatTree())
- return;
- } else {
- while (style_parent && !style_parent->CanParticipateInFlatTree())
- style_parent = style_parent->GetStyleRecalcParent();
- if (style_parent) {
- if (const auto* parent_style = style_parent->GetComputedStyle()) {
- if (parent_style->IsEnsuredOutsideFlatTree())
- return;
- }
+ // If we are outside the flat tree we should not update the recalc root
+ // because we should not traverse those nodes from StyleEngine::RecalcStyle().
+ if (const ComputedStyle* current_style = GetComputedStyle()) {
+ if (current_style->IsEnsuredOutsideFlatTree())
+ return;
+ } else {
+ while (style_parent && !style_parent->CanParticipateInFlatTree())
+ style_parent = style_parent->GetStyleRecalcParent();
+ if (style_parent) {
+ if (const auto* parent_style = style_parent->GetComputedStyle()) {
+ if (parent_style->IsEnsuredOutsideFlatTree())
+ return;
}
}
}
@@ -1354,8 +1356,9 @@ void Node::MarkAncestorsWithChildNeedsStyleRecalc() {
// roots. These would be updated when we commit the lock. If we have locked
// display locks somewhere in the document, we iterate up the ancestor chain
// to check if we're in one such subtree.
- if (RuntimeEnabledFeatures::CSSSubtreeVisibilityEnabled() &&
- GetDocument().LockedDisplayLockCount() > 0) {
+ if (RuntimeEnabledFeatures::CSSContentVisibilityEnabled() &&
+ GetDocument().GetDisplayLockDocumentState().LockedDisplayLockCount() >
+ 0) {
for (auto* ancestor_copy = ancestor; ancestor_copy;
ancestor_copy = ancestor_copy->GetStyleRecalcParent()) {
auto* ancestor_copy_element = DynamicTo<Element>(ancestor_copy);
@@ -1391,12 +1394,6 @@ Element* Node::FlatTreeParentForChildDirty() const {
return ParentOrShadowHostElement();
}
-ContainerNode* Node::GetStyleRecalcParent() const {
- if (RuntimeEnabledFeatures::FlatTreeStyleRecalcEnabled())
- return FlatTreeParentForChildDirty();
- return ParentOrShadowHostNode();
-}
-
void Node::MarkAncestorsWithChildNeedsReattachLayoutTree() {
DCHECK(isConnected());
Element* ancestor = GetReattachParent();
@@ -1427,13 +1424,7 @@ void Node::SetNeedsStyleRecalc(StyleChangeType change_type,
const StyleChangeReasonForTracing& reason) {
DCHECK(!GetDocument().GetStyleEngine().InRebuildLayoutTree());
DCHECK(change_type != kNoStyleChange);
- // TODO(crbug.com/972752): ShadowRoot can be marked kSubtreeStyleChange from
- // RescheduleSiblingInvalidationsAsDescendants() for WholeSubtreeInvalid(). We
- // should instead mark the shadow host for subtree recalc when we traverse the
- // flat tree (and skip non-slotted host children).
- DCHECK(IsElementNode() || IsTextNode() ||
- (IsShadowRoot() &&
- !RuntimeEnabledFeatures::FlatTreeStyleRecalcEnabled()));
+ DCHECK(IsElementNode() || IsTextNode());
if (!InActiveDocument())
return;
@@ -1767,6 +1758,16 @@ bool Node::CanStartSelection() const {
return parent ? parent->CanStartSelection() : true;
}
+void Node::NotifyPriorityScrollAnchorStatusChanged() {
+ auto* node = this;
+ while (node && !node->GetLayoutObject())
+ node = FlatTreeTraversal::Parent(*node);
+ if (node) {
+ DCHECK(node->GetLayoutObject());
+ node->GetLayoutObject()->NotifyPriorityScrollAnchorStatusChanged();
+ }
+}
+
// StyledElements allow inline style (style="border: 1px"), presentational
// attributes (ex. color), class names (ex. class="foo bar") and other non-basic
// styling features. They also control if this element can participate in style
@@ -3338,12 +3339,11 @@ void Node::FlatTreeParentChanged() {
// The node changed the flat tree position by being slotted to a new slot or
// slotted for the first time. We need to recalc style since the inheritance
// parent may have changed.
- if (NeedsStyleRecalc() &&
- RuntimeEnabledFeatures::FlatTreeStyleRecalcEnabled()) {
- // For flat tree style recalc, the ancestor chain may have changed. We need
- // make sure that the child-dirty flags are updated, but the
- // SetNeedsStyleRecalc() call below will skip
- // MarkAncestorsWithChildNeedsStyleRecalc() if the node was already dirty.
+ if (NeedsStyleRecalc()) {
+ // The ancestor chain may have changed. We need to make sure that the
+ // child-dirty flags are updated, but the SetNeedsStyleRecalc() call below
+ // will skip MarkAncestorsWithChildNeedsStyleRecalc() if the node was
+ // already dirty.
MarkAncestorsWithChildNeedsStyleRecalc();
}
SetNeedsStyleRecalc(kLocalStyleChange,
diff --git a/chromium/third_party/blink/renderer/core/dom/node.h b/chromium/third_party/blink/renderer/core/dom/node.h
index 767e551efc4..087c2133f2c 100644
--- a/chromium/third_party/blink/renderer/core/dom/node.h
+++ b/chromium/third_party/blink/renderer/core/dom/node.h
@@ -109,7 +109,7 @@ enum class SlotChangeType {
kSuppressSlotChangeEvent,
};
-enum class CloneChildrenFlag { kClone, kSkip };
+enum class CloneChildrenFlag { kSkip, kClone, kCloneWithShadows };
// Whether or not to force creation of a legacy layout object (i.e. disallow
// LayoutNG).
@@ -660,7 +660,9 @@ class CORE_EXPORT Node : public EventTarget {
bool IsChildOfV0ShadowHost() const;
ShadowRoot* V1ShadowRootOfParent() const;
Element* FlatTreeParentForChildDirty() const;
- ContainerNode* GetStyleRecalcParent() const;
+ Element* GetStyleRecalcParent() const {
+ return FlatTreeParentForChildDirty();
+ }
Element* GetReattachParent() const { return FlatTreeParentForChildDirty(); }
bool IsDocumentTypeNode() const { return getNodeType() == kDocumentTypeNode; }
@@ -680,6 +682,8 @@ class CORE_EXPORT Node : public EventTarget {
// Whether or not a selection can be started in this object
virtual bool CanStartSelection() const;
+ void NotifyPriorityScrollAnchorStatusChanged();
+
// ---------------------------------------------------------------------------
// Integration with layout tree
@@ -842,7 +846,7 @@ class CORE_EXPORT Node : public EventTarget {
ShadowTreesTreatment = kTreatShadowTreesAsDisconnected) const;
const AtomicString& InterfaceName() const override;
- ExecutionContext* GetExecutionContext() const final;
+ ExecutionContext* GetExecutionContext() const override;
void RemoveAllEventListeners() override;
void RemoveAllEventListenersRecursively();
diff --git a/chromium/third_party/blink/renderer/core/dom/node_test.cc b/chromium/third_party/blink/renderer/core/dom/node_test.cc
index 96d805be445..5dcd17b6417 100644
--- a/chromium/third_party/blink/renderer/core/dom/node_test.cc
+++ b/chromium/third_party/blink/renderer/core/dom/node_test.cc
@@ -341,13 +341,10 @@ TEST_F(NodeTest, MutationOutsideFlatTreeStyleDirty) {
GetDocument()
.getElementById("nonslotted")
->setAttribute("style", "color:green");
- EXPECT_EQ(!RuntimeEnabledFeatures::FlatTreeStyleRecalcEnabled(),
- GetDocument().NeedsLayoutTreeUpdate());
+ EXPECT_FALSE(GetDocument().NeedsLayoutTreeUpdate());
}
TEST_F(NodeTest, SkipStyleDirtyHostChild) {
- ScopedFlatTreeStyleRecalcForTest scope(true);
-
SetBodyContent("<div id=host><span></span></div>");
Element* host = GetDocument().getElementById("host");
ShadowRoot& shadow_root =
@@ -406,8 +403,6 @@ TEST_F(NodeTest, SkipForceReattachDisplayNone) {
}
TEST_F(NodeTest, UpdateChildDirtyAncestorsOnSlotAssignment) {
- ScopedFlatTreeStyleRecalcForTest scope(true);
-
SetBodyContent("<div id=host><span></span></div>");
Element* host = GetDocument().getElementById("host");
ShadowRoot& shadow_root =
@@ -432,8 +427,6 @@ TEST_F(NodeTest, UpdateChildDirtyAncestorsOnSlotAssignment) {
}
TEST_F(NodeTest, UpdateChildDirtySlotAfterRemoval) {
- ScopedFlatTreeStyleRecalcForTest scope(true);
-
SetBodyContent("<div id=host><span></span></div>");
Element* host = GetDocument().getElementById("host");
ShadowRoot& shadow_root =
@@ -464,8 +457,6 @@ TEST_F(NodeTest, UpdateChildDirtySlotAfterRemoval) {
}
TEST_F(NodeTest, UpdateChildDirtyAfterSlotRemoval) {
- ScopedFlatTreeStyleRecalcForTest scope(true);
-
SetBodyContent("<div id=host><span></span></div>");
Element* host = GetDocument().getElementById("host");
ShadowRoot& shadow_root =
@@ -503,8 +494,6 @@ TEST_F(NodeTest, UpdateChildDirtyAfterSlotRemoval) {
}
TEST_F(NodeTest, UpdateChildDirtyAfterSlottingDirtyNode) {
- ScopedFlatTreeStyleRecalcForTest scope(true);
-
SetBodyContent("<div id=host><span></span></div>");
auto* host = GetDocument().getElementById("host");
@@ -534,8 +523,6 @@ TEST_F(NodeTest, UpdateChildDirtyAfterSlottingDirtyNode) {
}
TEST_F(NodeTest, ChildDirtyNeedsV0Distribution) {
- ScopedFlatTreeStyleRecalcForTest scope(true);
-
SetBodyContent("<div id=host><span></span> </div>");
ShadowRoot* shadow_root = CreateShadowRootForElementWithIDAndSetInnerHTML(
GetDocument(), "host", "<content />");
diff --git a/chromium/third_party/blink/renderer/core/dom/presentation_attribute_style.cc b/chromium/third_party/blink/renderer/core/dom/presentation_attribute_style.cc
index a6288ac75f7..4548e75a33a 100644
--- a/chromium/third_party/blink/renderer/core/dom/presentation_attribute_style.cc
+++ b/chromium/third_party/blink/renderer/core/dom/presentation_attribute_style.cc
@@ -33,14 +33,11 @@
#include <algorithm>
#include "base/macros.h"
-#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/core/css/css_property_value_set.h"
#include "third_party/blink/renderer/core/dom/attribute.h"
#include "third_party/blink/renderer/core/dom/element.h"
#include "third_party/blink/renderer/core/html/forms/html_input_element.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
-#include "third_party/blink/renderer/platform/scheduler/public/thread.h"
-#include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h"
#include "third_party/blink/renderer/platform/wtf/hash_functions.h"
#include "third_party/blink/renderer/platform/wtf/hash_map.h"
@@ -85,116 +82,103 @@ static bool AttributeNameSort(const std::pair<StringImpl*, AtomicString>& p1,
return p1.first < p2.first;
}
-static void MakePresentationAttributeCacheKey(
+static unsigned ComputePresentationAttributeCacheHash(
+ const PresentationAttributeCacheKey& key) {
+ DCHECK(key.tag_name);
+ DCHECK(key.attributes_and_values.size());
+ unsigned attribute_hash = StringHasher::HashMemory(
+ key.attributes_and_values.data(),
+ key.attributes_and_values.size() * sizeof(key.attributes_and_values[0]));
+ return WTF::HashInts(key.tag_name->ExistingHash(), attribute_hash);
+}
+
+static unsigned MakePresentationAttributeCacheKey(
Element& element,
PresentationAttributeCacheKey& result) {
// FIXME: Enable for SVG.
if (!element.IsHTMLElement())
- return;
+ return 0;
// Interpretation of the size attributes on <input> depends on the type
// attribute.
if (IsA<HTMLInputElement>(element))
- return;
+ return 0;
AttributeCollection attributes = element.AttributesWithoutUpdate();
for (const Attribute& attr : attributes) {
if (!element.IsPresentationAttribute(attr.GetName()))
continue;
if (!attr.NamespaceURI().IsNull())
- return;
+ return 0;
// FIXME: Background URL may depend on the base URL and can't be shared.
// Disallow caching.
if (attr.GetName() == html_names::kBackgroundAttr)
- return;
+ return 0;
result.attributes_and_values.push_back(
std::make_pair(attr.LocalName().Impl(), attr.Value()));
}
if (result.attributes_and_values.IsEmpty())
- return;
+ return 0;
// Attribute order doesn't matter. Sort for easy equality comparison.
std::sort(result.attributes_and_values.begin(),
result.attributes_and_values.end(), AttributeNameSort);
// The cache key is non-null when the tagName is set.
result.tag_name = element.localName().Impl();
-}
-
-static unsigned ComputePresentationAttributeCacheHash(
- const PresentationAttributeCacheKey& key) {
- if (!key.tag_name)
- return 0;
- DCHECK(key.attributes_and_values.size());
- unsigned attribute_hash = StringHasher::HashMemory(
- key.attributes_and_values.data(),
- key.attributes_and_values.size() * sizeof(key.attributes_and_values[0]));
- return WTF::HashInts(key.tag_name->ExistingHash(), attribute_hash);
+ return ComputePresentationAttributeCacheHash(result);
}
CSSPropertyValueSet* ComputePresentationAttributeStyle(Element& element) {
DCHECK(element.IsStyledElement());
PresentationAttributeCacheKey cache_key;
- MakePresentationAttributeCacheKey(element, cache_key);
-
- unsigned cache_hash = ComputePresentationAttributeCacheHash(cache_key);
+ unsigned cache_hash = MakePresentationAttributeCacheKey(element, cache_key);
PresentationAttributeCache::ValueType* cache_value;
-
+ PresentationAttributeCache& cache = GetPresentationAttributeCache();
if (cache_hash) {
- cache_value = GetPresentationAttributeCache()
- .insert(cache_hash, nullptr)
- .stored_value;
+ cache_value = cache.insert(cache_hash, nullptr).stored_value;
if (cache_value->value && cache_value->value->key != cache_key)
cache_hash = 0;
} else {
cache_value = nullptr;
}
- // Keep the entry value of |cache_value| here in order to assure that the
- // value lives when it is used. Without this keeping, calling
- // |GetPresentationAttributeCache().clear()| destroys |cache_value->value| and
- // causes use-after-poison (crbug.com/810368).
- PresentationAttributeCacheEntry* entry = nullptr;
- if (cache_value)
- entry = cache_value->value;
-
- CSSPropertyValueSet* style = nullptr;
+ // The element can be cached (has non-zero hash) and has an entry in the
+ // cache. Hit.
if (cache_hash && cache_value->value) {
- style = cache_value->value->value;
+ // Reference the property set, since if we clean the cache below it may
+ // disappear.
+ CSSPropertyValueSet* style = cache_value->value->value;
static const unsigned kMinimumPresentationAttributeCacheSizeForCleaning =
100;
- if (GetPresentationAttributeCache().size() >=
- kMinimumPresentationAttributeCacheSizeForCleaning) {
- GetPresentationAttributeCache().clear();
- }
- } else {
- style = MakeGarbageCollected<MutableCSSPropertyValueSet>(
- element.IsSVGElement() ? kSVGAttributeMode : kHTMLStandardMode);
- AttributeCollection attributes = element.AttributesWithoutUpdate();
- for (const Attribute& attr : attributes) {
- element.CollectStyleForPresentationAttribute(
- attr.GetName(), attr.Value(), To<MutableCSSPropertyValueSet>(style));
- }
+ if (cache.size() >= kMinimumPresentationAttributeCacheSizeForCleaning)
+ cache.clear();
+ return style;
}
- if (!cache_hash || entry)
+ // No entry in the cache or cannot be cached. Miss. Create a new property set.
+ CSSPropertyValueSet* style = element.CreatePresentationAttributeStyle();
+
+ // Cannot be cached, so return without inserting into cache.
+ if (!cache_hash)
return style;
- PresentationAttributeCacheEntry* new_entry =
- MakeGarbageCollected<PresentationAttributeCacheEntry>();
+ // Have an unpopulated cached entry.
+ DCHECK(cache_value);
+ DCHECK(!cache_value->value);
+
+ auto* new_entry = MakeGarbageCollected<PresentationAttributeCacheEntry>();
new_entry->key = cache_key;
new_entry->value = style;
static const unsigned kPresentationAttributeCacheMaximumSize = 4096;
- if (GetPresentationAttributeCache().size() >
- kPresentationAttributeCacheMaximumSize) {
+ if (cache.size() > kPresentationAttributeCacheMaximumSize) {
// FIXME: Discarding the entire cache when it gets too big is probably bad
// since it creates a perf "cliff". Perhaps we should use an LRU?
- GetPresentationAttributeCache().clear();
- GetPresentationAttributeCache().Set(cache_hash, new_entry);
+ cache.clear();
+ cache.Set(cache_hash, new_entry);
} else {
cache_value->value = new_entry;
}
-
return style;
}
diff --git a/chromium/third_party/blink/renderer/core/dom/presentation_attribute_style.h b/chromium/third_party/blink/renderer/core/dom/presentation_attribute_style.h
index 1b2a6145f2c..e0b0db125f4 100644
--- a/chromium/third_party/blink/renderer/core/dom/presentation_attribute_style.h
+++ b/chromium/third_party/blink/renderer/core/dom/presentation_attribute_style.h
@@ -31,8 +31,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_DOM_PRESENTATION_ATTRIBUTE_STYLE_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_PRESENTATION_ATTRIBUTE_STYLE_H_
-#include "third_party/blink/renderer/platform/heap/handle.h"
-
namespace blink {
class Element;
diff --git a/chromium/third_party/blink/renderer/core/dom/processing_instruction.cc b/chromium/third_party/blink/renderer/core/dom/processing_instruction.cc
index be5780126f8..7dbe5566bec 100644
--- a/chromium/third_party/blink/renderer/core/dom/processing_instruction.cc
+++ b/chromium/third_party/blink/renderer/core/dom/processing_instruction.cc
@@ -207,6 +207,8 @@ void ProcessingInstruction::NotifyFinished(Resource* resource) {
GetDocument(), style_resource->GetResponse().ResponseUrl(),
style_resource->GetResponse().IsCorsSameOrigin(),
style_resource->GetReferrerPolicy(), style_resource->Encoding());
+ if (style_resource->GetResourceRequest().IsAdResource())
+ parser_context->SetIsAdRelated();
auto* new_sheet = MakeGarbageCollected<StyleSheetContents>(
parser_context, style_resource->Url());
diff --git a/chromium/third_party/blink/renderer/core/dom/scripted_idle_task_controller.cc b/chromium/third_party/blink/renderer/core/dom/scripted_idle_task_controller.cc
index 760c696f452..16323896e32 100644
--- a/chromium/third_party/blink/renderer/core/dom/scripted_idle_task_controller.cc
+++ b/chromium/third_party/blink/renderer/core/dom/scripted_idle_task_controller.cc
@@ -11,7 +11,6 @@
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/inspector/inspector_trace_events.h"
#include "third_party/blink/renderer/core/probe/core_probes.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/thread_scheduler.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"
@@ -121,10 +120,8 @@ ScriptedIdleTaskController::RegisterCallback(
DCHECK(idle_task);
CallbackId id = NextCallbackId();
- base::TimeTicks queue_timestamp = base::TimeTicks::Now();
+ idle_tasks_.Set(id, idle_task);
uint32_t timeout_millis = options->timeout();
- idle_tasks_.Set(id, MakeGarbageCollected<QueuedIdleTask>(
- idle_task, queue_timestamp, timeout_millis));
probe::AsyncTaskScheduled(GetExecutionContext(), "requestIdleCallback",
idle_task->async_task_id());
@@ -199,13 +196,11 @@ void ScriptedIdleTaskController::RunCallback(
auto idle_task_iter = idle_tasks_.find(id);
if (idle_task_iter == idle_tasks_.end())
return;
- QueuedIdleTask* queued_idle_task = idle_task_iter->value;
- DCHECK(queued_idle_task);
- IdleTask* idle_task = queued_idle_task->task();
+ IdleTask* idle_task = idle_task_iter->value;
DCHECK(idle_task);
- base::TimeTicks now = base::TimeTicks::Now();
- base::TimeDelta allotted_time = std::max(deadline - now, base::TimeDelta());
+ base::TimeDelta allotted_time =
+ std::max(deadline - base::TimeTicks::Now(), base::TimeDelta());
probe::AsyncTask async_task(GetExecutionContext(),
idle_task->async_task_id());
@@ -220,8 +215,6 @@ void ScriptedIdleTaskController::RunCallback(
idle_task->invoke(
MakeGarbageCollected<IdleDeadline>(deadline, callback_type));
- RecordIdleTaskMetrics(queued_idle_task, now, callback_type);
-
// Finally there is no need to keep the idle task alive.
//
// Do not use the iterator because the idle task might update |idle_tasks_|.
@@ -266,38 +259,4 @@ void ScriptedIdleTaskController::ContextUnpaused() {
}
}
-void ScriptedIdleTaskController::RecordIdleTaskMetrics(
- QueuedIdleTask* queued_idle_task,
- base::TimeTicks run_timestamp,
- IdleDeadline::CallbackType callback_type) {
- UMA_HISTOGRAM_ENUMERATION(
- "WebCore.ScriptedIdleTaskController.IdleTaskCallbackType", callback_type);
- UMA_HISTOGRAM_COUNTS_100000(
- "WebCore.ScriptedIdleTaskController.IdleTaskTimeout",
- queued_idle_task->timeout_millis());
- if (callback_type == IdleDeadline::CallbackType::kCalledWhenIdle) {
- DCHECK_GE(run_timestamp, queued_idle_task->queue_timestamp());
- UMA_HISTOGRAM_MEDIUM_TIMES(
- "WebCore.ScriptedIdleTaskController.IdleTaskQueueingTime",
- run_timestamp - queued_idle_task->queue_timestamp());
- }
- if (callback_type == IdleDeadline::CallbackType::kCalledByTimeout) {
- UMA_HISTOGRAM_COUNTS_100000(
- "WebCore.ScriptedIdleTaskController.IdleTaskTimeoutExceeded",
- queued_idle_task->timeout_millis());
- }
-}
-
-ScriptedIdleTaskController::QueuedIdleTask::QueuedIdleTask(
- IdleTask* idle_task,
- base::TimeTicks queue_timestamp,
- uint32_t timeout_millis)
- : task_(idle_task),
- queue_timestamp_(queue_timestamp),
- timeout_millis_(timeout_millis) {}
-
-void ScriptedIdleTaskController::QueuedIdleTask::Trace(Visitor* visitor) {
- visitor->Trace(task_);
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/dom/scripted_idle_task_controller.h b/chromium/third_party/blink/renderer/core/dom/scripted_idle_task_controller.h
index c13fe650ed9..82a8edee323 100644
--- a/chromium/third_party/blink/renderer/core/dom/scripted_idle_task_controller.h
+++ b/chromium/third_party/blink/renderer/core/dom/scripted_idle_task_controller.h
@@ -91,25 +91,6 @@ class CORE_EXPORT ScriptedIdleTaskController
IdleDeadline::CallbackType);
private:
- class QueuedIdleTask : public GarbageCollected<QueuedIdleTask> {
- public:
- QueuedIdleTask(IdleTask*,
- base::TimeTicks queue_timestamp,
- uint32_t timeout_millis);
- virtual ~QueuedIdleTask() = default;
-
- virtual void Trace(Visitor*);
-
- IdleTask* task() { return task_; }
- base::TimeTicks queue_timestamp() const { return queue_timestamp_; }
- uint32_t timeout_millis() const { return timeout_millis_; }
-
- private:
- Member<IdleTask> task_;
- base::TimeTicks queue_timestamp_;
- uint32_t timeout_millis_;
- };
-
friend class internal::IdleRequestCallbackWrapper;
void ContextPaused();
@@ -129,12 +110,8 @@ class CORE_EXPORT ScriptedIdleTaskController
base::TimeTicks deadline,
IdleDeadline::CallbackType);
- void RecordIdleTaskMetrics(QueuedIdleTask*,
- base::TimeTicks run_timestamp,
- IdleDeadline::CallbackType);
-
ThreadScheduler* scheduler_; // Not owned.
- HeapHashMap<CallbackId, Member<QueuedIdleTask>> idle_tasks_;
+ HeapHashMap<CallbackId, Member<IdleTask>> idle_tasks_;
Vector<CallbackId> pending_timeouts_;
CallbackId next_callback_id_;
bool paused_;
diff --git a/chromium/third_party/blink/renderer/core/dom/shadow_root.cc b/chromium/third_party/blink/renderer/core/dom/shadow_root.cc
index 215a8af0e76..230773200bf 100644
--- a/chromium/third_party/blink/renderer/core/dom/shadow_root.cc
+++ b/chromium/third_party/blink/renderer/core/dom/shadow_root.cc
@@ -124,23 +124,6 @@ void ShadowRoot::setInnerHTML(const String& markup,
ReplaceChildrenWithFragment(this, fragment, exception_state);
}
-void ShadowRoot::RecalcStyle(const StyleRecalcChange change) {
- // ShadowRoot doesn't support custom callbacks.
- DCHECK(!HasCustomStyleCallbacks());
- DCHECK(!RuntimeEnabledFeatures::FlatTreeStyleRecalcEnabled());
-
- StyleRecalcChange child_change = change;
- if (GetStyleChangeType() == kSubtreeStyleChange)
- child_change = child_change.ForceRecalcDescendants();
-
- // There's no style to update so just calling RecalcStyle means we're updated.
- ClearNeedsStyleRecalc();
-
- if (child_change.TraverseChildren(*this))
- RecalcDescendantStyles(child_change);
- ClearChildNeedsStyleRecalc();
-}
-
void ShadowRoot::RebuildLayoutTree(WhitespaceAttacher& whitespace_attacher) {
DCHECK(!NeedsReattachLayoutTree());
DCHECK(!ChildNeedsReattachLayoutTree());
diff --git a/chromium/third_party/blink/renderer/core/dom/shadow_root.h b/chromium/third_party/blink/renderer/core/dom/shadow_root.h
index 7a0290d0790..3ace8451c73 100644
--- a/chromium/third_party/blink/renderer/core/dom/shadow_root.h
+++ b/chromium/third_party/blink/renderer/core/dom/shadow_root.h
@@ -46,10 +46,6 @@ class WhitespaceAttacher;
enum class ShadowRootType { V0, kOpen, kClosed, kUserAgent };
-enum class SlotAssignmentMode { kManual, kAuto };
-
-enum class FocusDelegation { kNone, kDelegateFocus };
-
class CORE_EXPORT ShadowRoot final : public DocumentFragment, public TreeScope {
DEFINE_WRAPPERTYPEINFO();
USING_GARBAGE_COLLECTED_MIXIN(ShadowRoot);
@@ -114,7 +110,6 @@ class CORE_EXPORT ShadowRoot final : public DocumentFragment, public TreeScope {
// For Internals, don't use this.
unsigned ChildShadowRootCount() const { return child_shadow_root_count_; }
- void RecalcStyle(const StyleRecalcChange);
void RebuildLayoutTree(WhitespaceAttacher&);
void RegisterScopedHTMLStyleChild();
@@ -160,6 +155,13 @@ class CORE_EXPORT ShadowRoot final : public DocumentFragment, public TreeScope {
return IsManualSlotting() ? "manual" : "auto";
}
+ void SetIsDeclarativeShadowRoot(bool flag) {
+ DCHECK(!flag || GetType() == ShadowRootType::kOpen ||
+ GetType() == ShadowRootType::kClosed);
+ is_declarative_shadow_root_ = flag;
+ }
+ bool IsDeclarativeShadowRoot() const { return is_declarative_shadow_root_; }
+
bool ContainsShadowRoots() const { return child_shadow_root_count_; }
StyleSheetList& StyleSheets();
@@ -191,8 +193,9 @@ class CORE_EXPORT ShadowRoot final : public DocumentFragment, public TreeScope {
unsigned registered_with_parent_shadow_root_ : 1;
unsigned delegates_focus_ : 1;
unsigned slot_assignment_mode_ : 1;
+ unsigned is_declarative_shadow_root_ : 1;
unsigned needs_distribution_recalc_ : 1;
- unsigned unused_ : 10;
+ unsigned unused_ : 9;
DISALLOW_COPY_AND_ASSIGN(ShadowRoot);
};
diff --git a/chromium/third_party/blink/renderer/core/dom/shadow_root_v0.cc b/chromium/third_party/blink/renderer/core/dom/shadow_root_v0.cc
index 82ba28b1b39..bed947c0bd9 100644
--- a/chromium/third_party/blink/renderer/core/dom/shadow_root_v0.cc
+++ b/chromium/third_party/blink/renderer/core/dom/shadow_root_v0.cc
@@ -148,10 +148,10 @@ const V0InsertionPoint* ShadowRootV0::FinalDestinationInsertionPointFor(
#if DCHECK_IS_ON()
DCHECK(key);
// Allow traversal without V0 distribution up-to-date for marking ancestors
- // with ChildNeedsStyleRecalc() when FlatTreeStyleRecalc is enabled.
+ // with ChildNeedsStyleRecalc() for marking ancestors with child-needs-style-
+ // recalc on a tree with a dirty distribution.
DCHECK(!key->NeedsDistributionRecalc() ||
- RuntimeEnabledFeatures::FlatTreeStyleRecalcEnabled() &&
- key->GetDocument().AllowDirtyShadowV0Traversal());
+ key->GetDocument().AllowDirtyShadowV0Traversal());
#endif
NodeToDestinationInsertionPoints::const_iterator it =
node_to_insertion_points_.find(key);
diff --git a/chromium/third_party/blink/renderer/core/dom/slot_assignment.cc b/chromium/third_party/blink/renderer/core/dom/slot_assignment.cc
index d8dbcc1b5a2..833615ffc61 100644
--- a/chromium/third_party/blink/renderer/core/dom/slot_assignment.cc
+++ b/chromium/third_party/blink/renderer/core/dom/slot_assignment.cc
@@ -17,6 +17,7 @@
#include "third_party/blink/renderer/core/html/html_details_element.h"
#include "third_party/blink/renderer/core/html/html_slot_element.h"
#include "third_party/blink/renderer/core/html/parser/nesting_level_incrementer.h"
+#include "third_party/blink/renderer/core/inspector/console_message.h"
namespace blink {
@@ -43,7 +44,7 @@ void SlotAssignment::DidAddSlot(HTMLSlotElement& slot) {
needs_collect_slots_ = true;
if (owner_->IsManualSlotting()) {
- SetNeedsAssignmentRecalc();
+ // Adding a new slot should not require assignment recalc.
return;
}
@@ -66,7 +67,13 @@ void SlotAssignment::DidRemoveSlot(HTMLSlotElement& slot) {
needs_collect_slots_ = true;
if (owner_->IsManualSlotting()) {
- SetNeedsAssignmentRecalc();
+ auto& candidates = slot.AssignedNodesCandidates();
+ if (candidates.size()) {
+ ClearCandidateNodes(candidates);
+ slot.ClearAssignedNodesCandidates();
+ SetNeedsAssignmentRecalc();
+ slot.DidSlotChangeAfterRemovedFromShadowTree();
+ }
return;
}
@@ -259,17 +266,36 @@ void SlotAssignment::RecalcAssignment() {
FindSlotByName(HTMLSlotElement::UserAgentCustomAssignSlotName());
}
+ bool is_manual_slot_assignment = owner_->IsManualSlotting();
+ // Replaces candidate_assigned_slot_map_ after the loop, to avoid stale
+ // references resulting from calls to slot->DidRecalcAssignedNodes().
+ HeapHashMap<Member<Node>, Member<HTMLSlotElement>> candidate_map;
+
for (Node& child : NodeTraversal::ChildrenOf(owner_->host())) {
if (!child.IsSlotable())
continue;
HTMLSlotElement* slot = nullptr;
if (!is_user_agent) {
- if (owner_->IsManualSlotting()) {
- for (auto candidate_slot : Slots()) {
- if (candidate_slot->AssignedNodesCandidate().Contains(&child)) {
+ if (is_manual_slot_assignment) {
+ if (auto* candidate_slot = candidate_assigned_slot_map_.at(&child)) {
+ if (candidate_slot->ContainingShadowRoot() == owner_) {
slot = candidate_slot;
- break;
+ } else {
+ candidate_assigned_slot_map_.erase(&child);
+ const AtomicString& slot_name =
+ (candidate_slot->GetName() != g_empty_atom)
+ ? candidate_slot->GetName()
+ : "SLOT";
+ owner_->GetDocument().AddConsoleMessage(
+ MakeGarbageCollected<ConsoleMessage>(
+ mojom::blink::ConsoleMessageSource::kRendering,
+ mojom::blink::ConsoleMessageLevel::kWarning,
+ "This code triggered a slot assignment recalculation. At "
+ "the time of this recalculation, the assigned node '" +
+ child.nodeName() + "' was no longer a child of '" +
+ slot_name +
+ "'s parent shadow host, so it could not be assigned."));
}
}
} else {
@@ -285,6 +311,8 @@ void SlotAssignment::RecalcAssignment() {
if (slot) {
slot->AppendAssignedNode(child);
+ if (is_manual_slot_assignment)
+ candidate_map.Set(&child, slot);
} else {
child.ClearFlatTreeNodeData();
child.RemovedFromFlatTree();
@@ -299,6 +327,9 @@ void SlotAssignment::RecalcAssignment() {
for (auto& slot : Slots())
slot->DidRecalcAssignedNodes();
+
+ if (is_manual_slot_assignment)
+ candidate_assigned_slot_map_.swap(candidate_map);
}
const HeapVector<Member<HTMLSlotElement>>& SlotAssignment::Slots() {
@@ -334,10 +365,10 @@ HTMLSlotElement* SlotAssignment::FindSlotInUserAgentShadow(
}
HTMLSlotElement* SlotAssignment::FindSlotInManualSlotting(const Node& node) {
- for (auto& slot : Slots()) {
- if (slot->AssignedNodesCandidate().Contains(const_cast<Node*>(&node)))
- return slot;
- }
+ auto* slot = candidate_assigned_slot_map_.at(const_cast<Node*>(&node));
+ if (slot && slot->ContainingShadowRoot() == owner_)
+ return slot;
+
return nullptr;
}
@@ -363,10 +394,29 @@ HTMLSlotElement* SlotAssignment::GetCachedFirstSlotWithoutAccessingNodeTree(
return nullptr;
}
+bool SlotAssignment::UpdateCandidateNodeAssignedSlot(Node& node,
+ HTMLSlotElement& slot) {
+ bool updated = false;
+ auto* prev_slot = candidate_assigned_slot_map_.at(&node);
+ if (prev_slot && prev_slot != &slot) {
+ prev_slot->RemoveAssignedNodeCandidate(node);
+ updated = true;
+ }
+
+ candidate_assigned_slot_map_.Set(&node, &slot);
+ return updated;
+}
+
+void SlotAssignment::ClearCandidateNodes(
+ const HeapLinkedHashSet<Member<Node>>& candidates) {
+ candidate_assigned_slot_map_.RemoveAll(candidates);
+}
+
void SlotAssignment::Trace(Visitor* visitor) {
visitor->Trace(slots_);
visitor->Trace(slot_map_);
visitor->Trace(owner_);
+ visitor->Trace(candidate_assigned_slot_map_);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/dom/slot_assignment.h b/chromium/third_party/blink/renderer/core/dom/slot_assignment.h
index 5be3fe49259..1a507643eb2 100644
--- a/chromium/third_party/blink/renderer/core/dom/slot_assignment.h
+++ b/chromium/third_party/blink/renderer/core/dom/slot_assignment.h
@@ -49,13 +49,13 @@ class SlotAssignment final : public GarbageCollected<SlotAssignment> {
void CallSlotChangeAfterRemoved(HTMLSlotElement& slot);
void CallSlotChangeIfNeeded(HTMLSlotElement& slot, Node& child);
- HTMLSlotElement* FindSlotChange(HTMLSlotElement& slot, Node& child);
-
void Trace(Visitor*);
bool NeedsAssignmentRecalc() const { return needs_assignment_recalc_; }
void SetNeedsAssignmentRecalc();
void RecalcAssignment();
+ bool UpdateCandidateNodeAssignedSlot(Node&, HTMLSlotElement&);
+ void ClearCandidateNodes(const HeapLinkedHashSet<Member<Node>>& candidates);
private:
enum class SlotMutationType {
@@ -81,6 +81,9 @@ class SlotAssignment final : public GarbageCollected<SlotAssignment> {
unsigned needs_collect_slots_ : 1;
unsigned needs_assignment_recalc_ : 1;
unsigned slot_count_ : 30;
+ // TODO: (1067157) Ensure references inside the map are GCed.
+ HeapHashMap<Member<Node>, Member<HTMLSlotElement>>
+ candidate_assigned_slot_map_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/dom/text_link_colors.cc b/chromium/third_party/blink/renderer/core/dom/text_link_colors.cc
index df6d9db255c..9fd69e7280a 100644
--- a/chromium/third_party/blink/renderer/core/dom/text_link_colors.cc
+++ b/chromium/third_party/blink/renderer/core/dom/text_link_colors.cc
@@ -31,7 +31,7 @@
#include "third_party/blink/renderer/core/css/css_color_value.h"
#include "third_party/blink/renderer/core/css/css_identifier_value.h"
-#include "third_party/blink/renderer/core/css/css_light_dark_color_pair.h"
+#include "third_party/blink/renderer/core/css/css_light_dark_value_pair.h"
#include "third_party/blink/renderer/core/css/style_color.h"
#include "third_party/blink/renderer/core/layout/layout_theme.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
@@ -63,7 +63,7 @@ Color TextLinkColors::ColorFromCSSValue(const CSSValue& value,
if (auto* color_value = DynamicTo<cssvalue::CSSColorValue>(value))
return color_value->Value();
- if (auto* pair = DynamicTo<CSSLightDarkColorPair>(value)) {
+ if (auto* pair = DynamicTo<CSSLightDarkValuePair>(value)) {
const CSSValue& color_value =
color_scheme == WebColorScheme::kLight ? pair->First() : pair->Second();
return ColorFromCSSValue(color_value, current_color, color_scheme,
diff --git a/chromium/third_party/blink/renderer/core/dom/v0_insertion_point.cc b/chromium/third_party/blink/renderer/core/dom/v0_insertion_point.cc
index b0a904af877..3e92ef8c5d3 100644
--- a/chromium/third_party/blink/renderer/core/dom/v0_insertion_point.cc
+++ b/chromium/third_party/blink/renderer/core/dom/v0_insertion_point.cc
@@ -46,8 +46,6 @@ V0InsertionPoint::V0InsertionPoint(const QualifiedName& tag_name,
Document& document)
: HTMLElement(tag_name, document, kCreateV0InsertionPoint),
registered_with_shadow_root_(false) {
- if (!RuntimeEnabledFeatures::FlatTreeStyleRecalcEnabled())
- SetHasCustomStyleCallbacks();
}
V0InsertionPoint::~V0InsertionPoint() = default;
@@ -138,31 +136,8 @@ void V0InsertionPoint::RebuildDistributedChildrenLayoutTrees(
}
}
-void V0InsertionPoint::DidRecalcStyle(const StyleRecalcChange change) {
- DCHECK(!RuntimeEnabledFeatures::FlatTreeStyleRecalcEnabled());
- if (DistributedNodesAreFallback()) {
- // Fallback children have already been recalculated in
- // ContainerNode::RecalcDescendantStyles().
- return;
- }
-
- for (wtf_size_t i = 0; i < distributed_nodes_.size(); ++i) {
- Node* node = distributed_nodes_.at(i);
- if (!change.TraverseChild(*node))
- continue;
- if (auto* this_element = DynamicTo<Element>(node))
- this_element->RecalcStyle(change);
- else if (auto* text_node = DynamicTo<Text>(node))
- text_node->RecalcTextStyle(change);
- }
-}
-
void V0InsertionPoint::RecalcStyleForInsertionPointChildren(
const StyleRecalcChange change) {
- if (!RuntimeEnabledFeatures::FlatTreeStyleRecalcEnabled()) {
- RecalcDescendantStyles(change);
- return;
- }
for (wtf_size_t i = 0; i < distributed_nodes_.size(); ++i) {
Node* node = distributed_nodes_.at(i);
if (!change.TraverseChild(*node))
diff --git a/chromium/third_party/blink/renderer/core/dom/v0_insertion_point.h b/chromium/third_party/blink/renderer/core/dom/v0_insertion_point.h
index a4883c2a65e..a5c14c426b1 100644
--- a/chromium/third_party/blink/renderer/core/dom/v0_insertion_point.h
+++ b/chromium/third_party/blink/renderer/core/dom/v0_insertion_point.h
@@ -91,7 +91,6 @@ class CORE_EXPORT V0InsertionPoint : public HTMLElement {
void ChildrenChanged(const ChildrenChange&) override;
InsertionNotificationRequest InsertedInto(ContainerNode&) override;
void RemovedFrom(ContainerNode&) override;
- void DidRecalcStyle(const StyleRecalcChange) override;
private:
bool IsV0InsertionPoint() const =
diff --git a/chromium/third_party/blink/renderer/core/editing/commands/apply_style_command.cc b/chromium/third_party/blink/renderer/core/editing/commands/apply_style_command.cc
index cd6d78a27bc..351fcdabeee 100644
--- a/chromium/third_party/blink/renderer/core/editing/commands/apply_style_command.cc
+++ b/chromium/third_party/blink/renderer/core/editing/commands/apply_style_command.cc
@@ -217,7 +217,7 @@ void ApplyStyleCommand::DoApply(EditingState* editing_state) {
case kPropertyDefault: {
// Apply the block-centric properties of the style.
EditingStyle* block_style = style_->ExtractAndRemoveBlockProperties(
- GetDocument().ToExecutionContext());
+ GetDocument().GetExecutionContext());
if (!block_style->IsEmpty()) {
ApplyBlockStyle(block_style, editing_state);
if (editing_state->IsAborted())
diff --git a/chromium/third_party/blink/renderer/core/editing/commands/composite_edit_command.cc b/chromium/third_party/blink/renderer/core/editing/commands/composite_edit_command.cc
index a665fe43804..c7e9e877fd1 100644
--- a/chromium/third_party/blink/renderer/core/editing/commands/composite_edit_command.cc
+++ b/chromium/third_party/blink/renderer/core/editing/commands/composite_edit_command.cc
@@ -1519,7 +1519,7 @@ void CompositeEditCommand::MoveParagraphs(
style_in_empty_paragraph->MergeTypingStyle(&GetDocument());
// The moved paragraph should assume the block style of the destination.
style_in_empty_paragraph->RemoveBlockProperties(
- GetDocument().ToExecutionContext());
+ GetDocument().GetExecutionContext());
}
// FIXME (5098931): We should add a new insert action
diff --git a/chromium/third_party/blink/renderer/core/editing/commands/insert_text_command.cc b/chromium/third_party/blink/renderer/core/editing/commands/insert_text_command.cc
index d59c6167bf5..199f59516de 100644
--- a/chromium/third_party/blink/renderer/core/editing/commands/insert_text_command.cc
+++ b/chromium/third_party/blink/renderer/core/editing/commands/insert_text_command.cc
@@ -173,8 +173,10 @@ void InsertTextCommand::DoApply(EditingState* editing_state) {
return;
if (end_of_selection_was_at_start_of_block) {
if (EditingStyle* typing_style =
- GetDocument().GetFrame()->GetEditor().TypingStyle())
- typing_style->RemoveBlockProperties(GetDocument().ToExecutionContext());
+ GetDocument().GetFrame()->GetEditor().TypingStyle()) {
+ typing_style->RemoveBlockProperties(
+ GetDocument().GetExecutionContext());
+ }
}
} else if (GetDocument().GetFrame()->GetEditor().IsOverwriteModeEnabled()) {
if (PerformOverwrite(text_))
diff --git a/chromium/third_party/blink/renderer/core/editing/commands/style_commands.cc b/chromium/third_party/blink/renderer/core/editing/commands/style_commands.cc
index 7d1900ad7a3..6ba5f3a5fb3 100644
--- a/chromium/third_party/blink/renderer/core/editing/commands/style_commands.cc
+++ b/chromium/third_party/blink/renderer/core/editing/commands/style_commands.cc
@@ -45,6 +45,7 @@
#include "third_party/blink/renderer/core/editing/frame_selection.h"
#include "third_party/blink/renderer/core/editing/visible_position.h"
#include "third_party/blink/renderer/core/editing/writing_direction.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/html/html_font_element.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
@@ -216,9 +217,9 @@ bool StyleCommands::SelectionStartHasStyle(LocalFrame& frame,
frame.Selection().ComputeVisibleSelectionInDOMTreeDeprecated(),
property_id == CSSPropertyID::kBackgroundColor,
style_to_check->Style());
- return style_to_check->TriStateOfStyle(
- frame.GetDocument()->ToExecutionContext(), style_at_start,
- secure_context_mode) != EditingTriState::kFalse;
+ return style_to_check->TriStateOfStyle(frame.DomWindow(), style_at_start,
+ secure_context_mode) !=
+ EditingTriState::kFalse;
}
bool StyleCommands::ExecuteToggleStyle(LocalFrame& frame,
diff --git a/chromium/third_party/blink/renderer/core/editing/dom_selection.cc b/chromium/third_party/blink/renderer/core/editing/dom_selection.cc
index 5c6960cbb03..c690a203b05 100644
--- a/chromium/third_party/blink/renderer/core/editing/dom_selection.cc
+++ b/chromium/third_party/blink/renderer/core/editing/dom_selection.cc
@@ -96,7 +96,7 @@ void DOMSelection::UpdateFrameSelection(
if (!did_set)
return;
Element* focused_element = GetFrame()->GetDocument()->FocusedElement();
- frame_selection.DidSetSelectionDeprecated(options);
+ frame_selection.DidSetSelectionDeprecated(selection, options);
if (GetFrame() && GetFrame()->GetDocument() &&
focused_element != GetFrame()->GetDocument()->FocusedElement()) {
UseCounter::Count(GetFrame()->GetDocument(),
diff --git a/chromium/third_party/blink/renderer/core/editing/editing_behavior.cc b/chromium/third_party/blink/renderer/core/editing/editing_behavior.cc
index b10407a84d6..397d8185e54 100644
--- a/chromium/third_party/blink/renderer/core/editing/editing_behavior.cc
+++ b/chromium/third_party/blink/renderer/core/editing/editing_behavior.cc
@@ -236,7 +236,7 @@ const char* EditingBehavior::InterpretKeyEvent(
unsigned modifiers =
key_event->GetModifiers() & (kShiftKey | kAltKey | kCtrlKey | kMetaKey);
- if (key_event->GetType() == WebInputEvent::kRawKeyDown) {
+ if (key_event->GetType() == WebInputEvent::Type::kRawKeyDown) {
int map_key = modifiers << 16 | event.keyCode();
const char* name = map_key ? key_down_commands_map->at(map_key) : nullptr;
if (!name)
diff --git a/chromium/third_party/blink/renderer/core/editing/editing_style.cc b/chromium/third_party/blink/renderer/core/editing/editing_style.cc
index 2a3acb5cf40..dcc0eeebd82 100644
--- a/chromium/third_party/blink/renderer/core/editing/editing_style.cc
+++ b/chromium/third_party/blink/renderer/core/editing/editing_style.cc
@@ -510,9 +510,8 @@ void EditingStyle::Init(Node* node, PropertiesToInclude properties_to_include) {
mutable_style_ =
properties_to_include == kAllProperties && computed_style_at_position
? computed_style_at_position->CopyProperties()
- : CopyEditingProperties(
- node ? node->GetDocument().ToExecutionContext() : nullptr,
- computed_style_at_position);
+ : CopyEditingProperties(node ? node->GetExecutionContext() : nullptr,
+ computed_style_at_position);
if (properties_to_include == kEditingPropertiesInEffect) {
if (const CSSValue* value =
@@ -767,11 +766,11 @@ void EditingStyle::RemoveStyleAddedByElement(Element* element) {
if (!element || !element->parentNode())
return;
MutableCSSPropertyValueSet* parent_style = CopyEditingProperties(
- element->parentNode()->GetDocument().ToExecutionContext(),
+ element->parentNode()->GetExecutionContext(),
MakeGarbageCollected<CSSComputedStyleDeclaration>(element->parentNode()),
kAllEditingProperties);
MutableCSSPropertyValueSet* node_style = CopyEditingProperties(
- element->GetDocument().ToExecutionContext(),
+ element->GetExecutionContext(),
MakeGarbageCollected<CSSComputedStyleDeclaration>(element),
kAllEditingProperties);
node_style->RemoveEquivalentProperties(parent_style);
@@ -783,11 +782,11 @@ void EditingStyle::RemoveStyleConflictingWithStyleOfElement(Element* element) {
return;
MutableCSSPropertyValueSet* parent_style = CopyEditingProperties(
- element->parentNode()->GetDocument().ToExecutionContext(),
+ element->parentNode()->GetExecutionContext(),
MakeGarbageCollected<CSSComputedStyleDeclaration>(element->parentNode()),
kAllEditingProperties);
MutableCSSPropertyValueSet* node_style = CopyEditingProperties(
- element->GetDocument().ToExecutionContext(),
+ element->GetExecutionContext(),
MakeGarbageCollected<CSSComputedStyleDeclaration>(element),
kAllEditingProperties);
node_style->RemoveEquivalentProperties(parent_style);
@@ -871,7 +870,7 @@ EditingTriState EditingStyle::TriStateOfStyle(
if (selection.IsCaret()) {
return TriStateOfStyle(
- selection.Start().GetDocument()->ToExecutionContext(),
+ selection.Start().AnchorNode()->GetExecutionContext(),
EditingStyleUtilities::CreateStyleAtSelectionStart(selection),
secure_context_mode);
}
@@ -1199,7 +1198,7 @@ bool EditingStyle::ElementIsStyledSpanOrHTMLEquivalent(
if (const CSSPropertyValueSet* style = element->InlineStyle()) {
unsigned property_count = style->PropertyCount();
for (unsigned i = 0; i < property_count; ++i) {
- if (!IsEditingProperty(element->GetDocument().ToExecutionContext(),
+ if (!IsEditingProperty(element->GetExecutionContext(),
style->PropertyAt(i).Id()))
return false;
}
@@ -1286,14 +1285,14 @@ void EditingStyle::MergeInlineStyleOfElement(
MergeStyle(element->InlineStyle(), mode);
return;
case kOnlyEditingInheritableProperties:
- MergeStyle(CopyEditingProperties(
- element->GetDocument().ToExecutionContext(),
- element->InlineStyle(), kOnlyInheritableEditingProperties),
+ MergeStyle(CopyEditingProperties(element->GetExecutionContext(),
+ element->InlineStyle(),
+ kOnlyInheritableEditingProperties),
mode);
return;
case kEditingPropertiesInEffect:
MergeStyle(
- CopyEditingProperties(element->GetDocument().ToExecutionContext(),
+ CopyEditingProperties(element->GetExecutionContext(),
element->InlineStyle(), kAllEditingProperties),
mode);
return;
@@ -1345,8 +1344,8 @@ void EditingStyle::MergeInlineAndImplicitStyleOfElement(
element->InlineStyle());
style_from_rules->mutable_style_ = ExtractEditingProperties(
- element->GetDocument().ToExecutionContext(),
- style_from_rules->mutable_style_.Get(), properties_to_include);
+ element->GetExecutionContext(), style_from_rules->mutable_style_.Get(),
+ properties_to_include);
MergeStyle(style_from_rules->mutable_style_.Get(), mode);
const HeapVector<Member<HTMLElementEquivalent>>& element_equivalents =
@@ -1523,7 +1522,7 @@ void EditingStyle::RemoveStyleFromRulesAndContext(Element* element,
mutable_style_ =
GetPropertiesNotIn(mutable_style_.Get(),
style_from_matched_rules->EnsureCSSStyleDeclaration(
- element->GetDocument().ToExecutionContext()),
+ element->GetExecutionContext()),
secure_context_mode);
}
@@ -1542,7 +1541,7 @@ void EditingStyle::RemoveStyleFromRulesAndContext(Element* element,
mutable_style_ = GetPropertiesNotIn(
mutable_style_.Get(),
computed_style->mutable_style_->EnsureCSSStyleDeclaration(
- element->GetDocument().ToExecutionContext()),
+ element->GetExecutionContext()),
secure_context_mode);
}
diff --git a/chromium/third_party/blink/renderer/core/editing/editor.cc b/chromium/third_party/blink/renderer/core/editing/editor.cc
index b27d63b98a8..c594c5bfdb5 100644
--- a/chromium/third_party/blink/renderer/core/editing/editor.cc
+++ b/chromium/third_party/blink/renderer/core/editing/editor.cc
@@ -68,6 +68,7 @@
#include "third_party/blink/renderer/core/editing/writing_direction.h"
#include "third_party/blink/renderer/core/events/keyboard_event.h"
#include "third_party/blink/renderer/core/events/text_event.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
#include "third_party/blink/renderer/core/frame/settings.h"
@@ -725,8 +726,8 @@ void Editor::ComputeAndSetTypingStyle(CSSPropertyValueSet* style,
EditingStyle::kPreserveWritingDirection);
// Handle block styles, substracting these from the typing style.
- EditingStyle* block_style = typing_style_->ExtractAndRemoveBlockProperties(
- GetFrame().GetDocument()->ToExecutionContext());
+ EditingStyle* block_style =
+ typing_style_->ExtractAndRemoveBlockProperties(GetFrame().DomWindow());
if (!block_style->IsEmpty()) {
DCHECK(GetFrame().GetDocument());
MakeGarbageCollected<ApplyStyleCommand>(*GetFrame().GetDocument(),
diff --git a/chromium/third_party/blink/renderer/core/editing/editor_key_bindings.cc b/chromium/third_party/blink/renderer/core/editing/editor_key_bindings.cc
index 8b3aac0c93b..d695d23a0f5 100644
--- a/chromium/third_party/blink/renderer/core/editing/editor_key_bindings.cc
+++ b/chromium/third_party/blink/renderer/core/editing/editor_key_bindings.cc
@@ -45,7 +45,7 @@ bool Editor::HandleEditingKeyboardEvent(KeyboardEvent* evt) {
String command_name = Behavior().InterpretKeyEvent(*evt);
const EditorCommand command = this->CreateCommand(command_name);
- if (key_event->GetType() == WebInputEvent::kRawKeyDown) {
+ if (key_event->GetType() == WebInputEvent::Type::kRawKeyDown) {
// WebKit doesn't have enough information about mode to decide how
// commands that just insert text if executed via Editor should be treated,
// so we leave it upon WebCore to either handle them immediately
diff --git a/chromium/third_party/blink/renderer/core/editing/finder/find_buffer.cc b/chromium/third_party/blink/renderer/core/editing/finder/find_buffer.cc
index 1367abe1212..a0a94dd76bd 100644
--- a/chromium/third_party/blink/renderer/core/editing/finder/find_buffer.cc
+++ b/chromium/third_party/blink/renderer/core/editing/finder/find_buffer.cc
@@ -13,7 +13,6 @@
#include "third_party/blink/renderer/core/editing/iterators/text_searcher_icu.h"
#include "third_party/blink/renderer/core/html/forms/html_form_control_element.h"
#include "third_party/blink/renderer/core/html/forms/html_select_element.h"
-#include "third_party/blink/renderer/core/invisible_dom/invisible_dom.h"
#include "third_party/blink/renderer/core/layout/layout_block_flow.h"
#include "third_party/blink/renderer/core/layout/layout_object.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.h"
diff --git a/chromium/third_party/blink/renderer/core/editing/finder/find_task_controller.cc b/chromium/third_party/blink/renderer/core/editing/finder/find_task_controller.cc
index 594e3ff6895..996895991f7 100644
--- a/chromium/third_party/blink/renderer/core/editing/finder/find_task_controller.cc
+++ b/chromium/third_party/blink/renderer/core/editing/finder/find_task_controller.cc
@@ -6,6 +6,7 @@
#include "third_party/blink/public/mojom/frame/find_in_page.mojom-blink.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_idle_request_options.h"
+#include "third_party/blink/renderer/core/display_lock/display_lock_document_state.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/range.h"
#include "third_party/blink/renderer/core/dom/scripted_idle_task_controller.h"
@@ -21,57 +22,43 @@
namespace blink {
namespace {
-const int kFindingTimeoutMS = 100;
-constexpr base::TimeDelta kFindTaskTestTimeout =
- base::TimeDelta::FromSeconds(10);
+constexpr base::TimeDelta kFindTaskTimeAllotment =
+ base::TimeDelta::FromMilliseconds(10);
} // namespace
-class FindTaskController::IdleFindTask
- : public ScriptedIdleTaskController::IdleTask {
+class FindTaskController::FindTask final : public GarbageCollected<FindTask> {
public:
- IdleFindTask(FindTaskController* controller,
- Document* document,
- int identifier,
- const WebString& search_text,
- const mojom::blink::FindOptions& options)
+ FindTask(FindTaskController* controller,
+ Document* document,
+ int identifier,
+ const WebString& search_text,
+ const mojom::blink::FindOptions& options)
: document_(document),
controller_(controller),
identifier_(identifier),
search_text_(search_text),
options_(options.Clone()) {
DCHECK(document_);
- // We need to add deadline because some webpages might have frames
- // that are always busy, resulting in bad experience in find-in-page
- // because the scoping tasks are not run.
- // See crbug.com/893465.
- IdleRequestOptions* request_options = IdleRequestOptions::Create();
- request_options->setTimeout(kFindingTimeoutMS);
- callback_handle_ = document_->RequestIdleCallback(this, request_options);
- }
-
- void Dispose() {
- DCHECK_GT(callback_handle_, 0);
- document_->CancelIdleCallback(callback_handle_);
- }
-
- void ForceInvocationForTesting() {
- invoke(MakeGarbageCollected<IdleDeadline>(
- base::TimeTicks::Now() + kFindTaskTestTimeout,
- IdleDeadline::CallbackType::kCalledWhenIdle));
+ if (options.run_synchronously_for_testing) {
+ Invoke();
+ } else {
+ controller_->GetLocalFrame()
+ ->GetTaskRunner(blink::TaskType::kInternalFindInPage)
+ ->PostTask(FROM_HERE,
+ WTF::Bind(&FindTask::Invoke, WrapWeakPersistent(this)));
+ }
}
- void Trace(Visitor* visitor) override {
+ void Trace(Visitor* visitor) {
visitor->Trace(controller_);
visitor->Trace(document_);
- ScriptedIdleTaskController::IdleTask::Trace(visitor);
}
- private:
- void invoke(IdleDeadline* deadline) override {
+ void Invoke() {
const base::TimeTicks task_start_time = base::TimeTicks::Now();
if (!controller_)
return;
- if (!controller_->ShouldFindMatches(search_text_, *options_)) {
+ if (!controller_->ShouldFindMatches(identifier_, search_text_, *options_)) {
controller_->DidFinishTask(identifier_, search_text_, *options_,
true /* finished_whole_request */,
PositionInFlatTree(), 0 /* match_count */,
@@ -83,9 +70,9 @@ class FindTaskController::IdleFindTask
Document* document = controller_->GetLocalFrame()->GetDocument();
if (!document || document_ != document)
return;
- Document::ScopedForceActivatableDisplayLocks
- forced_activatable_display_locks(
- document->GetScopedForceActivatableLocks());
+ auto forced_activatable_display_locks =
+ document->GetDisplayLockDocumentState()
+ .GetScopedForceActivatableLocks();
PositionInFlatTree search_start =
PositionInFlatTree::FirstPositionInNode(*document);
PositionInFlatTree search_end;
@@ -119,6 +106,7 @@ class FindTaskController::IdleFindTask
(options_->forward ? 0 : kBackwards) |
(options_->match_case ? 0 : kCaseInsensitive) |
(options_->find_next ? 0 : kStartInSelection);
+ auto start_time = base::TimeTicks::Now();
while (search_start != search_end) {
// Find in the whole block.
@@ -151,7 +139,8 @@ class FindTaskController::IdleFindTask
break;
}
next_task_start_position = search_start;
- if (deadline->timeRemaining() <= 0)
+ auto time_elapsed = base::TimeTicks::Now() - start_time;
+ if (time_elapsed > kFindTaskTimeAllotment)
break;
}
controller_->DidFinishTask(identifier_, search_text_, *options_,
@@ -162,7 +151,6 @@ class FindTaskController::IdleFindTask
Member<Document> document_;
Member<FindTaskController> controller_;
- int callback_handle_ = 0;
const int identifier_;
const WebString search_text_;
mojom::blink::FindOptionsPtr options_;
@@ -178,41 +166,40 @@ void FindTaskController::StartRequest(
int identifier,
const WebString& search_text,
const mojom::blink::FindOptions& options) {
+ TRACE_EVENT_ASYNC_BEGIN0("blink", "FindInPageRequest", identifier);
current_request_start_time_ = base::TimeTicks::Now();
total_task_duration_for_current_request_ = base::TimeDelta();
task_count_for_current_request_ = 0;
DCHECK(!finding_in_progress_);
+ DCHECK_EQ(current_find_identifier_, kInvalidFindIdentifier);
// This is a brand new search, so we need to reset everything.
finding_in_progress_ = true;
current_match_count_ = 0;
- RequestIdleFindTask(identifier, search_text, options);
+ current_find_identifier_ = identifier;
+ RequestFindTask(identifier, search_text, options);
}
void FindTaskController::CancelPendingRequest() {
- if (find_task_) {
- find_task_->Dispose();
+ if (find_task_)
find_task_.Clear();
- }
if (finding_in_progress_) {
RecordRequestMetrics(RequestEndState::ABORTED);
last_find_request_completed_with_no_matches_ = false;
}
finding_in_progress_ = false;
resume_finding_from_range_ = nullptr;
+ current_find_identifier_ = kInvalidFindIdentifier;
}
-void FindTaskController::RequestIdleFindTask(
+void FindTaskController::RequestFindTask(
int identifier,
const WebString& search_text,
const mojom::blink::FindOptions& options) {
DCHECK_EQ(find_task_, nullptr);
- find_task_ = MakeGarbageCollected<IdleFindTask>(
+ DCHECK_EQ(identifier, current_find_identifier_);
+ task_count_for_current_request_++;
+ find_task_ = MakeGarbageCollected<FindTask>(
this, GetLocalFrame()->GetDocument(), identifier, search_text, options);
- // If it's for testing, run the task immediately.
- // TODO(rakina): Change to use general solution when it's available.
- // https://crbug.com/875203
- if (options.run_synchronously_for_testing)
- find_task_->ForceInvocationForTesting();
}
void FindTaskController::DidFinishTask(
@@ -224,10 +211,8 @@ void FindTaskController::DidFinishTask(
int match_count,
bool aborted,
base::TimeTicks task_start_time) {
- if (find_task_) {
- find_task_->Dispose();
- find_task_.Clear();
- }
+ if (current_find_identifier_ != identifier)
+ return;
total_task_duration_for_current_request_ +=
base::TimeTicks::Now() - task_start_time;
if (find_task_)
@@ -250,20 +235,24 @@ void FindTaskController::DidFinishTask(
if (!finished_whole_request) {
// Task ran out of time, request for another one.
- RequestIdleFindTask(identifier, search_text, options);
+ RequestFindTask(identifier, search_text, options);
return; // Done for now, resume work later.
}
text_finder_->FinishCurrentScopingEffort(identifier);
RecordRequestMetrics(RequestEndState::ABORTED);
- last_find_request_completed_with_no_matches_ = !current_match_count_;
+ last_find_request_completed_with_no_matches_ =
+ !aborted && !current_match_count_;
finding_in_progress_ = false;
+ current_find_identifier_ = kInvalidFindIdentifier;
}
void FindTaskController::RecordRequestMetrics(
RequestEndState request_end_state) {
bool aborted = (request_end_state == RequestEndState::ABORTED);
+ TRACE_EVENT_ASYNC_END1("blink", "FindInPageRequest", current_find_identifier_,
+ "aborted", aborted);
if (aborted) {
UMA_HISTOGRAM_MEDIUM_TIMES("WebCore.FindInPage.TotalTaskDuration.Aborted",
total_task_duration_for_current_request_);
@@ -290,8 +279,11 @@ LocalFrame* FindTaskController::GetLocalFrame() const {
}
bool FindTaskController::ShouldFindMatches(
+ int identifier,
const String& search_text,
const mojom::blink::FindOptions& options) {
+ if (identifier != current_find_identifier_)
+ return false;
// Don't scope if we can't find a frame, a document, or a view.
// The user may have closed the tab/application, so abort.
LocalFrame* frame = GetLocalFrame();
diff --git a/chromium/third_party/blink/renderer/core/editing/finder/find_task_controller.h b/chromium/third_party/blink/renderer/core/editing/finder/find_task_controller.h
index ff28a2d2849..9a240d89c6e 100644
--- a/chromium/third_party/blink/renderer/core/editing/finder/find_task_controller.h
+++ b/chromium/third_party/blink/renderer/core/editing/finder/find_task_controller.h
@@ -9,9 +9,16 @@
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/editing/position.h"
#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
+#include "third_party/blink/renderer/platform/scheduler/common/throttling/budget_pool.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/common/tracing_helper.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
namespace blink {
+namespace {
+const int kInvalidFindIdentifier = -1;
+}
class LocalFrame;
class Range;
@@ -45,10 +52,11 @@ class CORE_EXPORT FindTaskController final
// It is not necessary if the frame is invisible, for example, or if this
// is a repeat search that already returned nothing last time the same prefix
// was searched.
- bool ShouldFindMatches(const String& search_text,
+ bool ShouldFindMatches(int identifier,
+ const String& search_text,
const mojom::blink::FindOptions& options);
- // During a run of |find_task|, we found a match.
+ // During a run of |idle_find_task|, we found a match.
// Updates |current_match_count_| and notifies |text_finder_|.
void DidFindMatch(int identifier, Range* result_range);
@@ -69,16 +77,20 @@ class CORE_EXPORT FindTaskController final
// When invoked this will search for a given text and notify us
// whenever a match is found or when it finishes, through FoundMatch and
// DidFinishTask.
- class IdleFindTask;
+ class FindTask;
void Trace(Visitor* visitor);
void ResetLastFindRequestCompletedWithNoMatches();
+ void InvokeFind(int identifier,
+ const WebString& search_text_,
+ mojom::blink::FindOptionsPtr options_);
+
private:
- void RequestIdleFindTask(int identifier,
- const WebString& search_text,
- const mojom::blink::FindOptions& options);
+ void RequestFindTask(int identifier,
+ const WebString& search_text,
+ const mojom::blink::FindOptions& options);
enum class RequestEndState {
// The find-in-page request got aborted before going through every text in
@@ -95,7 +107,7 @@ class CORE_EXPORT FindTaskController final
Member<TextFinder> text_finder_;
- Member<IdleFindTask> find_task_;
+ Member<FindTask> find_task_;
// Keeps track if there is any ongoing find effort or not.
bool finding_in_progress_;
@@ -115,6 +127,10 @@ class CORE_EXPORT FindTaskController final
// without finding any matches in this frame.
bool last_find_request_completed_with_no_matches_;
+ // The identifier of the current find request, we should only run FindTasks
+ // that have the same identifier as this.
+ int current_find_identifier_ = kInvalidFindIdentifier;
+
// The start time of the current find-in-page request.
base::TimeTicks current_request_start_time_;
// The combined duration of all the tasks done for the current request.
diff --git a/chromium/third_party/blink/renderer/core/editing/finder/text_finder.cc b/chromium/third_party/blink/renderer/core/editing/finder/text_finder.cc
index 4e83f654829..8198fbac2a7 100644
--- a/chromium/third_party/blink/renderer/core/editing/finder/text_finder.cc
+++ b/chromium/third_party/blink/renderer/core/editing/finder/text_finder.cc
@@ -41,6 +41,7 @@
#include "third_party/blink/renderer/core/display_lock/display_lock_utilities.h"
#include "third_party/blink/renderer/core/dom/range.h"
#include "third_party/blink/renderer/core/dom/shadow_root.h"
+#include "third_party/blink/renderer/core/editing/editing_utilities.h"
#include "third_party/blink/renderer/core/editing/editor.h"
#include "third_party/blink/renderer/core/editing/ephemeral_range.h"
#include "third_party/blink/renderer/core/editing/finder/find_in_page_coordinates.h"
@@ -56,7 +57,6 @@
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
#include "third_party/blink/renderer/core/frame/settings.h"
#include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
-#include "third_party/blink/renderer/core/invisible_dom/invisible_dom.h"
#include "third_party/blink/renderer/core/layout/layout_object.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
#include "third_party/blink/renderer/core/layout/text_autosizer.h"
@@ -74,15 +74,44 @@ void TextFinder::FindMatch::Trace(Visitor* visitor) {
}
static void ScrollToVisible(Range* match) {
+ const EphemeralRangeInFlatTree range(match);
const Node& first_node = *match->FirstNode();
- if (RuntimeEnabledFeatures::InvisibleDOMEnabled() ||
- RuntimeEnabledFeatures::CSSSubtreeVisibilityEnabled()) {
- const EphemeralRangeInFlatTree range(match);
- if (InvisibleDOM::ActivateRangeIfNeeded(range) ||
- DisplayLockUtilities::ActivateFindInPageMatchRangeIfNeeded(range)) {
- first_node.GetDocument().UpdateStyleAndLayout(
- DocumentUpdateReason::kFindInPage);
- }
+
+ if (RuntimeEnabledFeatures::BeforeMatchEventEnabled()) {
+ // Find-in-page matches can't span multiple block-level elements (because
+ // the text will be broken by newlines between blocks), so first we find the
+ // block-level element which contains the match.
+ // This means we only need to traverse up from one node in the range, in
+ // this case we are traversing from the start position of the range.
+ Element* enclosing_block =
+ EnclosingBlock(range.StartPosition(), kCannotCrossEditingBoundary);
+ DCHECK(enclosing_block);
+ // Note that we don't check the `range.EndPosition()` since we just activate
+ // the beginning of the range. In find-in-page cases, the end position is
+ // the same since the matches cannot cross block boundaries. However, in
+ // scroll-to-text, the range might be different, but we still just activate
+ // the beginning of the range. See
+ // https://github.com/WICG/display-locking/issues/125 for more details.
+ enclosing_block->DispatchEvent(
+ *Event::Create(event_type_names::kBeforematch));
+ // TODO(jarhar): Consider what to do based on DOM/style modifications made
+ // by the beforematch event here and write tests for it once we decide on a
+ // behavior here: https://github.com/WICG/display-locking/issues/150
+ }
+
+ // The beforematch event may detach the target element from the DOM.
+ if (!first_node.isConnected())
+ return;
+
+ if (RuntimeEnabledFeatures::CSSContentVisibilityEnabled()) {
+ // TODO(vmpstr): Rework this, since it is only used for bookkeeping.
+ DisplayLockUtilities::ActivateFindInPageMatchRangeIfNeeded(range);
+
+ // We need to update the style and layout since the event dispatched may
+ // have modified it, and we need up-to-date layout to ScrollRectToVisible
+ // below.
+ first_node.GetDocument().UpdateStyleAndLayoutForNode(
+ &first_node, DocumentUpdateReason::kFindInPage);
}
Settings* settings = first_node.GetDocument().GetSettings();
bool smooth_find_enabled =
@@ -687,11 +716,11 @@ TextFinder::TextFinder(WebLocalFrameImpl& owner_frame)
bool TextFinder::SetMarkerActive(Range* range, bool active) {
if (!range || range->collapsed())
return false;
- return OwnerFrame()
- .GetFrame()
- ->GetDocument()
- ->Markers()
- .SetTextMatchMarkersActive(EphemeralRange(range), active);
+ Document* document = OwnerFrame().GetFrame()->GetDocument();
+ document->SetFindInPageActiveMatchNode(active ? range->startContainer()
+ : nullptr);
+ return document->Markers().SetTextMatchMarkersActive(EphemeralRange(range),
+ active);
}
void TextFinder::UnmarkAllTextMatches() {
diff --git a/chromium/third_party/blink/renderer/core/editing/finder/text_finder_test.cc b/chromium/third_party/blink/renderer/core/editing/finder/text_finder_test.cc
index 2e0035d3f9c..f41fd4e4c0c 100644
--- a/chromium/third_party/blink/renderer/core/editing/finder/text_finder_test.cc
+++ b/chromium/third_party/blink/renderer/core/editing/finder/text_finder_test.cc
@@ -9,6 +9,9 @@
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/web_float_rect.h"
#include "third_party/blink/public/web/web_document.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_controller.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_source_code.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/node_list.h"
#include "third_party/blink/renderer/core/dom/range.h"
@@ -45,6 +48,8 @@ class TextFinderTest : public testing::Test {
Document& GetDocument() const;
TextFinder& GetTextFinder() const;
+ v8::Local<v8::Value> EvalJs(const std::string& script);
+
static gfx::RectF FindInPageRect(Node* start_container,
int start_offset,
Node* end_container,
@@ -56,6 +61,15 @@ class TextFinderTest : public testing::Test {
Persistent<TextFinder> text_finder_;
};
+v8::Local<v8::Value> TextFinderTest::EvalJs(const std::string& script) {
+ return GetDocument()
+ .GetFrame()
+ ->GetScriptController()
+ .ExecuteScriptInMainWorldAndReturnValue(ScriptSourceCode(script.c_str()),
+ KURL(),
+ SanitizeScriptErrors::kSanitize);
+}
+
Document& TextFinderTest::GetDocument() const {
return *document_;
}
@@ -611,4 +625,96 @@ TEST_F(TextFinderTest, ScopeWithTimeouts) {
EXPECT_EQ(4, GetTextFinder().TotalMatchCount());
}
+TEST_F(TextFinderTest, BeforeMatchEvent) {
+ V8TestingScope v8_testing_scope;
+
+ EvalJs(R"(
+ const spacer = document.createElement('div');
+ spacer.style.height = '2000px';
+ document.body.appendChild(spacer);
+
+ const foo = document.createElement('div');
+ foo.textContent = 'foo';
+ document.body.appendChild(foo);
+ window.beforematchFiredOnFoo = false;
+ foo.addEventListener('beforematch', () => {
+ window.beforematchFiredOnFoo = true;
+ });
+
+ const bar = document.createElement('div');
+ bar.textContent = 'bar';
+ document.body.appendChild(bar);
+ window.beforematchFiredOnBar = false;
+ bar.addEventListener('beforematch', () => {
+ window.YOffsetOnBeforematch = window.pageYOffset;
+ window.beforematchFiredOnBar = true;
+ });
+ )");
+ GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest);
+
+ auto find_options = mojom::blink::FindOptions::New();
+ find_options->run_synchronously_for_testing = true;
+ GetTextFinder().Find(/*identifier=*/0, WebString(String("bar")),
+ *find_options, /*wrap_within_frame=*/false);
+
+ v8::Local<v8::Value> beforematch_fired_on_foo =
+ EvalJs("window.beforematchFiredOnFoo");
+ ASSERT_TRUE(beforematch_fired_on_foo->IsBoolean());
+ EXPECT_FALSE(
+ beforematch_fired_on_foo->ToBoolean(v8::Isolate::GetCurrent())->Value());
+
+ v8::Local<v8::Value> beforematch_fired_on_bar =
+ EvalJs("window.beforematchFiredOnBar");
+ ASSERT_TRUE(beforematch_fired_on_bar->IsBoolean());
+ EXPECT_TRUE(
+ beforematch_fired_on_bar->ToBoolean(v8::Isolate::GetCurrent())->Value());
+
+ // Scrolling should occur after the beforematch event.
+ v8::Local<v8::Context> context =
+ v8_testing_scope.GetScriptState()->GetContext();
+ v8::Local<v8::Value> beforematch_y_offset =
+ EvalJs("window.YOffsetOnBeforematch");
+ ASSERT_TRUE(beforematch_y_offset->IsNumber());
+ EXPECT_TRUE(
+ beforematch_y_offset->ToNumber(context).ToLocalChecked()->Value() == 0);
+}
+
+TEST_F(TextFinderTest, BeforeMatchEventRemoveElement) {
+ V8TestingScope v8_testing_scope;
+
+ EvalJs(R"(
+ const spacer = document.createElement('div');
+ spacer.style.height = '2000px';
+ document.body.appendChild(spacer);
+
+ const foo = document.createElement('div');
+ foo.textContent = 'foo';
+ document.body.appendChild(foo);
+ window.beforematchFiredOnFoo = false;
+ foo.addEventListener('beforematch', () => {
+ foo.remove();
+ window.beforematchFiredOnFoo = true;
+ });
+ )");
+ GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest);
+
+ auto find_options = mojom::blink::FindOptions::New();
+ find_options->run_synchronously_for_testing = true;
+ GetTextFinder().Find(/*identifier=*/0, WebString(String("foo")),
+ *find_options, /*wrap_within_frame=*/false);
+
+ v8::Local<v8::Value> beforematch_fired_on_foo =
+ EvalJs("window.beforematchFiredOnFoo");
+ ASSERT_TRUE(beforematch_fired_on_foo->IsBoolean());
+ EXPECT_TRUE(
+ beforematch_fired_on_foo->ToBoolean(v8::Isolate::GetCurrent())->Value());
+
+ // TODO(jarhar): Update this test to include checks for scrolling behavior
+ // once we decide what the behavior should be. Right now it is just here to
+ // make sure we avoid a renderer crash due to the detached element.
+}
+
+// TODO(jarhar): Write more tests here once we decide on a behavior here:
+// https://github.com/WICG/display-locking/issues/150
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/editing/frame_selection.cc b/chromium/third_party/blink/renderer/core/editing/frame_selection.cc
index b068e2fc56c..902dfcae37a 100644
--- a/chromium/third_party/blink/renderer/core/editing/frame_selection.cc
+++ b/chromium/third_party/blink/renderer/core/editing/frame_selection.cc
@@ -26,7 +26,11 @@
#include "third_party/blink/renderer/core/editing/frame_selection.h"
#include <stdio.h>
+
+#include "base/auto_reset.h"
#include "third_party/blink/renderer/core/accessibility/ax_object_cache.h"
+#include "third_party/blink/renderer/core/accessibility/blink_ax_event_intent.h"
+#include "third_party/blink/renderer/core/accessibility/scoped_blink_ax_event_intent.h"
#include "third_party/blink/renderer/core/css/css_property_value_set.h"
#include "third_party/blink/renderer/core/display_lock/display_lock_utilities.h"
#include "third_party/blink/renderer/core/dom/character_data.h"
@@ -83,6 +87,7 @@
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/geometry/float_quad.h"
#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
+#include "third_party/blink/renderer/platform/text/text_direction.h"
#include "third_party/blink/renderer/platform/text/unicode_utilities.h"
#define EDIT_DEBUG 0
@@ -186,7 +191,7 @@ void FrameSelection::MoveCaretSelection(const IntPoint& point) {
void FrameSelection::SetSelection(const SelectionInDOMTree& selection,
const SetSelectionOptions& data) {
if (SetSelectionDeprecated(selection, data))
- DidSetSelectionDeprecated(data);
+ DidSetSelectionDeprecated(selection, data);
}
void FrameSelection::SetSelectionAndEndTyping(
@@ -267,9 +272,28 @@ bool FrameSelection::SetSelectionDeprecated(
}
void FrameSelection::DidSetSelectionDeprecated(
+ const SelectionInDOMTree& new_selection,
const SetSelectionOptions& options) {
- const Document& current_document = GetDocument();
- if (!GetSelectionInDOMTree().IsNone() && !options.DoNotSetFocus()) {
+ Document& current_document = GetDocument();
+ const SetSelectionBy set_selection_by = options.GetSetSelectionBy();
+
+ // Provides details to accessibility about the selection change throughout the
+ // current call stack.
+ //
+ // If the selection is currently being modified via the "Modify" method, we
+ // should already have more detailed information on the stack than can be
+ // deduced in this method.
+ ScopedBlinkAXEventIntent scoped_blink_ax_event_intent(
+ is_being_modified_
+ ? BlinkAXEventIntent()
+ : new_selection.IsNone()
+ ? BlinkAXEventIntent::FromClearedSelection(set_selection_by)
+ : BlinkAXEventIntent::FromNewSelection(
+ options.Granularity(), new_selection.IsBaseFirst(),
+ set_selection_by),
+ &current_document);
+
+ if (!new_selection.IsNone() && !options.DoNotSetFocus()) {
SetFocusedNodeIfNeeded();
// |setFocusedNodeIfNeeded()| dispatches sync events "FocusOut" and
// "FocusIn", |frame_| may associate to another document.
@@ -298,7 +322,7 @@ void FrameSelection::DidSetSelectionDeprecated(
return;
}
}
- const SetSelectionBy set_selection_by = options.GetSetSelectionBy();
+
NotifyTextControlOfSelectionChange(set_selection_by);
if (set_selection_by == SetSelectionBy::kUser) {
const CursorAlignOnScroll align = options.GetCursorAlignOnScroll();
@@ -398,6 +422,15 @@ bool FrameSelection::Modify(SelectionModifyAlteration alter,
return true;
}
+ // Provides details to accessibility about the selection change throughout the
+ // current call stack.
+ base::AutoReset<bool> is_being_modified_resetter(&is_being_modified_, true);
+ ScopedBlinkAXEventIntent scoped_blink_ax_event_intent(
+ BlinkAXEventIntent::FromModifiedSelection(
+ alter, direction, granularity, set_selection_by,
+ selection_modifier.DirectionOfSelection()),
+ &GetDocument());
+
// For MacOS only selection is directionless at the beginning.
// Selection gets direction on extent.
const bool selection_is_directional =
diff --git a/chromium/third_party/blink/renderer/core/editing/frame_selection.h b/chromium/third_party/blink/renderer/core/editing/frame_selection.h
index 263f259996a..34ba4c42c30 100644
--- a/chromium/third_party/blink/renderer/core/editing/frame_selection.h
+++ b/chromium/third_party/blink/renderer/core/editing/frame_selection.h
@@ -166,7 +166,8 @@ class CORE_EXPORT FrameSelection final
// be called.
bool SetSelectionDeprecated(const SelectionInDOMTree&,
const SetSelectionOptions&);
- void DidSetSelectionDeprecated(const SetSelectionOptions&);
+ void DidSetSelectionDeprecated(const SelectionInDOMTree&,
+ const SetSelectionOptions&);
// Call this after doing user-triggered selections to make it easy to delete
// the frame you entirely selected.
@@ -323,6 +324,10 @@ class CORE_EXPORT FrameSelection final
LayoutUnit x_pos_for_vertical_arrow_navigation_;
bool focused_ : 1;
+
+ // The selection is currently being modified via the "Modify" method.
+ bool is_being_modified_ = false;
+
bool is_handle_visible_ = false;
// TODO(editing-dev): We should change is_directional_ type to enum.
// as directional can have three values forward, backward or directionless.
diff --git a/chromium/third_party/blink/renderer/core/editing/frame_selection_test.cc b/chromium/third_party/blink/renderer/core/editing/frame_selection_test.cc
index f1409f46337..fa8bf166d20 100644
--- a/chromium/third_party/blink/renderer/core/editing/frame_selection_test.cc
+++ b/chromium/third_party/blink/renderer/core/editing/frame_selection_test.cc
@@ -606,7 +606,7 @@ TEST_F(FrameSelectionTest, FocusingButtonHidesRangeInDisabledTextControl) {
// FrameSelection::SelectAll (= textarea.select() in JavaScript) would have
// been shorter, but currently that doesn't work on a *disabled* text control.
const IntRect elem_bounds = textarea->BoundsInViewport();
- WebMouseEvent double_click(WebMouseEvent::kMouseDown, 0,
+ WebMouseEvent double_click(WebMouseEvent::Type::kMouseDown, 0,
WebInputEvent::GetStaticTimeStampForTests());
double_click.SetPositionInWidget(elem_bounds.X(), elem_bounds.Y());
double_click.SetPositionInScreen(elem_bounds.X(), elem_bounds.Y());
diff --git a/chromium/third_party/blink/renderer/core/editing/ime/edit_context.cc b/chromium/third_party/blink/renderer/core/editing/ime/edit_context.cc
index 598f585111a..bb5164cc9fc 100644
--- a/chromium/third_party/blink/renderer/core/editing/ime/edit_context.cc
+++ b/chromium/third_party/blink/renderer/core/editing/ime/edit_context.cc
@@ -18,6 +18,7 @@
#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/geometry/dom_rect.h"
+#include "third_party/blink/renderer/platform/geometry/double_rect.h"
#include "third_party/blink/renderer/platform/wtf/decimal.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
@@ -198,14 +199,15 @@ void EditContext::updateSelection(uint32_t start,
void EditContext::updateLayout(DOMRect* control_bounds,
DOMRect* selection_bounds) {
- control_bounds_.x = control_bounds->x();
- control_bounds_.y = control_bounds->y();
- control_bounds_.width = control_bounds->width();
- control_bounds_.height = control_bounds->height();
- selection_bounds_.x = selection_bounds->x();
- selection_bounds_.y = selection_bounds->y();
- selection_bounds_.width = selection_bounds->width();
- selection_bounds_.height = selection_bounds->height();
+ // Return the IntRect containing the given DOMRect.
+ const DoubleRect control_bounds_double_rect(
+ control_bounds->x(), control_bounds->y(), control_bounds->width(),
+ control_bounds->height());
+ control_bounds_ = EnclosingIntRect(control_bounds_double_rect);
+ const DoubleRect selection_bounds_double_rect(
+ selection_bounds->x(), selection_bounds->y(), selection_bounds->width(),
+ selection_bounds->height());
+ selection_bounds_ = EnclosingIntRect(selection_bounds_double_rect);
}
void EditContext::updateText(uint32_t start,
diff --git a/chromium/third_party/blink/renderer/core/editing/ime/input_method_controller.cc b/chromium/third_party/blink/renderer/core/editing/ime/input_method_controller.cc
index 64be8237804..deacb4fbef0 100644
--- a/chromium/third_party/blink/renderer/core/editing/ime/input_method_controller.cc
+++ b/chromium/third_party/blink/renderer/core/editing/ime/input_method_controller.cc
@@ -62,6 +62,7 @@
#include "third_party/blink/renderer/core/layout/layout_theme.h"
#include "third_party/blink/renderer/core/page/focus_controller.h"
#include "third_party/blink/renderer/core/page/page.h"
+#include "third_party/blink/renderer/platform/geometry/double_rect.h"
namespace blink {
@@ -391,8 +392,11 @@ int ComputeAutocapitalizeFlags(const Element* element) {
enum class InputMethodController::TypingContinuation { kContinue, kEnd };
-InputMethodController::InputMethodController(LocalFrame& frame)
- : frame_(&frame), has_composition_(false) {}
+InputMethodController::InputMethodController(LocalDOMWindow& window,
+ LocalFrame& frame)
+ : ExecutionContextLifecycleObserver(&window),
+ frame_(frame),
+ has_composition_(false) {}
InputMethodController::~InputMethodController() = default;
@@ -402,7 +406,7 @@ bool InputMethodController::IsAvailable() const {
Document& InputMethodController::GetDocument() const {
DCHECK(IsAvailable());
- return *Document::From(GetExecutionContext());
+ return *To<LocalDOMWindow>(GetExecutionContext())->document();
}
bool InputMethodController::HasComposition() const {
@@ -414,6 +418,10 @@ inline Editor& InputMethodController::GetEditor() const {
return GetFrame().GetEditor();
}
+LocalFrame& InputMethodController::GetFrame() const {
+ return *frame_;
+}
+
void InputMethodController::Clear() {
RemoveSuggestionMarkerInCompositionRange();
@@ -432,11 +440,6 @@ void InputMethodController::ContextDestroyed() {
active_edit_context_ = nullptr;
}
-void InputMethodController::DidAttachDocument(Document* document) {
- DCHECK(document);
- SetExecutionContext(document->ToExecutionContext());
-}
-
void InputMethodController::SelectComposition() const {
const EphemeralRange range = CompositionEphemeralRange();
if (range.IsNull())
@@ -770,7 +773,7 @@ void InputMethodController::CancelComposition() {
// An open typing command that disagrees about current selection would cause
// issues with typing later on.
- TypingCommand::CloseTyping(frame_);
+ TypingCommand::CloseTyping(&GetFrame());
// No DOM update after 'compositionend'.
DispatchCompositionEndEvent(GetFrame(), g_empty_string);
@@ -1373,11 +1376,12 @@ void InputMethodController::GetLayoutBounds(WebRect* control_bounds,
// Selection bounds are currently populated only for EditContext.
// For editable elements we use GetCompositionCharacterBounds to fetch the
// selection bounds.
- DOMRect* editable_rect = element->getBoundingClientRect();
- control_bounds->x = editable_rect->x();
- control_bounds->y = editable_rect->y();
- control_bounds->width = editable_rect->width();
- control_bounds->height = editable_rect->height();
+ const DOMRect* editable_rect = element->getBoundingClientRect();
+ const DoubleRect editable_rect_double(editable_rect->x(), editable_rect->y(),
+ editable_rect->width(),
+ editable_rect->height());
+ // Return the IntRect containing the given DOMRect.
+ *control_bounds = EnclosingIntRect(editable_rect_double);
}
WebTextInputInfo InputMethodController::TextInputInfo() const {
diff --git a/chromium/third_party/blink/renderer/core/editing/ime/input_method_controller.h b/chromium/third_party/blink/renderer/core/editing/ime/input_method_controller.h
index 3ad7cd7c416..545a199670e 100644
--- a/chromium/third_party/blink/renderer/core/editing/ime/input_method_controller.h
+++ b/chromium/third_party/blink/renderer/core/editing/ime/input_method_controller.h
@@ -43,13 +43,14 @@ namespace blink {
class Editor;
class EditContext;
+class LocalDOMWindow;
class LocalFrame;
class Range;
enum class TypingContinuation;
class CORE_EXPORT InputMethodController final
: public GarbageCollected<InputMethodController>,
- ExecutionContextLifecycleObserver {
+ public ExecutionContextLifecycleObserver {
USING_GARBAGE_COLLECTED_MIXIN(InputMethodController);
public:
@@ -58,7 +59,7 @@ class CORE_EXPORT InputMethodController final
kKeepSelection,
};
- explicit InputMethodController(LocalFrame&);
+ explicit InputMethodController(LocalDOMWindow&, LocalFrame&);
virtual ~InputMethodController();
void Trace(Visitor*) override;
@@ -93,7 +94,6 @@ class CORE_EXPORT InputMethodController final
EphemeralRange CompositionEphemeralRange() const;
void Clear();
- void DidAttachDocument(Document*);
PlainTextRange GetSelectionOffsets() const;
// Returns true if setting selection to specified offsets, otherwise false.
@@ -136,10 +136,7 @@ class CORE_EXPORT InputMethodController final
bool has_composition_;
Editor& GetEditor() const;
- LocalFrame& GetFrame() const {
- DCHECK(frame_);
- return *frame_;
- }
+ LocalFrame& GetFrame() const;
String ComposingText() const;
void SelectComposition() const;
diff --git a/chromium/third_party/blink/renderer/core/editing/iterators/text_iterator_behavior.cc b/chromium/third_party/blink/renderer/core/editing/iterators/text_iterator_behavior.cc
index 98cabe8caca..8423d61958d 100644
--- a/chromium/third_party/blink/renderer/core/editing/iterators/text_iterator_behavior.cc
+++ b/chromium/third_party/blink/renderer/core/editing/iterators/text_iterator_behavior.cc
@@ -17,12 +17,6 @@ TextIteratorBehavior TextIteratorBehavior::Builder::Build() {
}
TextIteratorBehavior::Builder&
-TextIteratorBehavior::Builder::SetCollapseTrailingSpace(bool value) {
- behavior_.values_.bits.collapse_trailing_space = value;
- return *this;
-}
-
-TextIteratorBehavior::Builder&
TextIteratorBehavior::Builder::SetDoesNotBreakAtReplacedElement(bool value) {
behavior_.values_.bits.does_not_break_at_replaced_element = value;
return *this;
diff --git a/chromium/third_party/blink/renderer/core/editing/iterators/text_iterator_behavior.h b/chromium/third_party/blink/renderer/core/editing/iterators/text_iterator_behavior.h
index f198a7a4457..38e16d4be3c 100644
--- a/chromium/third_party/blink/renderer/core/editing/iterators/text_iterator_behavior.h
+++ b/chromium/third_party/blink/renderer/core/editing/iterators/text_iterator_behavior.h
@@ -23,9 +23,6 @@ class CORE_EXPORT TextIteratorBehavior final {
bool operator==(const TextIteratorBehavior& other) const;
bool operator!=(const TextIteratorBehavior& other) const;
- bool CollapseTrailingSpace() const {
- return values_.bits.collapse_trailing_space;
- }
bool DoesNotBreakAtReplacedElement() const {
return values_.bits.does_not_break_at_replaced_element;
}
@@ -83,7 +80,6 @@ class CORE_EXPORT TextIteratorBehavior final {
union {
unsigned all;
struct {
- bool collapse_trailing_space : 1;
bool does_not_break_at_replaced_element : 1;
bool emits_characters_between_all_visible_positions : 1;
bool emits_image_alt_text : 1;
@@ -117,7 +113,6 @@ class CORE_EXPORT TextIteratorBehavior::Builder final {
TextIteratorBehavior Build();
- Builder& SetCollapseTrailingSpace(bool);
Builder& SetDoesNotBreakAtReplacedElement(bool);
Builder& SetEmitsCharactersBetweenAllVisiblePositions(bool);
Builder& SetEmitsImageAltText(bool);
diff --git a/chromium/third_party/blink/renderer/core/editing/iterators/text_iterator_behavior_test.cc b/chromium/third_party/blink/renderer/core/editing/iterators/text_iterator_behavior_test.cc
index 256829cd1a1..5b36782a500 100644
--- a/chromium/third_party/blink/renderer/core/editing/iterators/text_iterator_behavior_test.cc
+++ b/chromium/third_party/blink/renderer/core/editing/iterators/text_iterator_behavior_test.cc
@@ -11,34 +11,26 @@ namespace blink {
TEST(TextIteratorBehaviorTest, Basic) {
EXPECT_TRUE(TextIteratorBehavior() == TextIteratorBehavior());
EXPECT_FALSE(TextIteratorBehavior() != TextIteratorBehavior());
- EXPECT_NE(
- TextIteratorBehavior(),
- TextIteratorBehavior::Builder().SetCollapseTrailingSpace(true).Build());
- EXPECT_NE(
- TextIteratorBehavior::Builder().SetCollapseTrailingSpace(true).Build(),
- TextIteratorBehavior());
- EXPECT_NE(
- TextIteratorBehavior::Builder().SetCollapseTrailingSpace(true).Build(),
- TextIteratorBehavior::Builder().SetEmitsImageAltText(true).Build());
- EXPECT_NE(
- TextIteratorBehavior::Builder().SetEmitsImageAltText(true).Build(),
- TextIteratorBehavior::Builder().SetCollapseTrailingSpace(true).Build());
+ EXPECT_NE(TextIteratorBehavior(),
+ TextIteratorBehavior::Builder().SetForInnerText(true).Build());
+ EXPECT_NE(TextIteratorBehavior::Builder().SetForInnerText(true).Build(),
+ TextIteratorBehavior());
+ EXPECT_NE(TextIteratorBehavior::Builder().SetForInnerText(true).Build(),
+ TextIteratorBehavior::Builder().SetEmitsImageAltText(true).Build());
+ EXPECT_NE(TextIteratorBehavior::Builder().SetEmitsImageAltText(true).Build(),
+ TextIteratorBehavior::Builder().SetForInnerText(true).Build());
EXPECT_EQ(TextIteratorBehavior::Builder()
- .SetCollapseTrailingSpace(true)
+ .SetForInnerText(true)
.SetEmitsImageAltText(true)
.Build(),
TextIteratorBehavior::Builder()
.SetEmitsImageAltText(true)
- .SetCollapseTrailingSpace(true)
+ .SetForInnerText(true)
.Build());
}
TEST(TextIteratorBehaviorTest, Values) {
EXPECT_TRUE(TextIteratorBehavior::Builder()
- .SetCollapseTrailingSpace(true)
- .Build()
- .CollapseTrailingSpace());
- EXPECT_TRUE(TextIteratorBehavior::Builder()
.SetDoesNotBreakAtReplacedElement(true)
.Build()
.DoesNotBreakAtReplacedElement());
diff --git a/chromium/third_party/blink/renderer/core/editing/iterators/text_iterator_test.cc b/chromium/third_party/blink/renderer/core/editing/iterators/text_iterator_test.cc
index 7f7f2a2fd7d..6af39c1764a 100644
--- a/chromium/third_party/blink/renderer/core/editing/iterators/text_iterator_test.cc
+++ b/chromium/third_party/blink/renderer/core/editing/iterators/text_iterator_test.cc
@@ -43,10 +43,6 @@
namespace blink {
namespace text_iterator_test {
-TextIteratorBehavior CollapseTrailingSpaceBehavior() {
- return TextIteratorBehavior::Builder().SetCollapseTrailingSpace(true).Build();
-}
-
TextIteratorBehavior EmitsImageAltTextBehavior() {
return TextIteratorBehavior::Builder().SetEmitsImageAltText(true).Build();
}
@@ -544,16 +540,41 @@ TEST_P(TextIteratorTest, RangeLengthWithFirstLetterMultipleLeadingSpaces) {
EXPECT_EQ(3, TestRangeLength("<p>^ foo|</p>"));
}
+TEST_P(TextIteratorTest, TrainlingSpace) {
+ // text_content = "ab\ncd"
+ // offset mapping units:
+ // [0] I DOM:0-2 TC:0-2 "ab"
+ // [1] C DOM:2-4 TC:2-2 " " spaces after "ab"
+ // [2] I DOM:0-1 TC:2-3 <br>
+ // [3] I DOM:0-2 TC:3-5 "cd"
+ // Note: InlineTextBox has trailing spaces which we should get rid from
+ // inline layout tree as LayoutNG.
+ SetBodyContent("ab <br> cd");
+ EXPECT_EQ(LayoutNGEnabled() ? "[ab][\n][cd]" : "[ab ][\n][cd]",
+ Iterate<DOMTree>());
+}
+
TEST_P(TextIteratorTest, WhitespaceCollapseForReplacedElements) {
static const char* body_content =
"<span>Some text </span> <input type='button' value='Button "
"text'/><span>Some more text</span>";
SetBodyContent(body_content);
- EXPECT_EQ("[Some text ][][Some more text]",
- Iterate<DOMTree>(CollapseTrailingSpaceBehavior()));
+ // text_content = "Some text \uFFFCSome more text"
+ // offset mapping units:
+ // [0] I DOM:0-10 TC:0-10 "Some text "
+ // [1] C DOM:0-1 TC:10-10 " " (A space between </span> and <input>
+ // [2] I DOM:0-1 TC:10-11 <input> as U+FFFC (ORC)
+ // [3] I DOM:0-14 TC:11-25 "Some more text"
+ // Note: InlineTextBox has a collapsed space which we should get rid from
+ // inline layout tree as LayoutNG.
+ EXPECT_EQ(LayoutNGEnabled() ? "[Some text ][][Some more text]"
+ : "[Some text ][ ][][Some more text]",
+ Iterate<DOMTree>());
// <input type=button> is not text control element
- EXPECT_EQ("[Some text ][][Button text][Some more text]",
- Iterate<FlatTree>(CollapseTrailingSpaceBehavior()));
+ EXPECT_EQ(LayoutNGEnabled()
+ ? "[Some text ][][Button text][Some more text]"
+ : "[Some text ][ ][][Button text][Some more text]",
+ Iterate<FlatTree>());
}
TEST_P(TextIteratorTest, characterAt) {
@@ -1036,7 +1057,7 @@ TEST_P(TextIteratorTest, EmitsSpaceForNbsp) {
TEST_P(TextIteratorTest, IterateWithLockedSubtree) {
SetBodyContent("<div id='parent'>foo<div id='locked'>text</div>bar</div>");
auto* locked = GetDocument().getElementById("locked");
- locked->setAttribute(html_names::kStyleAttr, "subtree-visibility: auto");
+ locked->setAttribute(html_names::kStyleAttr, "content-visibility: auto");
GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest);
auto* parent = GetDocument().getElementById("parent");
const Position start_position = Position::FirstPositionInNode(*parent);
diff --git a/chromium/third_party/blink/renderer/core/editing/iterators/text_iterator_text_node_handler.cc b/chromium/third_party/blink/renderer/core/editing/iterators/text_iterator_text_node_handler.cc
index 8c69950615f..531e363b728 100644
--- a/chromium/third_party/blink/renderer/core/editing/iterators/text_iterator_text_node_handler.cc
+++ b/chromium/third_party/blink/renderer/core/editing/iterators/text_iterator_text_node_handler.cc
@@ -178,12 +178,9 @@ void TextIteratorTextNodeHandler::HandlePreFormattedTextNode() {
if (last_text_node_ended_with_collapsed_space_ &&
HasVisibleTextNode(layout_object)) {
- if (!behavior_.CollapseTrailingSpace() ||
- (offset_ > 0 && str[offset_ - 1] == ' ')) {
- EmitChar16Before(kSpaceCharacter, offset_);
- needs_handle_pre_formatted_text_node_ = true;
- return;
- }
+ EmitChar16Before(kSpaceCharacter, offset_);
+ needs_handle_pre_formatted_text_node_ = true;
+ return;
}
if (ShouldHandleFirstLetter(*layout_object)) {
LayoutTextFragment* remaining_text = ToLayoutTextFragment(layout_object);
@@ -545,12 +542,7 @@ bool TextIteratorTextNodeHandler::ShouldFixLeadingWhiteSpaceForReplacedElement()
return false;
if (!last_text_node_ended_with_collapsed_space_)
return false;
- if (!behavior_.CollapseTrailingSpace())
- return true;
- if (!text_node_)
- return false;
- const String str = text_node_->GetLayoutObject()->GetText();
- return offset_ > 0 && str[offset_ - 1] == ' ';
+ return true;
}
bool TextIteratorTextNodeHandler::FixLeadingWhiteSpaceForReplacedElement() {
diff --git a/chromium/third_party/blink/renderer/core/editing/keyboard_test.cc b/chromium/third_party/blink/renderer/core/editing/keyboard_test.cc
index f208b02608e..34ae8ce43c9 100644
--- a/chromium/third_party/blink/renderer/core/editing/keyboard_test.cc
+++ b/chromium/third_party/blink/renderer/core/editing/keyboard_test.cc
@@ -80,30 +80,31 @@ class KeyboardTest : public testing::Test {
WebInputEvent::Modifiers os_modifier = WebInputEvent::kControlKey;
#endif
return InterpretKeyEvent(CreateFakeKeyboardEvent(
- key_code, os_modifier, WebInputEvent::kRawKeyDown));
+ key_code, os_modifier, WebInputEvent::Type::kRawKeyDown));
}
// Like interpretKeyEvent, but with pressing down ctrl+|keyCode|.
const char* InterpretCtrlKeyPress(char key_code) {
- return InterpretKeyEvent(CreateFakeKeyboardEvent(
- key_code, WebInputEvent::kControlKey, WebInputEvent::kRawKeyDown));
+ return InterpretKeyEvent(
+ CreateFakeKeyboardEvent(key_code, WebInputEvent::kControlKey,
+ WebInputEvent::Type::kRawKeyDown));
}
// Like interpretKeyEvent, but with typing a tab.
const char* InterpretTab(int modifiers) {
return InterpretKeyEvent(
- CreateFakeKeyboardEvent('\t', modifiers, WebInputEvent::kChar));
+ CreateFakeKeyboardEvent('\t', modifiers, WebInputEvent::Type::kChar));
}
// Like interpretKeyEvent, but with typing a newline.
const char* InterpretNewLine(int modifiers) {
return InterpretKeyEvent(
- CreateFakeKeyboardEvent('\r', modifiers, WebInputEvent::kChar));
+ CreateFakeKeyboardEvent('\r', modifiers, WebInputEvent::Type::kChar));
}
const char* InterpretDomKey(const char* key) {
return InterpretKeyEvent(CreateFakeKeyboardEvent(
- 0, kNoModifiers, WebInputEvent::kRawKeyDown, key));
+ 0, kNoModifiers, WebInputEvent::Type::kRawKeyDown, key));
}
// A name for "no modifiers set".
@@ -152,7 +153,7 @@ TEST_F(KeyboardTest, TestOSModifierV) {
TEST_F(KeyboardTest, TestEscape) {
const char* result = InterpretKeyEvent(CreateFakeKeyboardEvent(
- VKEY_ESCAPE, kNoModifiers, WebInputEvent::kRawKeyDown));
+ VKEY_ESCAPE, kNoModifiers, WebInputEvent::Type::kRawKeyDown));
EXPECT_STREQ("Cancel", result);
}
diff --git a/chromium/third_party/blink/renderer/core/editing/link_selection_test.cc b/chromium/third_party/blink/renderer/core/editing/link_selection_test.cc
index 69e1e4c06f6..3f19c64db25 100644
--- a/chromium/third_party/blink/renderer/core/editing/link_selection_test.cc
+++ b/chromium/third_party/blink/renderer/core/editing/link_selection_test.cc
@@ -4,7 +4,7 @@
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/platform/web_coalesced_input_event.h"
+#include "third_party/blink/public/common/input/web_coalesced_input_event.h"
#include "third_party/blink/public/web/web_settings.h"
#include "third_party/blink/renderer/core/dom/events/native_event_listener.h"
#include "third_party/blink/renderer/core/dom/range.h"
@@ -19,7 +19,7 @@
#include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
#include "third_party/blink/renderer/platform/testing/url_test_helpers.h"
#include "ui/base/cursor/cursor.h"
-#include "ui/base/mojom/cursor_type.mojom-blink.h"
+#include "ui/base/cursor/mojom/cursor_type.mojom-blink.h"
using testing::_;
@@ -62,10 +62,10 @@ void LinkSelectionTestBase::EmulateMouseDrag(const IntPoint& down_point,
DragFlags drag_flags) {
if (drag_flags & kSendDownEvent) {
const auto& down_event = frame_test_helpers::CreateMouseEvent(
- WebMouseEvent::kMouseDown, WebMouseEvent::Button::kLeft, down_point,
- modifiers);
+ WebMouseEvent::Type::kMouseDown, WebMouseEvent::Button::kLeft,
+ down_point, modifiers);
web_view_->MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(down_event));
+ WebCoalescedInputEvent(down_event, ui::LatencyInfo()));
}
const int kMoveEventsNumber = 10;
@@ -75,18 +75,18 @@ void LinkSelectionTestBase::EmulateMouseDrag(const IntPoint& down_point,
const auto& move_point =
down_point + Scaled(up_down_vector, i * kMoveIncrementFraction);
const auto& move_event = frame_test_helpers::CreateMouseEvent(
- WebMouseEvent::kMouseMove, WebMouseEvent::Button::kLeft, move_point,
- modifiers);
+ WebMouseEvent::Type::kMouseMove, WebMouseEvent::Button::kLeft,
+ move_point, modifiers);
web_view_->MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(move_event));
+ WebCoalescedInputEvent(move_event, ui::LatencyInfo()));
}
if (drag_flags & kSendUpEvent) {
const auto& up_event = frame_test_helpers::CreateMouseEvent(
- WebMouseEvent::kMouseUp, WebMouseEvent::Button::kLeft, up_point,
+ WebMouseEvent::Type::kMouseUp, WebMouseEvent::Button::kLeft, up_point,
modifiers);
web_view_->MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(up_event));
+ WebCoalescedInputEvent(up_event, ui::LatencyInfo()));
}
}
@@ -95,11 +95,13 @@ void LinkSelectionTestBase::EmulateMouseClick(const IntPoint& click_point,
int modifiers,
int count) {
auto event = frame_test_helpers::CreateMouseEvent(
- WebMouseEvent::kMouseDown, button, click_point, modifiers);
+ WebMouseEvent::Type::kMouseDown, button, click_point, modifiers);
event.click_count = count;
- web_view_->MainFrameWidget()->HandleInputEvent(WebCoalescedInputEvent(event));
- event.SetType(WebMouseEvent::kMouseUp);
- web_view_->MainFrameWidget()->HandleInputEvent(WebCoalescedInputEvent(event));
+ web_view_->MainFrameWidget()->HandleInputEvent(
+ WebCoalescedInputEvent(event, ui::LatencyInfo()));
+ event.SetType(WebMouseEvent::Type::kMouseUp);
+ web_view_->MainFrameWidget()->HandleInputEvent(
+ WebCoalescedInputEvent(event, ui::LatencyInfo()));
}
void LinkSelectionTestBase::EmulateMouseDown(const IntPoint& click_point,
@@ -107,9 +109,10 @@ void LinkSelectionTestBase::EmulateMouseDown(const IntPoint& click_point,
int modifiers,
int count) {
auto event = frame_test_helpers::CreateMouseEvent(
- WebMouseEvent::kMouseDown, button, click_point, modifiers);
+ WebMouseEvent::Type::kMouseDown, button, click_point, modifiers);
event.click_count = count;
- web_view_->MainFrameWidget()->HandleInputEvent(WebCoalescedInputEvent(event));
+ web_view_->MainFrameWidget()->HandleInputEvent(
+ WebCoalescedInputEvent(event, ui::LatencyInfo()));
}
String LinkSelectionTestBase::GetSelectionText() {
diff --git a/chromium/third_party/blink/renderer/core/editing/markers/document_marker_controller.cc b/chromium/third_party/blink/renderer/core/editing/markers/document_marker_controller.cc
index e9c3deffee1..412c7fbbb37 100644
--- a/chromium/third_party/blink/renderer/core/editing/markers/document_marker_controller.cc
+++ b/chromium/third_party/blink/renderer/core/editing/markers/document_marker_controller.cc
@@ -771,7 +771,7 @@ void DocumentMarkerController::InvalidateRectsForAllTextMatchMarkers() {
}
}
-void DocumentMarkerController::DidProcessMarkerMap(const WeakCallbackInfo&) {
+void DocumentMarkerController::DidProcessMarkerMap(const LivenessBroker&) {
if (markers_.IsEmpty())
Clear();
}
diff --git a/chromium/third_party/blink/renderer/core/editing/markers/document_marker_controller.h b/chromium/third_party/blink/renderer/core/editing/markers/document_marker_controller.h
index a5d7b850598..0295a9180be 100644
--- a/chromium/third_party/blink/renderer/core/editing/markers/document_marker_controller.h
+++ b/chromium/third_party/blink/renderer/core/editing/markers/document_marker_controller.h
@@ -189,7 +189,7 @@ class CORE_EXPORT DocumentMarkerController final
DocumentMarker::MarkerTypes);
// Called after weak processing of |markers_| is done.
- void DidProcessMarkerMap(const WeakCallbackInfo&);
+ void DidProcessMarkerMap(const LivenessBroker&);
MarkerMap markers_;
// Provide a quick way to determine whether a particular marker type is absent
diff --git a/chromium/third_party/blink/renderer/core/editing/selection_controller.cc b/chromium/third_party/blink/renderer/core/editing/selection_controller.cc
index 8ed3c295c8a..0736b1ce96c 100644
--- a/chromium/third_party/blink/renderer/core/editing/selection_controller.cc
+++ b/chromium/third_party/blink/renderer/core/editing/selection_controller.cc
@@ -48,6 +48,7 @@
#include "third_party/blink/renderer/core/editing/spellcheck/spell_checker.h"
#include "third_party/blink/renderer/core/editing/suggestion/text_suggestion_controller.h"
#include "third_party/blink/renderer/core/editing/visible_position.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/local_frame_client.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
@@ -62,7 +63,7 @@
namespace blink {
SelectionController::SelectionController(LocalFrame& frame)
- : ExecutionContextLifecycleObserver(frame.GetDocument()),
+ : ExecutionContextLifecycleObserver(frame.DomWindow()),
frame_(&frame),
mouse_down_may_start_select_(false),
mouse_down_was_single_click_in_selection_(false),
@@ -833,7 +834,7 @@ void SelectionController::SetNonDirectionalSelectionIfNeeded(
if (adjusted_selection.Base() != base.GetPosition() ||
adjusted_selection.Extent() != extent.GetPosition()) {
original_base_in_flat_tree_ = base;
- SetExecutionContext(GetDocument().ToExecutionContext());
+ SetExecutionContext(frame_->DomWindow());
builder.SetBaseAndExtent(adjusted_selection.Base(),
adjusted_selection.Extent());
} else if (original_base.IsNotNull()) {
@@ -1137,7 +1138,7 @@ bool SelectionController::HandlePasteGlobalSelection(
// down then the text is pasted just before the onclick handler runs and
// clears the text box. So it's important this happens after the event
// handlers have been fired.
- if (mouse_event.GetType() != WebInputEvent::kMouseUp)
+ if (mouse_event.GetType() != WebInputEvent::Type::kMouseUp)
return false;
if (!frame_->GetPage())
diff --git a/chromium/third_party/blink/renderer/core/editing/selection_controller_test.cc b/chromium/third_party/blink/renderer/core/editing/selection_controller_test.cc
index 39db548a9d0..bcc0c15b983 100644
--- a/chromium/third_party/blink/renderer/core/editing/selection_controller_test.cc
+++ b/chromium/third_party/blink/renderer/core/editing/selection_controller_test.cc
@@ -213,7 +213,7 @@ TEST_F(SelectionControllerTest,
// Simulate a tap somewhere in the document
blink::WebMouseEvent mouse_event(
- blink::WebInputEvent::kMouseDown,
+ blink::WebInputEvent::Type::kMouseDown,
blink::WebInputEvent::kIsCompatibilityEventForTouch,
blink::WebInputEvent::GetStaticTimeStampForTests());
// Frame scale defaults to 0, which would cause a divide-by-zero problem.
diff --git a/chromium/third_party/blink/renderer/core/editing/selection_modifier.cc b/chromium/third_party/blink/renderer/core/editing/selection_modifier.cc
index 5b4c215906a..e06d5224f56 100644
--- a/chromium/third_party/blink/renderer/core/editing/selection_modifier.cc
+++ b/chromium/third_party/blink/renderer/core/editing/selection_modifier.cc
@@ -396,7 +396,6 @@ VisiblePosition SelectionModifier::ModifyExtendingForwardInternal(
return LogicalEndOfLine(EndForPlatform());
case TextGranularity::kParagraphBoundary:
return EndOfParagraph(EndForPlatform());
- break;
case TextGranularity::kDocumentBoundary: {
const VisiblePosition& pos = EndForPlatform();
if (IsEditablePosition(pos.DeepEquivalent()))
diff --git a/chromium/third_party/blink/renderer/core/editing/selection_modifier.h b/chromium/third_party/blink/renderer/core/editing/selection_modifier.h
index 3aebd05b90e..0beea6227d1 100644
--- a/chromium/third_party/blink/renderer/core/editing/selection_modifier.h
+++ b/chromium/third_party/blink/renderer/core/editing/selection_modifier.h
@@ -61,6 +61,8 @@ class CORE_EXPORT SelectionModifier {
// to return |current_selection_|.
VisibleSelection Selection() const;
+ TextDirection DirectionOfSelection() const;
+
bool Modify(SelectionModifyAlteration,
SelectionModifyDirection,
TextGranularity);
@@ -78,7 +80,6 @@ class CORE_EXPORT SelectionModifier {
VisibleSelection PrepareToModifySelection(SelectionModifyAlteration,
SelectionModifyDirection) const;
TextDirection DirectionOfEnclosingBlock() const;
- TextDirection DirectionOfSelection() const;
TextDirection LineDirectionOfExtent() const;
VisiblePosition PositionForPlatform(bool is_get_start) const;
VisiblePosition StartForPlatform() const;
diff --git a/chromium/third_party/blink/renderer/core/editing/selection_modifier_line.cc b/chromium/third_party/blink/renderer/core/editing/selection_modifier_line.cc
index fffc06a48b4..786f9af68d4 100644
--- a/chromium/third_party/blink/renderer/core/editing/selection_modifier_line.cc
+++ b/chromium/third_party/blink/renderer/core/editing/selection_modifier_line.cc
@@ -195,7 +195,7 @@ class AbstractLineBox {
for (cursor.MoveToNext(); cursor; cursor.MoveToNext()) {
if (!cursor.Current().GetLayoutObject())
continue;
- if (!cursor.IsInlineLeaf())
+ if (!cursor.Current().IsInlineLeaf())
continue;
if (only_editable_leaves && !IsEditable(cursor))
continue;
diff --git a/chromium/third_party/blink/renderer/core/editing/serializers/markup_accumulator.cc b/chromium/third_party/blink/renderer/core/editing/serializers/markup_accumulator.cc
index 508c0337557..a9a285fed92 100644
--- a/chromium/third_party/blink/renderer/core/editing/serializers/markup_accumulator.cc
+++ b/chromium/third_party/blink/renderer/core/editing/serializers/markup_accumulator.cc
@@ -545,8 +545,10 @@ bool MarkupAccumulator::SerializeAsHTML() const {
std::pair<Node*, Element*> MarkupAccumulator::GetAuxiliaryDOMTree(
const Element& element) const {
ShadowRoot* shadow_root = element.GetShadowRoot();
- if (!shadow_root || include_shadow_roots_ != kIncludeShadowRoots)
+ if (!shadow_root || include_shadow_roots_ != kIncludeShadowRoots ||
+ shadow_root->GetType() != ShadowRootType::kOpen) {
return std::pair<Node*, Element*>();
+ }
DCHECK(RuntimeEnabledFeatures::DeclarativeShadowDOMEnabled());
AtomicString shadowroot_type;
switch (shadow_root->GetType()) {
@@ -597,10 +599,16 @@ void MarkupAccumulator::SerializeNodesWithNamespaces(
!(SerializeAsHTML() && ElementCannotHaveEndTag(target_element));
if (has_end_tag) {
const Node* parent = &target_element;
- if (auto* template_element = DynamicTo<HTMLTemplateElement>(target_element))
+ if (auto* template_element =
+ DynamicTo<HTMLTemplateElement>(target_element)) {
+ // Declarative shadow roots that are currently being parsed will have a
+ // null content() - don't serialize contents in this case.
parent = template_element->content();
- for (const Node& child : Strategy::ChildrenOf(*parent))
- SerializeNodesWithNamespaces<Strategy>(child, kIncludeNode);
+ }
+ if (parent) {
+ for (const Node& child : Strategy::ChildrenOf(*parent))
+ SerializeNodesWithNamespaces<Strategy>(child, kIncludeNode);
+ }
// Traverses other DOM tree, i.e., shadow tree.
std::pair<Node*, Element*> auxiliary_pair =
diff --git a/chromium/third_party/blink/renderer/core/editing/serializers/serialization.cc b/chromium/third_party/blink/renderer/core/editing/serializers/serialization.cc
index 21b74b91f87..f688bb9a361 100644
--- a/chromium/third_party/blink/renderer/core/editing/serializers/serialization.cc
+++ b/chromium/third_party/blink/renderer/core/editing/serializers/serialization.cc
@@ -779,6 +779,7 @@ static Document* CreateStagingDocumentForMarkupSanitization() {
LocalFrame* frame = MakeGarbageCollected<LocalFrame>(
MakeGarbageCollected<EmptyLocalFrameClient>(), *page,
nullptr, // FrameOwner*
+ base::UnguessableToken::Create(),
nullptr, // WindowAgentFactory*
nullptr // InterfaceRegistry*
);
diff --git a/chromium/third_party/blink/renderer/core/editing/spellcheck/cold_mode_spell_check_requester.cc b/chromium/third_party/blink/renderer/core/editing/spellcheck/cold_mode_spell_check_requester.cc
index 1821a5e93fc..5fd35434c38 100644
--- a/chromium/third_party/blink/renderer/core/editing/spellcheck/cold_mode_spell_check_requester.cc
+++ b/chromium/third_party/blink/renderer/core/editing/spellcheck/cold_mode_spell_check_requester.cc
@@ -15,6 +15,7 @@
#include "third_party/blink/renderer/core/editing/spellcheck/spell_checker.h"
#include "third_party/blink/renderer/core/editing/visible_position.h"
#include "third_party/blink/renderer/core/editing/visible_units.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
@@ -28,13 +29,13 @@ const int kInvalidChunkIndex = -1;
} // namespace
void ColdModeSpellCheckRequester::Trace(Visitor* visitor) {
- visitor->Trace(frame_);
+ visitor->Trace(window_);
visitor->Trace(root_editable_);
visitor->Trace(remaining_check_range_);
}
-ColdModeSpellCheckRequester::ColdModeSpellCheckRequester(LocalFrame& frame)
- : frame_(frame),
+ColdModeSpellCheckRequester::ColdModeSpellCheckRequester(LocalDOMWindow& window)
+ : window_(window),
last_chunk_index_(kInvalidChunkIndex),
needs_more_invocation_for_testing_(false) {}
@@ -54,12 +55,12 @@ bool ColdModeSpellCheckRequester::FullyChecked() const {
SpellCheckRequester& ColdModeSpellCheckRequester::GetSpellCheckRequester()
const {
- return GetFrame().GetSpellChecker().GetSpellCheckRequester();
+ return window_->GetSpellChecker().GetSpellCheckRequester();
}
const Element* ColdModeSpellCheckRequester::CurrentFocusedEditable() const {
const Position position =
- GetFrame().Selection().GetSelectionInDOMTree().Extent();
+ window_->GetFrame()->Selection().GetSelectionInDOMTree().Extent();
if (position.IsNull())
return nullptr;
@@ -78,8 +79,7 @@ void ColdModeSpellCheckRequester::Invoke(IdleDeadline* deadline) {
TRACE_EVENT0("blink", "ColdModeSpellCheckRequester::invoke");
// TODO(xiaochengh): Figure out if this has any performance impact.
- GetFrame().GetDocument()->UpdateStyleAndLayout(
- DocumentUpdateReason::kSpellCheck);
+ window_->document()->UpdateStyleAndLayout(DocumentUpdateReason::kSpellCheck);
const Element* current_focused = CurrentFocusedEditable();
if (!current_focused) {
diff --git a/chromium/third_party/blink/renderer/core/editing/spellcheck/cold_mode_spell_check_requester.h b/chromium/third_party/blink/renderer/core/editing/spellcheck/cold_mode_spell_check_requester.h
index 0e6012793e6..100eeba1a7b 100644
--- a/chromium/third_party/blink/renderer/core/editing/spellcheck/cold_mode_spell_check_requester.h
+++ b/chromium/third_party/blink/renderer/core/editing/spellcheck/cold_mode_spell_check_requester.h
@@ -12,7 +12,7 @@
namespace blink {
class Element;
-class LocalFrame;
+class LocalDOMWindow;
class IdleDeadline;
class SpellCheckRequester;
@@ -24,7 +24,7 @@ class SpellCheckRequester;
class ColdModeSpellCheckRequester
: public GarbageCollected<ColdModeSpellCheckRequester> {
public:
- explicit ColdModeSpellCheckRequester(LocalFrame&);
+ explicit ColdModeSpellCheckRequester(LocalDOMWindow&);
void SetNeedsMoreInvocationForTesting() {
needs_more_invocation_for_testing_ = true;
@@ -38,7 +38,6 @@ class ColdModeSpellCheckRequester
void Trace(Visitor*);
private:
- LocalFrame& GetFrame() const { return *frame_; }
SpellCheckRequester& GetSpellCheckRequester() const;
const Element* CurrentFocusedEditable() const;
@@ -46,8 +45,8 @@ class ColdModeSpellCheckRequester
void RequestCheckingForNextChunk();
void SetHasFullyChecked();
- // The LocalFrame this cold mode checker belongs to.
- const Member<LocalFrame> frame_;
+ // The window this cold mode checker belongs to.
+ const Member<LocalDOMWindow> window_;
// The root editable element checked in the last invocation. |nullptr| if not
// invoked yet or didn't find any root editable element to check.
diff --git a/chromium/third_party/blink/renderer/core/editing/spellcheck/idle_spell_check_controller.cc b/chromium/third_party/blink/renderer/core/editing/spellcheck/idle_spell_check_controller.cc
index c3bda605135..79a955961fe 100644
--- a/chromium/third_party/blink/renderer/core/editing/spellcheck/idle_spell_check_controller.cc
+++ b/chromium/third_party/blink/renderer/core/editing/spellcheck/idle_spell_check_controller.cc
@@ -20,8 +20,10 @@
#include "third_party/blink/renderer/core/editing/spellcheck/spell_checker.h"
#include "third_party/blink/renderer/core/editing/visible_selection.h"
#include "third_party/blink/renderer/core/editing/visible_units.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
+#include "third_party/blink/renderer/platform/scheduler/public/post_cancellable_task.h"
namespace blink {
@@ -61,32 +63,40 @@ class IdleSpellCheckController::IdleCallback final
IdleSpellCheckController::~IdleSpellCheckController() = default;
void IdleSpellCheckController::Trace(Visitor* visitor) {
- visitor->Trace(frame_);
visitor->Trace(cold_mode_requester_);
+ visitor->Trace(spell_check_requeseter_);
ExecutionContextLifecycleObserver::Trace(visitor);
}
-IdleSpellCheckController::IdleSpellCheckController(LocalFrame& frame)
- : state_(State::kInactive),
+IdleSpellCheckController::IdleSpellCheckController(
+ LocalDOMWindow& window,
+ SpellCheckRequester& requester)
+ : ExecutionContextLifecycleObserver(&window),
+ state_(State::kInactive),
idle_callback_handle_(kInvalidHandle),
- frame_(frame),
last_processed_undo_step_sequence_(0),
cold_mode_requester_(
- MakeGarbageCollected<ColdModeSpellCheckRequester>(frame)),
- cold_mode_timer_(frame.GetTaskRunner(TaskType::kInternalDefault),
- this,
- &IdleSpellCheckController::ColdModeTimerFired) {}
+ MakeGarbageCollected<ColdModeSpellCheckRequester>(window)),
+ spell_check_requeseter_(requester) {}
-SpellCheckRequester& IdleSpellCheckController::GetSpellCheckRequester() const {
- return GetFrame().GetSpellChecker().GetSpellCheckRequester();
+LocalDOMWindow& IdleSpellCheckController::GetWindow() const {
+ DCHECK(GetExecutionContext());
+ return *To<LocalDOMWindow>(GetExecutionContext());
+}
+
+Document& IdleSpellCheckController::GetDocument() const {
+ DCHECK(GetExecutionContext());
+ return *GetWindow().document();
}
bool IdleSpellCheckController::IsSpellCheckingEnabled() const {
- return GetFrame().GetSpellChecker().IsSpellCheckingEnabled();
+ if (!GetExecutionContext())
+ return false;
+ return GetWindow().GetSpellChecker().IsSpellCheckingEnabled();
}
void IdleSpellCheckController::DisposeIdleCallback() {
- if (idle_callback_handle_ != kInvalidHandle && IsAvailable())
+ if (idle_callback_handle_ != kInvalidHandle && GetExecutionContext())
GetDocument().CancelIdleCallback(idle_callback_handle_);
idle_callback_handle_ = kInvalidHandle;
}
@@ -94,14 +104,14 @@ void IdleSpellCheckController::DisposeIdleCallback() {
void IdleSpellCheckController::Deactivate() {
state_ = State::kInactive;
if (cold_mode_timer_.IsActive())
- cold_mode_timer_.Stop();
+ cold_mode_timer_.Cancel();
cold_mode_requester_->ClearProgress();
DisposeIdleCallback();
- GetSpellCheckRequester().Deactivate();
+ spell_check_requeseter_->Deactivate();
}
void IdleSpellCheckController::SetNeedsInvocation() {
- if (!IsSpellCheckingEnabled() || !IsAvailable()) {
+ if (!IsSpellCheckingEnabled()) {
Deactivate();
return;
}
@@ -113,7 +123,7 @@ void IdleSpellCheckController::SetNeedsInvocation() {
if (state_ == State::kColdModeTimerStarted) {
DCHECK(cold_mode_timer_.IsActive());
- cold_mode_timer_.Stop();
+ cold_mode_timer_.Cancel();
}
if (state_ == State::kColdModeRequested)
@@ -127,11 +137,7 @@ void IdleSpellCheckController::SetNeedsInvocation() {
}
void IdleSpellCheckController::SetNeedsColdModeInvocation() {
- if (!IsSpellCheckingEnabled()) {
- Deactivate();
- return;
- }
-
+ DCHECK(IsSpellCheckingEnabled());
if (state_ != State::kInactive && state_ != State::kInHotModeInvocation &&
state_ != State::kInColdModeInvocation)
return;
@@ -140,14 +146,18 @@ void IdleSpellCheckController::SetNeedsColdModeInvocation() {
base::TimeDelta interval = state_ == State::kInColdModeInvocation
? kConsecutiveColdModeTimerInterval
: kColdModeTimerInterval;
- cold_mode_timer_.StartOneShot(interval, FROM_HERE);
+ cold_mode_timer_ = PostDelayedCancellableTask(
+ *GetWindow().GetTaskRunner(TaskType::kInternalDefault), FROM_HERE,
+ WTF::Bind(&IdleSpellCheckController::ColdModeTimerFired,
+ WrapPersistent(this)),
+ interval);
state_ = State::kColdModeTimerStarted;
}
-void IdleSpellCheckController::ColdModeTimerFired(TimerBase*) {
+void IdleSpellCheckController::ColdModeTimerFired() {
DCHECK_EQ(State::kColdModeTimerStarted, state_);
- if (!IsSpellCheckingEnabled() || !IsAvailable()) {
+ if (!IsSpellCheckingEnabled()) {
Deactivate();
return;
}
@@ -163,14 +173,14 @@ void IdleSpellCheckController::HotModeInvocation(IdleDeadline* deadline) {
// TODO(xiaochengh): Figure out if this has any performance impact.
GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing);
- HotModeSpellCheckRequester requester(GetSpellCheckRequester());
+ HotModeSpellCheckRequester requester(*spell_check_requeseter_);
requester.CheckSpellingAt(
- GetFrame().Selection().GetSelectionInDOMTree().Extent());
+ GetWindow().GetFrame()->Selection().GetSelectionInDOMTree().Extent());
const uint64_t watermark = last_processed_undo_step_sequence_;
for (const UndoStep* step :
- GetFrame().GetEditor().GetUndoStack().UndoSteps()) {
+ GetWindow().GetFrame()->GetEditor().GetUndoStack().UndoSteps()) {
if (step->SequenceNumber() <= watermark)
break;
last_processed_undo_step_sequence_ =
@@ -190,7 +200,7 @@ void IdleSpellCheckController::Invoke(IdleDeadline* deadline) {
DCHECK_NE(idle_callback_handle_, kInvalidHandle);
idle_callback_handle_ = kInvalidHandle;
- if (!IsSpellCheckingEnabled() || !IsAvailable()) {
+ if (!IsSpellCheckingEnabled()) {
Deactivate();
return;
}
@@ -211,10 +221,6 @@ void IdleSpellCheckController::Invoke(IdleDeadline* deadline) {
}
}
-void IdleSpellCheckController::DidAttachDocument(Document* document) {
- SetExecutionContext(document->ToExecutionContext());
-}
-
void IdleSpellCheckController::ContextDestroyed() {
Deactivate();
}
@@ -229,7 +235,7 @@ void IdleSpellCheckController::ForceInvocationForTesting() {
switch (state_) {
case State::kColdModeTimerStarted:
- cold_mode_timer_.Stop();
+ cold_mode_timer_.Cancel();
state_ = State::kColdModeRequested;
idle_callback_handle_ = kDummyHandleForForcedInvocation;
Invoke(deadline);
@@ -248,8 +254,8 @@ void IdleSpellCheckController::ForceInvocationForTesting() {
void IdleSpellCheckController::SkipColdModeTimerForTesting() {
DCHECK(cold_mode_timer_.IsActive());
- cold_mode_timer_.Stop();
- ColdModeTimerFired(&cold_mode_timer_);
+ cold_mode_timer_.Cancel();
+ ColdModeTimerFired();
}
void IdleSpellCheckController::SetNeedsMoreColdModeInvocationForTesting() {
diff --git a/chromium/third_party/blink/renderer/core/editing/spellcheck/idle_spell_check_controller.h b/chromium/third_party/blink/renderer/core/editing/spellcheck/idle_spell_check_controller.h
index 171a8adc367..b2c3f7120bf 100644
--- a/chromium/third_party/blink/renderer/core/editing/spellcheck/idle_spell_check_controller.h
+++ b/chromium/third_party/blink/renderer/core/editing/spellcheck/idle_spell_check_controller.h
@@ -5,16 +5,16 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_SPELLCHECK_IDLE_SPELL_CHECK_CONTROLLER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_SPELLCHECK_IDLE_SPELL_CHECK_CONTROLLER_H_
-#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/scripted_idle_task_controller.h"
#include "third_party/blink/renderer/core/editing/forward.h"
#include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.h"
-#include "third_party/blink/renderer/platform/timer.h"
+#include "third_party/blink/renderer/platform/scheduler/public/post_cancellable_task.h"
namespace blink {
class ColdModeSpellCheckRequester;
-class LocalFrame;
+class Document;
+class LocalDOMWindow;
class SpellCheckRequester;
#define FOR_EACH_IDLE_SPELL_CHECK_CONTROLLER_STATE(V) \
@@ -34,7 +34,7 @@ class CORE_EXPORT IdleSpellCheckController final
USING_GARBAGE_COLLECTED_MIXIN(IdleSpellCheckController);
public:
- explicit IdleSpellCheckController(LocalFrame&);
+ explicit IdleSpellCheckController(LocalDOMWindow&, SpellCheckRequester&);
~IdleSpellCheckController();
enum class State {
@@ -53,8 +53,6 @@ class CORE_EXPORT IdleSpellCheckController final
// document is detached or spellchecking is globally disabled.
void Deactivate();
- void DidAttachDocument(Document*);
-
// Exposed for testing only.
SpellCheckRequester& GetSpellCheckRequester() const;
void ForceInvocationForTesting();
@@ -67,16 +65,11 @@ class CORE_EXPORT IdleSpellCheckController final
private:
class IdleCallback;
- LocalFrame& GetFrame() const { return *frame_; }
-
- // Returns whether there is an active document to work on.
- bool IsAvailable() const { return GetExecutionContext(); }
+ LocalDOMWindow& GetWindow() const;
- // Return the document to work on. Callable only when IsAvailable() is true.
- Document& GetDocument() const {
- DCHECK(IsAvailable());
- return *Document::From(GetExecutionContext());
- }
+ // Return the document to work on. Callable only when GetExecutionContext()
+ // is non-null.
+ Document& GetDocument() const;
// Returns whether spell checking is globally enabled.
bool IsSpellCheckingEnabled() const;
@@ -92,7 +85,7 @@ class CORE_EXPORT IdleSpellCheckController final
void SetNeedsColdModeInvocation();
// Functions for cold mode.
- void ColdModeTimerFired(TimerBase*);
+ void ColdModeTimerFired();
void ColdModeInvocation(IdleDeadline*);
// Implements |ExecutionContextLifecycleObserver|.
@@ -102,10 +95,10 @@ class CORE_EXPORT IdleSpellCheckController final
State state_;
int idle_callback_handle_;
- const Member<LocalFrame> frame_;
uint64_t last_processed_undo_step_sequence_;
const Member<ColdModeSpellCheckRequester> cold_mode_requester_;
- TaskRunnerTimer<IdleSpellCheckController> cold_mode_timer_;
+ Member<SpellCheckRequester> spell_check_requeseter_;
+ TaskHandle cold_mode_timer_;
friend class IdleSpellCheckControllerTest;
};
diff --git a/chromium/third_party/blink/renderer/core/editing/spellcheck/spell_check_requester.cc b/chromium/third_party/blink/renderer/core/editing/spellcheck/spell_check_requester.cc
index c84093f2124..a0a3ffc5ee9 100644
--- a/chromium/third_party/blink/renderer/core/editing/spellcheck/spell_check_requester.cc
+++ b/chromium/third_party/blink/renderer/core/editing/spellcheck/spell_check_requester.cc
@@ -35,8 +35,7 @@
#include "third_party/blink/renderer/core/editing/ephemeral_range.h"
#include "third_party/blink/renderer/core/editing/markers/document_marker_controller.h"
#include "third_party/blink/renderer/core/editing/spellcheck/spell_checker.h"
-#include "third_party/blink/renderer/core/frame/local_frame.h"
-#include "third_party/blink/renderer/core/frame/settings.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/html/forms/text_control_element.h"
#include "third_party/blink/renderer/platform/instrumentation/histogram.h"
@@ -165,22 +164,18 @@ void SpellCheckRequest::SetCheckerAndSequence(SpellCheckRequester* requester,
sequence_ = sequence;
}
-SpellCheckRequester::SpellCheckRequester(LocalFrame& frame)
- : frame_(&frame),
+SpellCheckRequester::SpellCheckRequester(LocalDOMWindow& window)
+ : window_(&window),
last_request_sequence_(0),
- last_processed_sequence_(0),
- timer_to_process_queued_request_(
- frame.GetTaskRunner(TaskType::kInternalDefault),
- this,
- &SpellCheckRequester::TimerFiredToProcessQueuedRequest) {}
+ last_processed_sequence_(0) {}
SpellCheckRequester::~SpellCheckRequester() = default;
WebTextCheckClient* SpellCheckRequester::GetTextCheckerClient() const {
- return GetFrame().GetSpellChecker().GetTextCheckerClient();
+ return window_->GetSpellChecker().GetTextCheckerClient();
}
-void SpellCheckRequester::TimerFiredToProcessQueuedRequest(TimerBase*) {
+void SpellCheckRequester::TimerFiredToProcessQueuedRequest() {
DCHECK(!request_queue_.IsEmpty());
if (request_queue_.IsEmpty())
return;
@@ -227,7 +222,7 @@ void SpellCheckRequester::CancelCheck() {
}
void SpellCheckRequester::Deactivate() {
- timer_to_process_queued_request_.Stop();
+ timer_to_process_queued_request_.Cancel();
// Empty all pending requests to prevent them from being a leak source, as the
// requests may hold reference to a closed document.
request_queue_.clear();
@@ -296,8 +291,12 @@ void SpellCheckRequester::DidCheck(int sequence) {
last_processed_sequence_ = sequence;
ClearProcessingRequest();
- if (!request_queue_.IsEmpty())
- timer_to_process_queued_request_.StartOneShot(base::TimeDelta(), FROM_HERE);
+ if (!request_queue_.IsEmpty()) {
+ timer_to_process_queued_request_ = PostCancellableTask(
+ *window_->GetTaskRunner(TaskType::kInternalDefault), FROM_HERE,
+ WTF::Bind(&SpellCheckRequester::TimerFiredToProcessQueuedRequest,
+ WrapPersistent(this)));
+ }
}
void SpellCheckRequester::DidCheckSucceed(
@@ -305,7 +304,7 @@ void SpellCheckRequester::DidCheckSucceed(
const Vector<TextCheckingResult>& results) {
if (!EnsureValidRequestQueueFor(sequence))
return;
- GetFrame().GetSpellChecker().MarkAndReplaceFor(processing_request_, results);
+ window_->GetSpellChecker().MarkAndReplaceFor(processing_request_, results);
DidCheck(sequence);
}
@@ -316,7 +315,7 @@ void SpellCheckRequester::DidCheckCancel(int sequence) {
}
void SpellCheckRequester::Trace(Visitor* visitor) {
- visitor->Trace(frame_);
+ visitor->Trace(window_);
visitor->Trace(processing_request_);
visitor->Trace(request_queue_);
}
diff --git a/chromium/third_party/blink/renderer/core/editing/spellcheck/spell_check_requester.h b/chromium/third_party/blink/renderer/core/editing/spellcheck/spell_check_requester.h
index 02c197d2943..18bb605fa35 100644
--- a/chromium/third_party/blink/renderer/core/editing/spellcheck/spell_check_requester.h
+++ b/chromium/third_party/blink/renderer/core/editing/spellcheck/spell_check_requester.h
@@ -32,14 +32,14 @@
#include "third_party/blink/renderer/core/dom/range.h"
#include "third_party/blink/renderer/core/editing/forward.h"
#include "third_party/blink/renderer/core/editing/spellcheck/text_checking.h"
-#include "third_party/blink/renderer/platform/timer.h"
+#include "third_party/blink/renderer/platform/scheduler/public/post_cancellable_task.h"
#include "third_party/blink/renderer/platform/wtf/deque.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
namespace blink {
-class LocalFrame;
+class LocalDOMWindow;
class SpellCheckRequester;
class WebTextCheckClient;
@@ -82,7 +82,7 @@ class CORE_EXPORT SpellCheckRequest final
class CORE_EXPORT SpellCheckRequester final
: public GarbageCollected<SpellCheckRequester> {
public:
- explicit SpellCheckRequester(LocalFrame&);
+ explicit SpellCheckRequester(LocalDOMWindow&);
~SpellCheckRequester();
void Trace(Visitor*);
@@ -103,7 +103,7 @@ class CORE_EXPORT SpellCheckRequester final
friend class SpellCheckRequest;
WebTextCheckClient* GetTextCheckerClient() const;
- void TimerFiredToProcessQueuedRequest(TimerBase*);
+ void TimerFiredToProcessQueuedRequest();
void InvokeRequest(SpellCheckRequest*);
void EnqueueRequest(SpellCheckRequest*);
bool EnsureValidRequestQueueFor(int sequence);
@@ -113,17 +113,13 @@ class CORE_EXPORT SpellCheckRequester final
void ClearProcessingRequest();
- Member<LocalFrame> frame_;
- LocalFrame& GetFrame() const {
- DCHECK(frame_);
- return *frame_;
- }
+ Member<LocalDOMWindow> window_;
int last_request_sequence_;
int last_processed_sequence_;
base::TimeTicks last_request_time_;
- TaskRunnerTimer<SpellCheckRequester> timer_to_process_queued_request_;
+ TaskHandle timer_to_process_queued_request_;
Member<SpellCheckRequest> processing_request_;
diff --git a/chromium/third_party/blink/renderer/core/editing/spellcheck/spell_checker.cc b/chromium/third_party/blink/renderer/core/editing/spellcheck/spell_checker.cc
index d5b3c0c0f19..57e3e2f7b46 100644
--- a/chromium/third_party/blink/renderer/core/editing/spellcheck/spell_checker.cc
+++ b/chromium/third_party/blink/renderer/core/editing/spellcheck/spell_checker.cc
@@ -48,6 +48,7 @@
#include "third_party/blink/renderer/core/editing/spellcheck/text_checking_paragraph.h"
#include "third_party/blink/renderer/core/editing/visible_position.h"
#include "third_party/blink/renderer/core/editing/visible_units.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/html/forms/html_input_element.h"
#include "third_party/blink/renderer/core/html_names.h"
@@ -100,11 +101,18 @@ WebTextCheckClient* SpellChecker::GetTextCheckerClient() const {
return GetFrame().Client()->GetTextCheckerClient();
}
-SpellChecker::SpellChecker(LocalFrame& frame)
- : frame_(&frame),
- spell_check_requester_(MakeGarbageCollected<SpellCheckRequester>(frame)),
+SpellChecker::SpellChecker(LocalDOMWindow& window)
+ : window_(&window),
+ spell_check_requester_(MakeGarbageCollected<SpellCheckRequester>(window)),
idle_spell_check_controller_(
- MakeGarbageCollected<IdleSpellCheckController>(frame)) {}
+ MakeGarbageCollected<IdleSpellCheckController>(
+ window,
+ *spell_check_requester_)) {}
+
+LocalFrame& SpellChecker::GetFrame() const {
+ DCHECK(window_->GetFrame());
+ return *window_->GetFrame();
+}
bool SpellChecker::IsSpellCheckingEnabled() const {
if (WebTextCheckClient* client = GetTextCheckerClient())
@@ -412,7 +420,8 @@ void SpellChecker::RemoveSpellingAndGrammarMarkers(const HTMLElement& element,
ElementsType elements_type) {
// TODO(editing-dev): The use of updateStyleAndLayoutIgnorePendingStylesheets
// needs to be audited. See http://crbug.com/590369 for more details.
- GetFrame().GetDocument()->UpdateStyleAndLayoutTreeForNode(&element);
+ if (elements_type == ElementsType::kOnlyNonEditable)
+ GetFrame().GetDocument()->UpdateStyleAndLayoutTreeForNode(&element);
for (Node& node : NodeTraversal::InclusiveDescendantsOf(element)) {
auto* text_node = DynamicTo<Text>(node);
@@ -598,12 +607,8 @@ void SpellChecker::RemoveMarkers(const EphemeralRange& range,
GetFrame().GetDocument()->Markers().RemoveMarkersInRange(range, marker_types);
}
-void SpellChecker::DidAttachDocument(Document* document) {
- idle_spell_check_controller_->DidAttachDocument(document);
-}
-
void SpellChecker::Trace(Visitor* visitor) {
- visitor->Trace(frame_);
+ visitor->Trace(window_);
visitor->Trace(spell_check_requester_);
visitor->Trace(idle_spell_check_controller_);
}
diff --git a/chromium/third_party/blink/renderer/core/editing/spellcheck/spell_checker.h b/chromium/third_party/blink/renderer/core/editing/spellcheck/spell_checker.h
index a0f95b20f39..8144c0f224e 100644
--- a/chromium/third_party/blink/renderer/core/editing/spellcheck/spell_checker.h
+++ b/chromium/third_party/blink/renderer/core/editing/spellcheck/spell_checker.h
@@ -35,9 +35,9 @@
namespace blink {
-class Document;
class Element;
class IdleSpellCheckController;
+class LocalDOMWindow;
class LocalFrame;
class HTMLElement;
class SpellCheckMarker;
@@ -49,7 +49,7 @@ class WebTextCheckClient;
class CORE_EXPORT SpellChecker final : public GarbageCollected<SpellChecker> {
public:
- explicit SpellChecker(LocalFrame&);
+ explicit SpellChecker(LocalDOMWindow&);
void Trace(Visitor*);
@@ -88,13 +88,8 @@ class CORE_EXPORT SpellChecker final : public GarbageCollected<SpellChecker> {
return *idle_spell_check_controller_;
}
- void DidAttachDocument(Document*);
-
private:
- LocalFrame& GetFrame() const {
- DCHECK(frame_);
- return *frame_;
- }
+ LocalFrame& GetFrame() const;
// Helper functions for advanceToNextMisspelling()
Vector<TextCheckingResult> FindMisspellings(const String&);
@@ -102,7 +97,7 @@ class CORE_EXPORT SpellChecker final : public GarbageCollected<SpellChecker> {
void RemoveMarkers(const EphemeralRange&, DocumentMarker::MarkerTypes);
- Member<LocalFrame> frame_;
+ Member<LocalDOMWindow> window_;
const Member<SpellCheckRequester> spell_check_requester_;
const Member<IdleSpellCheckController> idle_spell_check_controller_;
diff --git a/chromium/third_party/blink/renderer/core/editing/suggestion/text_suggestion_controller.cc b/chromium/third_party/blink/renderer/core/editing/suggestion/text_suggestion_controller.cc
index 748094ca5cf..aa9d982eeb3 100644
--- a/chromium/third_party/blink/renderer/core/editing/suggestion/text_suggestion_controller.cc
+++ b/chromium/third_party/blink/renderer/core/editing/suggestion/text_suggestion_controller.cc
@@ -20,6 +20,7 @@
#include "third_party/blink/renderer/core/editing/spellcheck/spell_checker.h"
#include "third_party/blink/renderer/core/editing/suggestion/text_suggestion_info.h"
#include "third_party/blink/renderer/core/frame/frame_view.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/settings.h"
#include "third_party/blink/renderer/core/layout/layout_theme.h"
@@ -192,13 +193,10 @@ SuggestionInfosWithNodeAndHighlightColor ComputeSuggestionInfos(
} // namespace
-TextSuggestionController::TextSuggestionController(LocalFrame& frame)
- : is_suggestion_menu_open_(false), frame_(&frame) {}
-
-void TextSuggestionController::DidAttachDocument(Document* document) {
- DCHECK(document);
- SetExecutionContext(document->ToExecutionContext());
-}
+TextSuggestionController::TextSuggestionController(LocalDOMWindow& window)
+ : is_suggestion_menu_open_(false),
+ window_(&window),
+ text_suggestion_host_(&window) {}
bool TextSuggestionController::IsMenuOpen() const {
return is_suggestion_menu_open_;
@@ -243,17 +241,18 @@ void TextSuggestionController::HandlePotentialSuggestionTap(
if (marker && marker->Suggestions().IsEmpty())
return;
- if (!text_suggestion_host_) {
+ if (!text_suggestion_host_.is_bound()) {
GetFrame().GetBrowserInterfaceBroker().GetInterface(
- text_suggestion_host_.BindNewPipeAndPassReceiver());
+ text_suggestion_host_.BindNewPipeAndPassReceiver(
+ GetFrame().GetTaskRunner(TaskType::kMiscPlatformAPI)));
}
text_suggestion_host_->StartSuggestionMenuTimer();
}
void TextSuggestionController::Trace(Visitor* visitor) {
- visitor->Trace(frame_);
- ExecutionContextLifecycleObserver::Trace(visitor);
+ visitor->Trace(window_);
+ visitor->Trace(text_suggestion_host_);
}
void TextSuggestionController::ReplaceActiveSuggestionRange(
@@ -535,16 +534,16 @@ void TextSuggestionController::CallMojoShowTextSuggestionMenu(
Document& TextSuggestionController::GetDocument() const {
DCHECK(IsAvailable());
- return *Document::From(GetExecutionContext());
+ return *window_->document();
}
bool TextSuggestionController::IsAvailable() const {
- return GetExecutionContext();
+ return !window_->IsContextDestroyed();
}
LocalFrame& TextSuggestionController::GetFrame() const {
- DCHECK(frame_);
- return *frame_;
+ DCHECK(window_->GetFrame());
+ return *window_->GetFrame();
}
std::pair<const Node*, const DocumentMarker*>
diff --git a/chromium/third_party/blink/renderer/core/editing/suggestion/text_suggestion_controller.h b/chromium/third_party/blink/renderer/core/editing/suggestion/text_suggestion_controller.h
index 29b70a243ef..40b2620e9df 100644
--- a/chromium/third_party/blink/renderer/core/editing/suggestion/text_suggestion_controller.h
+++ b/chromium/third_party/blink/renderer/core/editing/suggestion/text_suggestion_controller.h
@@ -6,7 +6,6 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_SUGGESTION_TEXT_SUGGESTION_CONTROLLER_H_
#include <utility>
-#include "mojo/public/cpp/bindings/remote.h"
#include "third_party/blink/public/mojom/input/input_host.mojom-blink.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/dom/document.h"
@@ -14,11 +13,14 @@
#include "third_party/blink/renderer/core/editing/markers/document_marker.h"
#include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
+#include "third_party/blink/renderer/platform/mojo/heap_mojo_remote.h"
+#include "third_party/blink/renderer/platform/mojo/heap_mojo_wrapper_mode.h"
namespace blink {
class Document;
class DocumentMarker;
+class LocalDOMWindow;
class LocalFrame;
struct TextSuggestionInfo;
@@ -26,14 +28,9 @@ struct TextSuggestionInfo;
// suggestions (e.g. from spellcheck), and performing actions relating to those
// suggestions. Android is currently the only platform that has such a menu.
class CORE_EXPORT TextSuggestionController final
- : public GarbageCollected<TextSuggestionController>,
- public ExecutionContextLifecycleObserver {
- USING_GARBAGE_COLLECTED_MIXIN(TextSuggestionController);
-
+ : public GarbageCollected<TextSuggestionController> {
public:
- explicit TextSuggestionController(LocalFrame&);
-
- void DidAttachDocument(Document*);
+ explicit TextSuggestionController(LocalDOMWindow&);
bool IsMenuOpen() const;
@@ -46,10 +43,7 @@ class CORE_EXPORT TextSuggestionController final
void OnSuggestionMenuClosed();
void SuggestionMenuTimeoutCallback(size_t max_number_of_suggestions);
- // ExecutionContextLifecycleObserver methods:
- void ContextDestroyed() override {}
-
- void Trace(Visitor*) override;
+ virtual void Trace(Visitor*);
private:
friend class TextSuggestionControllerTest;
@@ -77,8 +71,10 @@ class CORE_EXPORT TextSuggestionController final
void ReplaceRangeWithText(const EphemeralRange&, const String& replacement);
bool is_suggestion_menu_open_;
- const Member<LocalFrame> frame_;
- mojo::Remote<mojom::blink::TextSuggestionHost> text_suggestion_host_;
+ const Member<LocalDOMWindow> window_;
+ HeapMojoRemote<mojom::blink::TextSuggestionHost,
+ HeapMojoWrapperMode::kWithoutContextObserver>
+ text_suggestion_host_;
DISALLOW_COPY_AND_ASSIGN(TextSuggestionController);
};
diff --git a/chromium/third_party/blink/renderer/core/editing/suggestion/text_suggestion_controller_test.cc b/chromium/third_party/blink/renderer/core/editing/suggestion/text_suggestion_controller_test.cc
index d2a6e5a1f8a..6646cf07797 100644
--- a/chromium/third_party/blink/renderer/core/editing/suggestion/text_suggestion_controller_test.cc
+++ b/chromium/third_party/blink/renderer/core/editing/suggestion/text_suggestion_controller_test.cc
@@ -25,7 +25,7 @@ class TextSuggestionControllerTest : public EditingTestBase {
return bool(GetDocument()
.GetFrame()
->GetTextSuggestionController()
- .text_suggestion_host_);
+ .text_suggestion_host_.is_bound());
}
void ShowSuggestionMenu(
diff --git a/chromium/third_party/blink/renderer/core/editing/visible_position_test.cc b/chromium/third_party/blink/renderer/core/editing/visible_position_test.cc
index 9a5adde5b36..3d71e51c2d0 100644
--- a/chromium/third_party/blink/renderer/core/editing/visible_position_test.cc
+++ b/chromium/third_party/blink/renderer/core/editing/visible_position_test.cc
@@ -89,14 +89,14 @@ TEST_F(VisiblePositionTest, NonNullInvalidatedAfterStyleChange) {
Position position(paragraph->firstChild(), 1);
VisiblePosition visible_position1 = CreateVisiblePosition(position);
- div->style()->setProperty(GetDocument().ToExecutionContext(), "color", "red",
+ div->style()->setProperty(GetDocument().GetExecutionContext(), "color", "red",
"important", ASSERT_NO_EXCEPTION);
EXPECT_FALSE(visible_position1.IsValid());
UpdateAllLifecyclePhasesForTest();
VisiblePosition visible_position2 = CreateVisiblePosition(position);
- div->style()->setProperty(GetDocument().ToExecutionContext(), "display",
+ div->style()->setProperty(GetDocument().GetExecutionContext(), "display",
"none", "important", ASSERT_NO_EXCEPTION);
EXPECT_FALSE(visible_position2.IsValid());
diff --git a/chromium/third_party/blink/renderer/core/editing/visible_units_line.cc b/chromium/third_party/blink/renderer/core/editing/visible_units_line.cc
index 46334945df3..766bba980ae 100644
--- a/chromium/third_party/blink/renderer/core/editing/visible_units_line.cc
+++ b/chromium/third_party/blink/renderer/core/editing/visible_units_line.cc
@@ -70,7 +70,7 @@ PositionWithAffinityTemplate<Strategy> StartPositionForLine(
NGInlineCursor line_box = caret_position.cursor;
line_box.MoveToContainingLine();
DCHECK(line_box.Current().IsLineBox()) << line_box;
- const PhysicalOffset start_point = line_box.LineStartPoint();
+ const PhysicalOffset start_point = line_box.Current().LineStartPoint();
return FromPositionInDOMTree<Strategy>(
line_box.PositionForPointInInlineBox(start_point));
}
@@ -252,7 +252,7 @@ static PositionWithAffinityTemplate<Strategy> EndPositionForLine(
}
NGInlineCursor line_box = caret_position.cursor;
line_box.MoveToContainingLine();
- const PhysicalOffset end_point = line_box.LineEndPoint();
+ const PhysicalOffset end_point = line_box.Current().LineEndPoint();
return FromPositionInDOMTree<Strategy>(
line_box.PositionForPointInInlineBox(end_point));
}
diff --git a/chromium/third_party/blink/renderer/core/editing/web_substring_util.mm b/chromium/third_party/blink/renderer/core/editing/web_substring_util.mm
index a966c7852ed..a90af365634 100644
--- a/chromium/third_party/blink/renderer/core/editing/web_substring_util.mm
+++ b/chromium/third_party/blink/renderer/core/editing/web_substring_util.mm
@@ -161,7 +161,7 @@ NSAttributedString* WebSubstringUtil::AttributedWordAtPoint(
gfx::Point point,
gfx::Point& baseline_point) {
HitTestResult result = static_cast<WebFrameWidgetBase*>(frame_widget)
- ->CoreHitTestResultAt(IntPoint(point));
+ ->CoreHitTestResultAt(FloatPoint(IntPoint(point)));
if (!result.InnerNode())
return nil;
diff --git a/chromium/third_party/blink/renderer/core/events/animation_playback_event.cc b/chromium/third_party/blink/renderer/core/events/animation_playback_event.cc
index a1f113c9a25..e669632cac3 100644
--- a/chromium/third_party/blink/renderer/core/events/animation_playback_event.cc
+++ b/chromium/third_party/blink/renderer/core/events/animation_playback_event.cc
@@ -36,16 +36,6 @@ AnimationPlaybackEvent::AnimationPlaybackEvent(
AnimationPlaybackEvent::~AnimationPlaybackEvent() = default;
-double AnimationPlaybackEvent::currentTime(bool& is_null) const {
- is_null = !current_time_.has_value();
- return current_time_.value_or(0);
-}
-
-double AnimationPlaybackEvent::timelineTime(bool& is_null) const {
- is_null = !timeline_time_.has_value();
- return timeline_time_.value_or(0);
-}
-
const AtomicString& AnimationPlaybackEvent::InterfaceName() const {
return event_interface_names::kAnimationPlaybackEvent;
}
diff --git a/chromium/third_party/blink/renderer/core/events/animation_playback_event.h b/chromium/third_party/blink/renderer/core/events/animation_playback_event.h
index de5a081d84b..3a779e353b0 100644
--- a/chromium/third_party/blink/renderer/core/events/animation_playback_event.h
+++ b/chromium/third_party/blink/renderer/core/events/animation_playback_event.h
@@ -31,9 +31,6 @@ class AnimationPlaybackEvent final : public Event {
base::Optional<double> currentTime() const { return current_time_; }
base::Optional<double> timelineTime() const { return timeline_time_; }
- // TODO(crbug.com/1060971): Remove |is_null| version.
- double currentTime(bool& is_null) const; // DEPRECATED
- double timelineTime(bool& is_null) const; // DEPRECATED
const AtomicString& InterfaceName() const override;
diff --git a/chromium/third_party/blink/renderer/core/events/application_cache_error_event.cc b/chromium/third_party/blink/renderer/core/events/application_cache_error_event.cc
index 2bf16a6928a..1897d0bdb1d 100644
--- a/chromium/third_party/blink/renderer/core/events/application_cache_error_event.cc
+++ b/chromium/third_party/blink/renderer/core/events/application_cache_error_event.cc
@@ -57,7 +57,6 @@ ApplicationCacheErrorEvent::ApplicationCacheErrorEvent(
const AtomicString& event_type,
const ApplicationCacheErrorEventInit* initializer)
: Event(event_type, initializer), status_(0) {
- DCHECK(RuntimeEnabledFeatures::AppCacheEnabled());
if (initializer->hasReason())
reason_ = initializer->reason();
if (initializer->hasUrl())
diff --git a/chromium/third_party/blink/renderer/core/events/application_cache_error_event.idl b/chromium/third_party/blink/renderer/core/events/application_cache_error_event.idl
index c5c59b49a95..040c370b258 100644
--- a/chromium/third_party/blink/renderer/core/events/application_cache_error_event.idl
+++ b/chromium/third_party/blink/renderer/core/events/application_cache_error_event.idl
@@ -9,6 +9,7 @@
// https://www.w3.org/Bugs/Public/show_bug.cgi?id=22702
[
+ Exposed=Window,
RuntimeEnabled=AppCache,
SecureContext=RestrictAppCacheToSecureContexts
] interface ApplicationCacheErrorEvent : Event {
diff --git a/chromium/third_party/blink/renderer/core/events/error_event.cc b/chromium/third_party/blink/renderer/core/events/error_event.cc
index 57d3110b656..6809893c57d 100644
--- a/chromium/third_party/blink/renderer/core/events/error_event.cc
+++ b/chromium/third_party/blink/renderer/core/events/error_event.cc
@@ -60,14 +60,23 @@ ErrorEvent::ErrorEvent(ScriptState* script_state,
: Event(type, initializer),
sanitized_message_(),
world_(&script_state->World()) {
- if (initializer->hasMessage())
- sanitized_message_ = initializer->message();
- location_ = std::make_unique<SourceLocation>(
- initializer->hasFilename() ? initializer->filename() : String(),
- initializer->hasLineno() ? initializer->lineno() : 0,
- initializer->hasColno() ? initializer->colno() : 0, nullptr);
+ sanitized_message_ = initializer->message();
+ location_ = std::make_unique<SourceLocation>(initializer->filename(),
+ initializer->lineno(),
+ initializer->colno(), nullptr);
+ // TODO(crbug.com/1070964): Remove this existence check. There is a bug that
+ // the current code generator does not initialize a ScriptValue with the
+ // v8::Null value despite that the dictionary member has the default value of
+ // IDL null. |hasError| guard is necessary here.
if (initializer->hasError()) {
- error_.Set(script_state->GetIsolate(), initializer->error().V8Value());
+ v8::Local<v8::Value> error = initializer->error().V8Value();
+ // TODO(crbug.com/1070871): Remove the following IsNullOrUndefined() check.
+ // This null/undefined check fills the gap between the new and old bindings
+ // code. The new behavior is preferred in a long term, and we'll switch to
+ // the new behavior once the migration to the new bindings gets settled.
+ if (!error->IsNullOrUndefined()) {
+ error_.Set(script_state->GetIsolate(), error);
+ }
}
}
diff --git a/chromium/third_party/blink/renderer/core/events/error_event_init.idl b/chromium/third_party/blink/renderer/core/events/error_event_init.idl
index 29426b728a0..7df17a32fcc 100644
--- a/chromium/third_party/blink/renderer/core/events/error_event_init.idl
+++ b/chromium/third_party/blink/renderer/core/events/error_event_init.idl
@@ -5,9 +5,9 @@
// https://html.spec.whatwg.org/C/#the-errorevent-interface
dictionary ErrorEventInit : EventInit {
- DOMString message;
- DOMString filename;
- unsigned long lineno;
- unsigned long colno;
- any error;
+ DOMString message = "";
+ DOMString filename = "";
+ unsigned long lineno = 0;
+ unsigned long colno = 0;
+ any error = null;
};
diff --git a/chromium/third_party/blink/renderer/core/events/event_type_names.json5 b/chromium/third_party/blink/renderer/core/events/event_type_names.json5
index 90d76aae98d..be9f251243f 100644
--- a/chromium/third_party/blink/renderer/core/events/event_type_names.json5
+++ b/chromium/third_party/blink/renderer/core/events/event_type_names.json5
@@ -24,7 +24,6 @@
"accessibleincrement",
"accessiblescrollintoview",
"activate",
- "activateinvisible",
"active",
"addsourcebuffer",
"addstream",
@@ -45,6 +44,7 @@
"backgroundfetchclick",
"backgroundfetchfail",
"backgroundfetchsuccess",
+ "beforematch",
"beforecopy",
"beforecut",
"beforeinput",
@@ -199,6 +199,7 @@
"open",
"orientationchange",
"overscroll",
+ "overlaygeometrychange",
"pagehide",
"pageshow",
"paste",
@@ -231,6 +232,7 @@
"ratechange",
"reading",
"readystatechange",
+ "reflectionchange",
"rejectionhandled",
"release",
"remove",
@@ -245,6 +247,7 @@
"resourcetimingbufferfull",
"result",
"resume",
+ "screenschange",
"scroll",
"scrollend",
"search",
diff --git a/chromium/third_party/blink/renderer/core/events/gesture_event.cc b/chromium/third_party/blink/renderer/core/events/gesture_event.cc
index 68516d8992d..e195eb8fa6d 100644
--- a/chromium/third_party/blink/renderer/core/events/gesture_event.cc
+++ b/chromium/third_party/blink/renderer/core/events/gesture_event.cc
@@ -35,38 +35,38 @@ GestureEvent* GestureEvent::Create(AbstractView* view,
AtomicString event_type;
switch (event.GetType()) {
- case WebInputEvent::kGestureScrollBegin:
+ case WebInputEvent::Type::kGestureScrollBegin:
event_type = event_type_names::kGesturescrollstart;
break;
- case WebInputEvent::kGestureScrollEnd:
+ case WebInputEvent::Type::kGestureScrollEnd:
event_type = event_type_names::kGesturescrollend;
break;
- case WebInputEvent::kGestureScrollUpdate:
+ case WebInputEvent::Type::kGestureScrollUpdate:
event_type = event_type_names::kGesturescrollupdate;
break;
- case WebInputEvent::kGestureTap:
+ case WebInputEvent::Type::kGestureTap:
event_type = event_type_names::kGesturetap;
break;
- case WebInputEvent::kGestureTapUnconfirmed:
+ case WebInputEvent::Type::kGestureTapUnconfirmed:
event_type = event_type_names::kGesturetapunconfirmed;
break;
- case WebInputEvent::kGestureTapDown:
+ case WebInputEvent::Type::kGestureTapDown:
event_type = event_type_names::kGesturetapdown;
break;
- case WebInputEvent::kGestureShowPress:
+ case WebInputEvent::Type::kGestureShowPress:
event_type = event_type_names::kGestureshowpress;
break;
- case WebInputEvent::kGestureLongPress:
+ case WebInputEvent::Type::kGestureLongPress:
event_type = event_type_names::kGesturelongpress;
break;
- case WebInputEvent::kGestureFlingStart:
+ case WebInputEvent::Type::kGestureFlingStart:
event_type = event_type_names::kGestureflingstart;
break;
- case WebInputEvent::kGestureTwoFingerTap:
- case WebInputEvent::kGesturePinchBegin:
- case WebInputEvent::kGesturePinchEnd:
- case WebInputEvent::kGesturePinchUpdate:
- case WebInputEvent::kGestureTapCancel:
+ case WebInputEvent::Type::kGestureTwoFingerTap:
+ case WebInputEvent::Type::kGesturePinchBegin:
+ case WebInputEvent::Type::kGesturePinchEnd:
+ case WebInputEvent::Type::kGesturePinchUpdate:
+ case WebInputEvent::Type::kGestureTapCancel:
default:
return nullptr;
}
diff --git a/chromium/third_party/blink/renderer/core/events/keyboard_event.cc b/chromium/third_party/blink/renderer/core/events/keyboard_event.cc
index 2b905985c1b..54f140ee186 100644
--- a/chromium/third_party/blink/renderer/core/events/keyboard_event.cc
+++ b/chromium/third_party/blink/renderer/core/events/keyboard_event.cc
@@ -42,13 +42,13 @@ namespace {
const AtomicString& EventTypeForKeyboardEventType(WebInputEvent::Type type) {
switch (type) {
- case WebInputEvent::kKeyUp:
+ case WebInputEvent::Type::kKeyUp:
return event_type_names::kKeyup;
- case WebInputEvent::kRawKeyDown:
+ case WebInputEvent::Type::kRawKeyDown:
return event_type_names::kKeydown;
- case WebInputEvent::kChar:
+ case WebInputEvent::Type::kChar:
return event_type_names::kKeypress;
- case WebInputEvent::kKeyDown:
+ case WebInputEvent::Type::kKeyDown:
// The caller should disambiguate the combined event into RawKeyDown or
// Char events.
break;
diff --git a/chromium/third_party/blink/renderer/core/events/message_event.cc b/chromium/third_party/blink/renderer/core/events/message_event.cc
index 9ea925f9dab..becc0cd8511 100644
--- a/chromium/third_party/blink/renderer/core/events/message_event.cc
+++ b/chromium/third_party/blink/renderer/core/events/message_event.cc
@@ -96,9 +96,19 @@ MessageEvent::MessageEvent(const AtomicString& type,
: Event(type, initializer),
data_type_(kDataTypeScriptValue),
source_(nullptr) {
+ // TODO(crbug.com/1070964): Remove this existence check. There is a bug that
+ // the current code generator does not initialize a ScriptValue with the
+ // v8::Null value despite that the dictionary member has the default value of
+ // IDL null. |hasData| guard is necessary here.
if (initializer->hasData()) {
- data_as_v8_value_.Set(initializer->data().GetIsolate(),
- initializer->data().V8Value());
+ v8::Local<v8::Value> data = initializer->data().V8Value();
+ // TODO(crbug.com/1070871): Remove the following IsNullOrUndefined() check.
+ // This null/undefined check fills the gap between the new and old bindings
+ // code. The new behavior is preferred in a long term, and we'll switch to
+ // the new behavior once the migration to the new bindings gets settled.
+ if (!data->IsNullOrUndefined()) {
+ data_as_v8_value_.Set(initializer->data().GetIsolate(), data);
+ }
}
if (initializer->hasOrigin())
origin_ = initializer->origin();
diff --git a/chromium/third_party/blink/renderer/core/events/message_event_init.idl b/chromium/third_party/blink/renderer/core/events/message_event_init.idl
index 2e4d36ef20e..f98dd7449ed 100644
--- a/chromium/third_party/blink/renderer/core/events/message_event_init.idl
+++ b/chromium/third_party/blink/renderer/core/events/message_event_init.idl
@@ -5,11 +5,11 @@
// https://html.spec.whatwg.org/C/#the-messageevent-interfaces
dictionary MessageEventInit : EventInit {
- any data;
- DOMString origin;
- DOMString lastEventId;
+ any data = null;
+ DOMString origin = "";
+ DOMString lastEventId = "";
// TODO(bashi): |source| should be (WindowProxy or MessagePort)?
- EventTarget? source;
+ EventTarget? source = null;
sequence<MessagePort> ports = [];
[RuntimeEnabled=UserActivationAPI] UserActivation? userActivation = null;
};
diff --git a/chromium/third_party/blink/renderer/core/events/message_event_test.cc b/chromium/third_party/blink/renderer/core/events/message_event_test.cc
index 95e292f2631..0383ce893d0 100644
--- a/chromium/third_party/blink/renderer/core/events/message_event_test.cc
+++ b/chromium/third_party/blink/renderer/core/events/message_event_test.cc
@@ -43,10 +43,8 @@ TEST_F(MessageEventTest, AccountForStringMemory) {
scope.GetIsolate()->AdjustAmountOfExternalAllocatedMemory(0);
ASSERT_LE(initial + string_size, size_with_event);
- ThreadState::Current()->CollectGarbage(
- BlinkGC::CollectionType::kMajor, BlinkGC::kNoHeapPointersOnStack,
- BlinkGC::kAtomicMarking, BlinkGC::kEagerSweeping,
- BlinkGC::GCReason::kForcedGCForTesting);
+ ThreadState::Current()->CollectAllGarbageForTesting(
+ BlinkGC::kNoHeapPointersOnStack);
int64_t size_after_gc =
scope.GetIsolate()->AdjustAmountOfExternalAllocatedMemory(0);
@@ -91,10 +89,8 @@ TEST_F(MessageEventTest, AccountForArrayBufferMemory) {
scope.GetIsolate()->AdjustAmountOfExternalAllocatedMemory(0);
ASSERT_LE(initial + buffer_size, size_with_event);
- ThreadState::Current()->CollectGarbage(
- BlinkGC::CollectionType::kMajor, BlinkGC::kNoHeapPointersOnStack,
- BlinkGC::kAtomicMarking, BlinkGC::kEagerSweeping,
- BlinkGC::GCReason::kForcedGCForTesting);
+ ThreadState::Current()->CollectAllGarbageForTesting(
+ BlinkGC::kNoHeapPointersOnStack);
int64_t size_after_gc =
scope.GetIsolate()->AdjustAmountOfExternalAllocatedMemory(0);
diff --git a/chromium/third_party/blink/renderer/core/events/mutation_event.idl b/chromium/third_party/blink/renderer/core/events/mutation_event.idl
index 0c34b81c77c..416c0c2fc1c 100644
--- a/chromium/third_party/blink/renderer/core/events/mutation_event.idl
+++ b/chromium/third_party/blink/renderer/core/events/mutation_event.idl
@@ -19,7 +19,9 @@
// https://w3c.github.io/uievents/#interface-MutationEvent
-interface MutationEvent : Event {
+[
+ Exposed=Window
+] interface MutationEvent : Event {
// attrChangeType
const unsigned short MODIFICATION = 1;
const unsigned short ADDITION = 2;
diff --git a/chromium/third_party/blink/renderer/core/events/overscroll_event.idl b/chromium/third_party/blink/renderer/core/events/overscroll_event.idl
index 909255e1b3a..f3e8c8ca244 100644
--- a/chromium/third_party/blink/renderer/core/events/overscroll_event.idl
+++ b/chromium/third_party/blink/renderer/core/events/overscroll_event.idl
@@ -5,6 +5,7 @@
// TODO(sahel): Add link to w3c. https://crbugs.com/907601
[
+ Exposed=Window,
RuntimeEnabled=OverscrollCustomization
] interface OverscrollEvent : Event {
constructor(DOMString type, boolean bubbles, optional OverscrollEventInit eventInitDict = {});
diff --git a/chromium/third_party/blink/renderer/core/events/pointer_event.idl b/chromium/third_party/blink/renderer/core/events/pointer_event.idl
index fc1bddad1a5..30b96c89024 100644
--- a/chromium/third_party/blink/renderer/core/events/pointer_event.idl
+++ b/chromium/third_party/blink/renderer/core/events/pointer_event.idl
@@ -21,5 +21,5 @@
// https://w3c.github.io/pointerevents/extension.html#extensions-to-the-pointerevent-interface
sequence<PointerEvent> getCoalescedEvents();
- [RuntimeEnabled=PredictedEvents, Measure] sequence<PointerEvent> getPredictedEvents();
+ [Measure] sequence<PointerEvent> getPredictedEvents();
};
diff --git a/chromium/third_party/blink/renderer/core/events/pointer_event_factory.cc b/chromium/third_party/blink/renderer/core/events/pointer_event_factory.cc
index 43009215f7d..f07824798fa 100644
--- a/chromium/third_party/blink/renderer/core/events/pointer_event_factory.cc
+++ b/chromium/third_party/blink/renderer/core/events/pointer_event_factory.cc
@@ -61,15 +61,15 @@ uint16_t ButtonToButtonsBitfield(WebPointerProperties::Button button) {
const AtomicString& PointerEventNameForEventType(WebInputEvent::Type type) {
switch (type) {
- case WebInputEvent::kPointerDown:
+ case WebInputEvent::Type::kPointerDown:
return event_type_names::kPointerdown;
- case WebInputEvent::kPointerUp:
+ case WebInputEvent::Type::kPointerUp:
return event_type_names::kPointerup;
- case WebInputEvent::kPointerMove:
+ case WebInputEvent::Type::kPointerMove:
return event_type_names::kPointermove;
- case WebInputEvent::kPointerRawUpdate:
+ case WebInputEvent::Type::kPointerRawUpdate:
return event_type_names::kPointerrawupdate;
- case WebInputEvent::kPointerCancel:
+ case WebInputEvent::Type::kPointerCancel:
return event_type_names::kPointercancel;
default:
NOTREACHED();
@@ -100,8 +100,8 @@ void UpdateCommonPointerEventInit(const WebPointerEvent& web_pointer_event,
web_pointer_event_in_root_frame, dom_window, pointer_event_init);
if (RuntimeEnabledFeatures::ConsolidatedMovementXYEnabled() &&
!web_pointer_event.is_raw_movement_event &&
- (web_pointer_event.GetType() == WebInputEvent::kPointerMove ||
- web_pointer_event.GetType() == WebInputEvent::kPointerRawUpdate)) {
+ (web_pointer_event.GetType() == WebInputEvent::Type::kPointerMove ||
+ web_pointer_event.GetType() == WebInputEvent::Type::kPointerRawUpdate)) {
// TODO(crbug.com/907309): Current movementX/Y is in physical pixel when
// zoom-for-dsf is enabled. Here we apply the device-scale-factor to align
// with the current behavior. We need to figure out what is the best
@@ -233,8 +233,8 @@ PointerEventInit* PointerEventFactory::ConvertIdTypeButtonsEvent(
// touching the screen. This misconception comes from the touch devices and
// is not correct for stylus.
buttons = static_cast<unsigned>(
- (web_pointer_event.GetType() == WebInputEvent::kPointerUp ||
- web_pointer_event.GetType() == WebInputEvent::kPointerCancel)
+ (web_pointer_event.GetType() == WebInputEvent::Type::kPointerUp ||
+ web_pointer_event.GetType() == WebInputEvent::Type::kPointerCancel)
? WebPointerProperties::Buttons::kNoButton
: WebPointerProperties::Buttons::kLeft);
}
@@ -285,18 +285,18 @@ PointerEvent* PointerEventFactory::Create(
const Vector<WebPointerEvent>& predicted_events,
LocalDOMWindow* view) {
const WebInputEvent::Type event_type = web_pointer_event.GetType();
- DCHECK(event_type == WebInputEvent::kPointerDown ||
- event_type == WebInputEvent::kPointerUp ||
- event_type == WebInputEvent::kPointerMove ||
- event_type == WebInputEvent::kPointerRawUpdate ||
- event_type == WebInputEvent::kPointerCancel);
+ DCHECK(event_type == WebInputEvent::Type::kPointerDown ||
+ event_type == WebInputEvent::Type::kPointerUp ||
+ event_type == WebInputEvent::Type::kPointerMove ||
+ event_type == WebInputEvent::Type::kPointerRawUpdate ||
+ event_type == WebInputEvent::Type::kPointerCancel);
PointerEventInit* pointer_event_init =
ConvertIdTypeButtonsEvent(web_pointer_event);
AtomicString type = PointerEventNameForEventType(event_type);
- if (event_type == WebInputEvent::kPointerDown ||
- event_type == WebInputEvent::kPointerUp) {
+ if (event_type == WebInputEvent::Type::kPointerDown ||
+ event_type == WebInputEvent::Type::kPointerUp) {
WebPointerProperties::Button button = web_pointer_event.button;
// TODO(mustaq): Fix when the spec starts supporting hovering erasers.
if (web_pointer_event.pointer_type ==
@@ -306,10 +306,10 @@ PointerEvent* PointerEventFactory::Create(
pointer_event_init->setButton(static_cast<int>(button));
// Make sure chorded buttons fire pointermove instead of pointerup/down.
- if ((event_type == WebInputEvent::kPointerDown &&
+ if ((event_type == WebInputEvent::Type::kPointerDown &&
(pointer_event_init->buttons() & ~ButtonToButtonsBitfield(button)) !=
0) ||
- (event_type == WebInputEvent::kPointerUp &&
+ (event_type == WebInputEvent::Type::kPointerUp &&
pointer_event_init->buttons() != 0))
type = event_type_names::kPointermove;
} else {
@@ -353,7 +353,7 @@ PointerEvent* PointerEventFactory::Create(
void PointerEventFactory::SetLastPosition(int pointer_id,
const FloatPoint& position_in_screen,
WebInputEvent::Type event_type) {
- if (event_type == WebInputEvent::kPointerRawUpdate)
+ if (event_type == WebInputEvent::Type::kPointerRawUpdate)
pointerrawupdate_last_position_mapping_.Set(pointer_id, position_in_screen);
else
pointer_id_last_position_mapping_.Set(pointer_id, position_in_screen);
@@ -368,7 +368,7 @@ FloatPoint PointerEventFactory::GetLastPointerPosition(
int pointer_id,
const WebPointerProperties& event,
WebInputEvent::Type event_type) const {
- if (event_type == WebInputEvent::kPointerRawUpdate) {
+ if (event_type == WebInputEvent::Type::kPointerRawUpdate) {
if (pointerrawupdate_last_position_mapping_.Contains(pointer_id))
return pointerrawupdate_last_position_mapping_.at(pointer_id);
} else {
diff --git a/chromium/third_party/blink/renderer/core/events/pointer_event_factory_test.cc b/chromium/third_party/blink/renderer/core/events/pointer_event_factory_test.cc
index f0cd905c553..5be5f1017e8 100644
--- a/chromium/third_party/blink/renderer/core/events/pointer_event_factory_test.cc
+++ b/chromium/third_party/blink/renderer/core/events/pointer_event_factory_test.cc
@@ -50,7 +50,7 @@ class PointerEventFactoryTest : public testing::Test {
bool is_primary,
bool hovering,
WebInputEvent::Modifiers modifiers = WebInputEvent::kNoModifiers,
- WebInputEvent::Type type = WebInputEvent::kPointerDown,
+ WebInputEvent::Type type = WebInputEvent::Type::kPointerDown,
WebPointerProperties::Button button =
WebPointerProperties::Button::kNoButton,
wtf_size_t coalesced_event_count = 0,
@@ -91,7 +91,7 @@ class PointerEventFactoryTest : public testing::Test {
EXPECT_EQ(!!(modifiers & WebInputEvent::kMetaKey),
pointer_event->metaKey());
- if (type == WebInputEvent::kPointerMove) {
+ if (type == WebInputEvent::Type::kPointerMove) {
EXPECT_EQ(coalesced_event_count,
pointer_event->getCoalescedEvents().size());
EXPECT_EQ(predicted_event_count,
@@ -325,7 +325,7 @@ TEST_F(PointerEventFactoryTest, TouchAndDrag) {
CreateAndCheckWebPointerEvent(
WebPointerProperties::PointerType::kTouch, 0, mapped_id_start_,
true /* isprimary */, false /* hovering */, WebInputEvent::kNoModifiers,
- WebInputEvent::kPointerUp);
+ WebInputEvent::Type::kPointerUp);
EXPECT_TRUE(pointer_event_factory_.IsActive(mapped_id_start_));
EXPECT_FALSE(pointer_event_factory_.IsActiveButtonsState(mapped_id_start_));
@@ -583,7 +583,8 @@ TEST_F(PointerEventFactoryTest, LastPointerPosition) {
CreateAndCheckWebPointerEvent(
WebPointerProperties::PointerType::kMouse, 0, expected_mouse_id_,
true /* isprimary */, true /* hovering */, WebInputEvent::kNoModifiers,
- WebInputEvent::kPointerMove, WebPointerProperties::Button::kNoButton, 4);
+ WebInputEvent::Type::kPointerMove,
+ WebPointerProperties::Button::kNoButton, 4);
pointer_event_factory_.RemoveLastPosition(expected_mouse_id_);
EXPECT_EQ(
pointer_event_factory_.GetLastPointerPosition(
@@ -591,7 +592,7 @@ TEST_F(PointerEventFactoryTest, LastPointerPosition) {
WebPointerProperties(1, WebPointerProperties::PointerType::kUnknown,
WebPointerProperties::Button::kNoButton,
gfx::PointF(50, 50), gfx::PointF(20, 20)),
- WebInputEvent::kPointerMove),
+ WebInputEvent::Type::kPointerMove),
FloatPoint(20, 20));
}
@@ -599,35 +600,40 @@ TEST_F(PointerEventFactoryTest, CoalescedEvents) {
CreateAndCheckWebPointerEvent(
WebPointerProperties::PointerType::kMouse, 0, expected_mouse_id_,
true /* isprimary */, true /* hovering */, WebInputEvent::kNoModifiers,
- WebInputEvent::kPointerMove, WebPointerProperties::Button::kNoButton, 4);
+ WebInputEvent::Type::kPointerMove,
+ WebPointerProperties::Button::kNoButton, 4);
CreateAndCheckWebPointerEvent(
WebPointerProperties::PointerType::kTouch, 0, mapped_id_start_,
true /* isprimary */, false /* hovering */, WebInputEvent::kNoModifiers,
- WebInputEvent::kPointerMove, WebPointerProperties::Button::kNoButton, 3);
+ WebInputEvent::Type::kPointerMove,
+ WebPointerProperties::Button::kNoButton, 3);
}
TEST_F(PointerEventFactoryTest, PredictedEvents) {
CreateAndCheckWebPointerEvent(
WebPointerProperties::PointerType::kMouse, 0, expected_mouse_id_,
true /* isprimary */, true /* hovering */, WebInputEvent::kNoModifiers,
- WebInputEvent::kPointerMove, WebPointerProperties::Button::kNoButton,
- 0 /* coalesced_count */, 4 /* predicted_count */);
+ WebInputEvent::Type::kPointerMove,
+ WebPointerProperties::Button::kNoButton, 0 /* coalesced_count */,
+ 4 /* predicted_count */);
CreateAndCheckWebPointerEvent(
WebPointerProperties::PointerType::kTouch, 0, mapped_id_start_,
true /* isprimary */, false /* hovering */, WebInputEvent::kNoModifiers,
- WebInputEvent::kPointerMove, WebPointerProperties::Button::kNoButton,
- 0 /* coalesced_count */, 3 /* predicted_count */);
+ WebInputEvent::Type::kPointerMove,
+ WebPointerProperties::Button::kNoButton, 0 /* coalesced_count */,
+ 3 /* predicted_count */);
// Check predicted_event_count when type != kPointerMove
CreateAndCheckWebPointerEvent(
WebPointerProperties::PointerType::kMouse, 0, expected_mouse_id_,
true /* isprimary */, true /* hovering */, WebInputEvent::kNoModifiers,
- WebInputEvent::kPointerDown, WebPointerProperties::Button::kNoButton,
- 0 /* coalesced_count */, 4 /* predicted_count */);
+ WebInputEvent::Type::kPointerDown,
+ WebPointerProperties::Button::kNoButton, 0 /* coalesced_count */,
+ 4 /* predicted_count */);
CreateAndCheckWebPointerEvent(
WebPointerProperties::PointerType::kTouch, 0, mapped_id_start_,
true /* isprimary */, false /* hovering */, WebInputEvent::kNoModifiers,
- WebInputEvent::kPointerUp, WebPointerProperties::Button::kNoButton,
+ WebInputEvent::Type::kPointerUp, WebPointerProperties::Button::kNoButton,
0 /* coalesced_count */, 3 /* predicted_count */);
}
@@ -636,7 +642,7 @@ TEST_F(PointerEventFactoryTest, PenEraserButton) {
PointerEvent* first_pointerdown_event = CreateAndCheckWebPointerEvent(
WebPointerProperties::PointerType::kEraser, 0, mapped_id_start_,
true /* isprimary */, false /* hovering */,
- WebInputEvent::kLeftButtonDown, WebInputEvent::kPointerDown,
+ WebInputEvent::kLeftButtonDown, WebInputEvent::Type::kPointerDown,
WebPointerProperties::Button::kLeft);
EXPECT_EQ(event_type_names::kPointerdown, first_pointerdown_event->type());
@@ -647,7 +653,7 @@ TEST_F(PointerEventFactoryTest, PenEraserButton) {
PointerEvent* second_pointerdown_event = CreateAndCheckWebPointerEvent(
WebPointerProperties::PointerType::kEraser, 1, mapped_id_start_ + 1,
false /* isprimary */, false /* hovering */, modifiers,
- WebInputEvent::kPointerDown, WebPointerProperties::Button::kRight);
+ WebInputEvent::Type::kPointerDown, WebPointerProperties::Button::kRight);
EXPECT_EQ(event_type_names::kPointermove, second_pointerdown_event->type());
// Send the pointermove event when releasing any other button while the
@@ -655,7 +661,7 @@ TEST_F(PointerEventFactoryTest, PenEraserButton) {
PointerEvent* first_pointerup_event = CreateAndCheckWebPointerEvent(
WebPointerProperties::PointerType::kEraser, 1, mapped_id_start_ + 1,
false /* isprimary */, true /* hovering */,
- WebInputEvent::kLeftButtonDown, WebInputEvent::kPointerUp,
+ WebInputEvent::kLeftButtonDown, WebInputEvent::Type::kPointerUp,
WebPointerProperties::Button::kRight);
EXPECT_EQ(event_type_names::kPointermove, first_pointerup_event->type());
@@ -663,7 +669,7 @@ TEST_F(PointerEventFactoryTest, PenEraserButton) {
PointerEvent* last_pointerup_event = CreateAndCheckWebPointerEvent(
WebPointerProperties::PointerType::kEraser, 0, mapped_id_start_,
true /* isprimary */, true /* hovering */, WebInputEvent::kNoModifiers,
- WebInputEvent::kPointerUp, WebPointerProperties::Button::kLeft);
+ WebInputEvent::Type::kPointerUp, WebPointerProperties::Button::kLeft);
EXPECT_EQ(event_type_names::kPointerup, last_pointerup_event->type());
}
@@ -674,7 +680,7 @@ TEST_F(PointerEventFactoryTest, MousePointerKeyStates) {
PointerEvent* pointer_event1 = CreateAndCheckWebPointerEvent(
WebPointerProperties::PointerType::kMouse, 0, expected_mouse_id_,
true /* isprimary */, true /* hovering */, modifiers,
- WebInputEvent::kPointerMove);
+ WebInputEvent::Type::kPointerMove);
CreateAndCheckPointerTransitionEvent(pointer_event1,
event_type_names::kPointerout);
@@ -684,7 +690,7 @@ TEST_F(PointerEventFactoryTest, MousePointerKeyStates) {
PointerEvent* pointer_event2 = CreateAndCheckWebPointerEvent(
WebPointerProperties::PointerType::kMouse, 0, expected_mouse_id_,
true /* isprimary */, true /* hovering */, modifiers,
- WebInputEvent::kPointerMove);
+ WebInputEvent::Type::kPointerMove);
CreateAndCheckPointerTransitionEvent(pointer_event2,
event_type_names::kPointerover);
diff --git a/chromium/third_party/blink/renderer/core/events/pointer_event_init.idl b/chromium/third_party/blink/renderer/core/events/pointer_event_init.idl
index 8dafde06d06..0426aed9e25 100644
--- a/chromium/third_party/blink/renderer/core/events/pointer_event_init.idl
+++ b/chromium/third_party/blink/renderer/core/events/pointer_event_init.idl
@@ -18,5 +18,5 @@ dictionary PointerEventInit : MouseEventInit {
// https://w3c.github.io/pointerevents/extension.html#extensions-to-the-pointerevent-interface
sequence<PointerEvent> coalescedEvents = [];
- [RuntimeEnabled=PredictedEvents]sequence<PointerEvent> predictedEvents = [];
+ sequence<PointerEvent> predictedEvents = [];
};
diff --git a/chromium/third_party/blink/renderer/core/events/pop_state_event.cc b/chromium/third_party/blink/renderer/core/events/pop_state_event.cc
index 47fe14831c2..19e98fea0b3 100644
--- a/chromium/third_party/blink/renderer/core/events/pop_state_event.cc
+++ b/chromium/third_party/blink/renderer/core/events/pop_state_event.cc
@@ -33,16 +33,32 @@
namespace blink {
-PopStateEvent::PopStateEvent()
- : serialized_state_(nullptr), history_(nullptr) {}
+PopStateEvent* PopStateEvent::Create() {
+ return MakeGarbageCollected<PopStateEvent>();
+}
+
+PopStateEvent* PopStateEvent::Create(ScriptState* script_state,
+ const AtomicString& type,
+ const PopStateEventInit* initializer) {
+ return MakeGarbageCollected<PopStateEvent>(script_state, type, initializer);
+}
+
+PopStateEvent* PopStateEvent::Create(
+ scoped_refptr<SerializedScriptValue> serialized_state,
+ History* history) {
+ return MakeGarbageCollected<PopStateEvent>(std::move(serialized_state),
+ history);
+}
PopStateEvent::PopStateEvent(ScriptState* script_state,
const AtomicString& type,
const PopStateEventInit* initializer)
- : Event(type, initializer), history_(nullptr) {
+ : Event(type, initializer) {
+ v8::Isolate* isolate = script_state->GetIsolate();
if (initializer->hasState()) {
- world_ = WrapRefCounted(&script_state->World());
- state_.Set(script_state->GetIsolate(), initializer->state().V8Value());
+ state_.Set(isolate, initializer->state().V8Value());
+ } else {
+ state_.Set(isolate, v8::Null(isolate));
}
}
@@ -53,43 +69,27 @@ PopStateEvent::PopStateEvent(
serialized_state_(std::move(serialized_state)),
history_(history) {}
-PopStateEvent::~PopStateEvent() = default;
-
-ScriptValue PopStateEvent::state(ScriptState* script_state) const {
- if (state_.IsEmpty())
- return ScriptValue();
-
+ScriptValue PopStateEvent::state(ScriptState* script_state,
+ ExceptionState& exception_state) {
v8::Isolate* isolate = script_state->GetIsolate();
- if (world_->GetWorldId() != script_state->World().GetWorldId()) {
- v8::Local<v8::Value> value = state_.NewLocal(isolate);
- scoped_refptr<SerializedScriptValue> serialized =
- SerializedScriptValue::SerializeAndSwallowExceptions(isolate, value);
- return ScriptValue(isolate, serialized->Deserialize(isolate));
- }
- return ScriptValue(isolate, state_.NewLocal(isolate));
-}
-PopStateEvent* PopStateEvent::Create() {
- return MakeGarbageCollected<PopStateEvent>();
-}
+ if (!state_.IsEmpty())
+ return ScriptValue(isolate, state_.GetAcrossWorld(script_state));
-PopStateEvent* PopStateEvent::Create(
- scoped_refptr<SerializedScriptValue> serialized_state,
- History* history) {
- return MakeGarbageCollected<PopStateEvent>(std::move(serialized_state),
- history);
-}
+ if (history_ && history_->IsSameAsCurrentState(serialized_state_.get())) {
+ return history_->state(script_state, exception_state);
+ }
-PopStateEvent* PopStateEvent::Create(ScriptState* script_state,
- const AtomicString& type,
- const PopStateEventInit* initializer) {
- return MakeGarbageCollected<PopStateEvent>(script_state, type, initializer);
-}
+ v8::Local<v8::Value> v8_state;
+ if (serialized_state_) {
+ ScriptState::EscapableScope target_context_scope(script_state);
+ v8_state =
+ target_context_scope.Escape(serialized_state_->Deserialize(isolate));
+ } else {
+ v8_state = v8::Null(isolate);
+ }
-void PopStateEvent::SetSerializedState(
- scoped_refptr<SerializedScriptValue> state) {
- DCHECK(!serialized_state_);
- serialized_state_ = std::move(state);
+ return ScriptValue(isolate, v8_state);
}
const AtomicString& PopStateEvent::InterfaceName() const {
diff --git a/chromium/third_party/blink/renderer/core/events/pop_state_event.h b/chromium/third_party/blink/renderer/core/events/pop_state_event.h
index d8452f95bd9..f788e5ace29 100644
--- a/chromium/third_party/blink/renderer/core/events/pop_state_event.h
+++ b/chromium/third_party/blink/renderer/core/events/pop_state_event.h
@@ -28,9 +28,8 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_EVENTS_POP_STATE_EVENT_H_
#include "third_party/blink/renderer/bindings/core/v8/v8_pop_state_event_init.h"
+#include "third_party/blink/renderer/bindings/core/v8/world_safe_v8_reference.h"
#include "third_party/blink/renderer/core/dom/events/event.h"
-#include "third_party/blink/renderer/platform/bindings/dom_wrapper_world.h"
-#include "third_party/blink/renderer/platform/bindings/trace_wrapper_v8_reference.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
namespace blink {
@@ -38,36 +37,36 @@ namespace blink {
class History;
class SerializedScriptValue;
-class PopStateEvent final : public Event {
+class CORE_EXPORT PopStateEvent final : public Event {
DEFINE_WRAPPERTYPEINFO();
public:
- PopStateEvent();
- PopStateEvent(ScriptState*, const AtomicString&, const PopStateEventInit*);
- PopStateEvent(scoped_refptr<SerializedScriptValue>, History*);
- ~PopStateEvent() override;
-
static PopStateEvent* Create();
- static PopStateEvent* Create(scoped_refptr<SerializedScriptValue>, History*);
- static PopStateEvent* Create(ScriptState*,
- const AtomicString&,
- const PopStateEventInit*);
+ static PopStateEvent* Create(ScriptState* script_state,
+ const AtomicString& type,
+ const PopStateEventInit* initializer);
+ static PopStateEvent* Create(
+ scoped_refptr<SerializedScriptValue> serialized_state,
+ History* history);
+
+ PopStateEvent() = default;
+ PopStateEvent(ScriptState* script_state,
+ const AtomicString& type,
+ const PopStateEventInit* initializer);
+ PopStateEvent(scoped_refptr<SerializedScriptValue> serialized_state,
+ History* history);
+ ~PopStateEvent() override = default;
- ScriptValue state(ScriptState*) const;
- SerializedScriptValue* SerializedState() const {
- return serialized_state_.get();
- }
- void SetSerializedState(scoped_refptr<SerializedScriptValue> state);
- History* GetHistory() const { return history_.Get(); }
+ ScriptValue state(ScriptState* script_state, ExceptionState& exception_state);
+ bool IsStateDirty() const { return false; }
const AtomicString& InterfaceName() const override;
void Trace(Visitor*) override;
private:
+ WorldSafeV8Reference<v8::Value> state_;
scoped_refptr<SerializedScriptValue> serialized_state_;
- scoped_refptr<DOMWrapperWorld> world_;
- TraceWrapperV8Reference<v8::Value> state_;
Member<History> history_;
};
diff --git a/chromium/third_party/blink/renderer/core/events/pop_state_event.idl b/chromium/third_party/blink/renderer/core/events/pop_state_event.idl
index bf478ea554a..16624a90559 100644
--- a/chromium/third_party/blink/renderer/core/events/pop_state_event.idl
+++ b/chromium/third_party/blink/renderer/core/events/pop_state_event.idl
@@ -31,5 +31,5 @@
Exposed=Window
] interface PopStateEvent : Event {
[CallWith=ScriptState] constructor(DOMString type, optional PopStateEventInit eventInitDict = {});
- [Custom=Getter] readonly attribute any state;
+ [CallWith=ScriptState, RaisesException, CachedAttribute=IsStateDirty] readonly attribute any state;
};
diff --git a/chromium/third_party/blink/renderer/core/events/pop_state_event_init.idl b/chromium/third_party/blink/renderer/core/events/pop_state_event_init.idl
index 94e39788524..b0cb9639d3e 100644
--- a/chromium/third_party/blink/renderer/core/events/pop_state_event_init.idl
+++ b/chromium/third_party/blink/renderer/core/events/pop_state_event_init.idl
@@ -5,5 +5,5 @@
// https://html.spec.whatwg.org/C/#the-popstateevent-interface
dictionary PopStateEventInit : EventInit {
- any state;
+ any state = null;
};
diff --git a/chromium/third_party/blink/renderer/core/events/security_policy_violation_event_init.idl b/chromium/third_party/blink/renderer/core/events/security_policy_violation_event_init.idl
index 47d2cab0509..1a4efec8efe 100644
--- a/chromium/third_party/blink/renderer/core/events/security_policy_violation_event_init.idl
+++ b/chromium/third_party/blink/renderer/core/events/security_policy_violation_event_init.idl
@@ -5,18 +5,23 @@
// https://w3c.github.io/webappsec-csp/#idl-index
dictionary SecurityPolicyViolationEventInit : EventInit {
- // TODO(foolip): The spec says "documentURL".
+ // TODO(foolip): The spec says "USVString documentURL".
required DOMString documentURI;
+ // TODO(foolip): The spec says USVString.
DOMString referrer;
- // TODO(foolip): The spec says "blockedURL".
- DOMString blockedURI;
- required DOMString violatedDirective;
+ // TODO(foolip): The spec says "USVString blockedURL".
+ DOMString blockedURI = "";
required DOMString effectiveDirective;
required DOMString originalPolicy;
+ // TODO(foolip): The spec says USVString.
+ DOMString sourceFile = "";
+ DOMString sample;
required SecurityPolicyViolationEventDisposition disposition;
- DOMString sourceFile;
required unsigned short statusCode;
- long lineNumber;
- long columnNumber;
- DOMString sample;
+ // TODO(foolip): The spec says "unsigned long lineno"
+ long lineNumber = 0;
+ // TODO(foolip): The spec says "unsigned long colno"
+ long columnNumber = 0;
+
+ required DOMString violatedDirective;
};
diff --git a/chromium/third_party/blink/renderer/core/events/text_event.idl b/chromium/third_party/blink/renderer/core/events/text_event.idl
index 3395b932224..7b3fd595aee 100644
--- a/chromium/third_party/blink/renderer/core/events/text_event.idl
+++ b/chromium/third_party/blink/renderer/core/events/text_event.idl
@@ -31,7 +31,9 @@
// https://www.w3.org/Bugs/Public/show_bug.cgi?id=12958
// https://github.com/w3c/uievents/commit/1a2aa02b474fd4feaf43fdced06e6fd7214196a4
-interface TextEvent : UIEvent {
+[
+ Exposed=Window
+] interface TextEvent : UIEvent {
[Measure] readonly attribute DOMString data;
diff --git a/chromium/third_party/blink/renderer/core/events/touch_event.cc b/chromium/third_party/blink/renderer/core/events/touch_event.cc
index 54a5a379039..dda3cf9d4f2 100644
--- a/chromium/third_party/blink/renderer/core/events/touch_event.cc
+++ b/chromium/third_party/blink/renderer/core/events/touch_event.cc
@@ -26,7 +26,7 @@
#include "third_party/blink/renderer/core/events/touch_event.h"
-#include "third_party/blink/public/platform/web_coalesced_input_event.h"
+#include "third_party/blink/public/common/input/web_coalesced_input_event.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_touch_event_init.h"
#include "third_party/blink/renderer/core/dom/events/event_dispatcher.h"
#include "third_party/blink/renderer/core/dom/events/event_path.h"
diff --git a/chromium/third_party/blink/renderer/core/events/touch_event.h b/chromium/third_party/blink/renderer/core/events/touch_event.h
index 90ca4041f33..adb67d575da 100644
--- a/chromium/third_party/blink/renderer/core/events/touch_event.h
+++ b/chromium/third_party/blink/renderer/core/events/touch_event.h
@@ -27,8 +27,8 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_EVENTS_TOUCH_EVENT_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_EVENTS_TOUCH_EVENT_H_
+#include "third_party/blink/public/common/input/web_coalesced_input_event.h"
#include "third_party/blink/public/common/input/web_touch_event.h"
-#include "third_party/blink/public/platform/web_coalesced_input_event.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/events/ui_event_with_key_state.h"
#include "third_party/blink/renderer/core/input/touch_list.h"
diff --git a/chromium/third_party/blink/renderer/core/events/touch_event_test.cc b/chromium/third_party/blink/renderer/core/events/touch_event_test.cc
index ff58660475f..7eb6171f7a7 100644
--- a/chromium/third_party/blink/renderer/core/events/touch_event_test.cc
+++ b/chromium/third_party/blink/renderer/core/events/touch_event_test.cc
@@ -65,12 +65,12 @@ class TouchEventTest : public PageTestBase {
LocalDOMWindow& Window() { return *GetFrame().DomWindow(); }
TouchEvent* EventWithDispatchType(WebInputEvent::DispatchType dispatch_type) {
- WebTouchEvent web_touch_event(WebInputEvent::kTouchStart, 0,
+ WebTouchEvent web_touch_event(WebInputEvent::Type::kTouchStart, 0,
base::TimeTicks());
web_touch_event.dispatch_type = dispatch_type;
- return TouchEvent::Create(WebCoalescedInputEvent(web_touch_event), nullptr,
- nullptr, nullptr, "touchstart", &Window(),
- TouchAction::kAuto);
+ return TouchEvent::Create(
+ WebCoalescedInputEvent(web_touch_event, ui::LatencyInfo()), nullptr,
+ nullptr, nullptr, "touchstart", &Window(), TouchAction::kAuto);
}
private:
@@ -80,8 +80,8 @@ class TouchEventTest : public PageTestBase {
TEST_F(TouchEventTest,
PreventDefaultPassiveDueToDocumentLevelScrollerIntervention) {
- TouchEvent* event =
- EventWithDispatchType(WebInputEvent::kListenersNonBlockingPassive);
+ TouchEvent* event = EventWithDispatchType(
+ WebInputEvent::DispatchType::kListenersNonBlockingPassive);
event->SetHandlingPassive(Event::PassiveMode::kPassiveForcedDocumentLevel);
EXPECT_THAT(Messages(), ElementsAre());
diff --git a/chromium/third_party/blink/renderer/core/events/web_input_event_conversion.cc b/chromium/third_party/blink/renderer/core/events/web_input_event_conversion.cc
index fcf3fc6b4af..16d9a69d9cb 100644
--- a/chromium/third_party/blink/renderer/core/events/web_input_event_conversion.cc
+++ b/chromium/third_party/blink/renderer/core/events/web_input_event_conversion.cc
@@ -138,7 +138,7 @@ WebMouseEvent TransformWebMouseEvent(LocalFrameView* frame_view,
// TODO(dtapuska): Perhaps the event should be constructed correctly?
// crbug.com/686200
- if (event.GetType() == WebInputEvent::kMouseUp) {
+ if (event.GetType() == WebInputEvent::Type::kMouseUp) {
result.SetModifiers(event.GetModifiers() &
~ToWebInputEventModifierFrom(event.button));
}
@@ -178,17 +178,17 @@ WebMouseEventBuilder::WebMouseEventBuilder(const LocalFrameView* plugin_parent,
// other frames; but for now we allow the fallback to generate
// WebMouseEvents from synthetic events.
if (event.type() == event_type_names::kMousemove)
- type_ = WebInputEvent::kMouseMove;
+ type_ = WebInputEvent::Type::kMouseMove;
else if (event.type() == event_type_names::kMouseout)
- type_ = WebInputEvent::kMouseLeave;
+ type_ = WebInputEvent::Type::kMouseLeave;
else if (event.type() == event_type_names::kMouseover)
- type_ = WebInputEvent::kMouseEnter;
+ type_ = WebInputEvent::Type::kMouseEnter;
else if (event.type() == event_type_names::kMousedown)
- type_ = WebInputEvent::kMouseDown;
+ type_ = WebInputEvent::Type::kMouseDown;
else if (event.type() == event_type_names::kMouseup)
- type_ = WebInputEvent::kMouseUp;
+ type_ = WebInputEvent::Type::kMouseUp;
else if (event.type() == event_type_names::kContextmenu)
- type_ = WebInputEvent::kContextMenu;
+ type_ = WebInputEvent::Type::kContextMenu;
else
return; // Skip all other mouse events.
@@ -263,11 +263,11 @@ WebMouseEventBuilder::WebMouseEventBuilder(const LocalFrameView* plugin_parent,
return;
if (event.type() == event_type_names::kTouchstart)
- type_ = kMouseDown;
+ type_ = WebInputEvent::Type::kMouseDown;
else if (event.type() == event_type_names::kTouchmove)
- type_ = kMouseMove;
+ type_ = WebInputEvent::Type::kMouseMove;
else if (event.type() == event_type_names::kTouchend)
- type_ = kMouseUp;
+ type_ = WebInputEvent::Type::kMouseUp;
else
return;
@@ -290,7 +290,8 @@ WebMouseEventBuilder::WebMouseEventBuilder(const LocalFrameView* plugin_parent,
button = WebMouseEvent::Button::kLeft;
modifiers_ |= WebInputEvent::kLeftButtonDown;
- click_count = (type_ == kMouseDown || type_ == kMouseUp);
+ click_count = (type_ == WebInputEvent::Type::kMouseDown ||
+ type_ == WebInputEvent::Type::kMouseUp);
FloatPoint local_point = ConvertAbsoluteLocationForLayoutObjectFloat(
DoublePoint(touch->AbsoluteLocation()), layout_object);
@@ -306,11 +307,11 @@ WebKeyboardEventBuilder::WebKeyboardEventBuilder(const KeyboardEvent& event) {
}
if (event.type() == event_type_names::kKeydown)
- type_ = kKeyDown;
+ type_ = WebInputEvent::Type::kKeyDown;
else if (event.type() == event_type_names::kKeyup)
- type_ = WebInputEvent::kKeyUp;
+ type_ = WebInputEvent::Type::kKeyUp;
else if (event.type() == event_type_names::kKeypress)
- type_ = WebInputEvent::kChar;
+ type_ = WebInputEvent::Type::kChar;
else
return; // Skip all other keyboard events.
@@ -321,9 +322,9 @@ WebKeyboardEventBuilder::WebKeyboardEventBuilder(const KeyboardEvent& event) {
Vector<WebMouseEvent> TransformWebMouseEventVector(
LocalFrameView* frame_view,
- const WebVector<const WebInputEvent*>& coalesced_events) {
+ const std::vector<std::unique_ptr<WebInputEvent>>& coalesced_events) {
Vector<WebMouseEvent> result;
- for (auto* const event : coalesced_events) {
+ for (const auto& event : coalesced_events) {
DCHECK(WebInputEvent::IsMouseEventType(event->GetType()));
result.push_back(TransformWebMouseEvent(
frame_view, static_cast<const WebMouseEvent&>(*event)));
@@ -333,11 +334,11 @@ Vector<WebMouseEvent> TransformWebMouseEventVector(
Vector<WebPointerEvent> TransformWebPointerEventVector(
LocalFrameView* frame_view,
- const WebVector<const WebInputEvent*>& coalesced_events) {
+ const std::vector<std::unique_ptr<WebInputEvent>>& coalesced_events) {
float scale = FrameScale(frame_view);
gfx::Vector2dF translation = FrameTranslation(frame_view);
Vector<WebPointerEvent> result;
- for (auto* const event : coalesced_events) {
+ for (const auto& event : coalesced_events) {
DCHECK(WebInputEvent::IsPointerEventType(event->GetType()));
result.push_back(TransformWebPointerEvent(
scale, translation, static_cast<const WebPointerEvent&>(*event)));
diff --git a/chromium/third_party/blink/renderer/core/events/web_input_event_conversion.h b/chromium/third_party/blink/renderer/core/events/web_input_event_conversion.h
index 9dc220ef02e..ec7abdc6c3b 100644
--- a/chromium/third_party/blink/renderer/core/events/web_input_event_conversion.h
+++ b/chromium/third_party/blink/renderer/core/events/web_input_event_conversion.h
@@ -31,12 +31,12 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_EVENTS_WEB_INPUT_EVENT_CONVERSION_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_EVENTS_WEB_INPUT_EVENT_CONVERSION_H_
+#include "third_party/blink/public/common/input/web_coalesced_input_event.h"
#include "third_party/blink/public/common/input/web_input_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"
-#include "third_party/blink/public/platform/web_coalesced_input_event.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/scroll/scroll_types.h"
@@ -89,12 +89,12 @@ TransformWebMouseWheelEvent(LocalFrameView*, const WebMouseWheelEvent&);
CORE_EXPORT WebPointerEvent TransformWebPointerEvent(LocalFrameView*,
const WebPointerEvent&);
-Vector<WebMouseEvent> CORE_EXPORT
-TransformWebMouseEventVector(LocalFrameView*,
- const WebVector<const WebInputEvent*>&);
-Vector<WebPointerEvent> CORE_EXPORT
-TransformWebPointerEventVector(LocalFrameView*,
- const WebVector<const WebInputEvent*>&);
+Vector<WebMouseEvent> CORE_EXPORT TransformWebMouseEventVector(
+ LocalFrameView*,
+ const std::vector<std::unique_ptr<WebInputEvent>>&);
+Vector<WebPointerEvent> CORE_EXPORT TransformWebPointerEventVector(
+ LocalFrameView*,
+ const std::vector<std::unique_ptr<WebInputEvent>>&);
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/events/web_input_event_conversion_test.cc b/chromium/third_party/blink/renderer/core/events/web_input_event_conversion_test.cc
index 8453864e754..6b6d1ddc914 100644
--- a/chromium/third_party/blink/renderer/core/events/web_input_event_conversion_test.cc
+++ b/chromium/third_party/blink/renderer/core/events/web_input_event_conversion_test.cc
@@ -110,7 +110,7 @@ TEST(WebInputEventConversionTest, WebKeyboardEventBuilder) {
TEST(WebInputEventConversionTest, WebMouseEventBuilder) {
TouchEvent* event = TouchEvent::Create();
WebMouseEventBuilder mouse(nullptr, nullptr, *event);
- EXPECT_EQ(WebInputEvent::kUndefined, mouse.GetType());
+ EXPECT_EQ(WebInputEvent::Type::kUndefined, mouse.GetType());
}
TEST(WebInputEventConversionTest, InputEventsScaling) {
@@ -134,7 +134,7 @@ TEST(WebInputEventConversionTest, InputEventsScaling) {
To<LocalFrame>(web_view->GetPage()->MainFrame())->View();
{
- WebMouseEvent web_mouse_event(WebInputEvent::kMouseMove,
+ WebMouseEvent web_mouse_event(WebInputEvent::Type::kMouseMove,
WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests());
web_mouse_event.SetPositionInWidget(15, 15);
@@ -157,7 +157,7 @@ TEST(WebInputEventConversionTest, InputEventsScaling) {
{
WebGestureEvent web_gesture_event(
- WebInputEvent::kGestureScrollUpdate, WebInputEvent::kNoModifiers,
+ WebInputEvent::Type::kGestureScrollUpdate, WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests(),
WebGestureDevice::kTouchscreen);
web_gesture_event.SetPositionInWidget(gfx::PointF(15, 18));
@@ -189,7 +189,7 @@ TEST(WebInputEventConversionTest, InputEventsScaling) {
{
WebGestureEvent web_gesture_event(
- WebInputEvent::kGestureScrollEnd, WebInputEvent::kNoModifiers,
+ WebInputEvent::Type::kGestureScrollEnd, WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests(),
WebGestureDevice::kTouchscreen);
web_gesture_event.SetPositionInWidget(gfx::PointF(15, 18));
@@ -209,7 +209,7 @@ TEST(WebInputEventConversionTest, InputEventsScaling) {
{
WebGestureEvent web_gesture_event(
- WebInputEvent::kGestureTap, WebInputEvent::kNoModifiers,
+ WebInputEvent::Type::kGestureTap, WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests(),
WebGestureDevice::kTouchscreen);
web_gesture_event.data.tap.width = 15;
@@ -225,7 +225,8 @@ TEST(WebInputEventConversionTest, InputEventsScaling) {
{
WebGestureEvent web_gesture_event(
- WebInputEvent::kGestureTapUnconfirmed, WebInputEvent::kNoModifiers,
+ WebInputEvent::Type::kGestureTapUnconfirmed,
+ WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests(),
WebGestureDevice::kTouchscreen);
web_gesture_event.data.tap.width = 30;
@@ -241,7 +242,7 @@ TEST(WebInputEventConversionTest, InputEventsScaling) {
{
WebGestureEvent web_gesture_event(
- WebInputEvent::kGestureTapDown, WebInputEvent::kNoModifiers,
+ WebInputEvent::Type::kGestureTapDown, WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests(),
WebGestureDevice::kTouchscreen);
web_gesture_event.data.tap_down.width = 9;
@@ -257,7 +258,7 @@ TEST(WebInputEventConversionTest, InputEventsScaling) {
{
WebGestureEvent web_gesture_event(
- WebInputEvent::kGestureShowPress, WebInputEvent::kNoModifiers,
+ WebInputEvent::Type::kGestureShowPress, WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests(),
WebGestureDevice::kTouchscreen);
web_gesture_event.data.show_press.width = 18;
@@ -273,7 +274,7 @@ TEST(WebInputEventConversionTest, InputEventsScaling) {
{
WebGestureEvent web_gesture_event(
- WebInputEvent::kGestureLongPress, WebInputEvent::kNoModifiers,
+ WebInputEvent::Type::kGestureLongPress, WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests(),
WebGestureDevice::kTouchscreen);
web_gesture_event.data.long_press.width = 15;
@@ -289,7 +290,7 @@ TEST(WebInputEventConversionTest, InputEventsScaling) {
{
WebGestureEvent web_gesture_event(
- WebInputEvent::kGestureTwoFingerTap, WebInputEvent::kNoModifiers,
+ WebInputEvent::Type::kGestureTwoFingerTap, WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests(),
WebGestureDevice::kTouchscreen);
web_gesture_event.data.two_finger_tap.first_finger_width = 15;
@@ -305,7 +306,7 @@ TEST(WebInputEventConversionTest, InputEventsScaling) {
{
WebPointerEvent web_pointer_event(
- WebInputEvent::kPointerDown,
+ WebInputEvent::Type::kPointerDown,
WebPointerProperties(1, WebPointerProperties::PointerType::kTouch,
WebPointerProperties::Button::kLeft,
gfx::PointF(10.8f, 10.5f),
@@ -355,7 +356,7 @@ TEST(WebInputEventConversionTest, InputEventsTransform) {
To<LocalFrame>(web_view->GetPage()->MainFrame())->View();
{
- WebMouseEvent web_mouse_event(WebInputEvent::kMouseMove,
+ WebMouseEvent web_mouse_event(WebInputEvent::Type::kMouseMove,
WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests());
web_mouse_event.SetPositionInWidget(90, 90);
@@ -376,7 +377,7 @@ TEST(WebInputEventConversionTest, InputEventsTransform) {
}
{
- WebMouseEvent web_mouse_event1(WebInputEvent::kMouseMove,
+ WebMouseEvent web_mouse_event1(WebInputEvent::Type::kMouseMove,
WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests());
web_mouse_event1.SetPositionInWidget(90, 90);
@@ -391,9 +392,9 @@ TEST(WebInputEventConversionTest, InputEventsTransform) {
web_mouse_event1.PositionInScreen().x(), 120);
web_mouse_event2.movement_y = 30;
- WebVector<const WebInputEvent*> events;
- events.emplace_back(&web_mouse_event1);
- events.emplace_back(&web_mouse_event2);
+ std::vector<std::unique_ptr<WebInputEvent>> events;
+ events.emplace_back(web_mouse_event1.Clone());
+ events.emplace_back(web_mouse_event2.Clone());
Vector<WebMouseEvent> coalescedevents =
TransformWebMouseEventVector(view, events);
@@ -420,7 +421,7 @@ TEST(WebInputEventConversionTest, InputEventsTransform) {
{
WebGestureEvent web_gesture_event(
- WebInputEvent::kGestureScrollUpdate, WebInputEvent::kNoModifiers,
+ WebInputEvent::Type::kGestureScrollUpdate, WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests(),
WebGestureDevice::kTouchscreen);
web_gesture_event.SetPositionInWidget(gfx::PointF(90, 90));
@@ -442,7 +443,7 @@ TEST(WebInputEventConversionTest, InputEventsTransform) {
{
WebGestureEvent web_gesture_event(
- WebInputEvent::kGestureTap, WebInputEvent::kNoModifiers,
+ WebInputEvent::Type::kGestureTap, WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests(),
WebGestureDevice::kTouchscreen);
web_gesture_event.data.tap.width = 30;
@@ -458,7 +459,8 @@ TEST(WebInputEventConversionTest, InputEventsTransform) {
{
WebGestureEvent web_gesture_event(
- WebInputEvent::kGestureTapUnconfirmed, WebInputEvent::kNoModifiers,
+ WebInputEvent::Type::kGestureTapUnconfirmed,
+ WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests(),
WebGestureDevice::kTouchscreen);
web_gesture_event.data.tap.width = 30;
@@ -474,7 +476,7 @@ TEST(WebInputEventConversionTest, InputEventsTransform) {
{
WebGestureEvent web_gesture_event(
- WebInputEvent::kGestureTapDown, WebInputEvent::kNoModifiers,
+ WebInputEvent::Type::kGestureTapDown, WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests(),
WebGestureDevice::kTouchscreen);
web_gesture_event.data.tap_down.width = 30;
@@ -490,7 +492,7 @@ TEST(WebInputEventConversionTest, InputEventsTransform) {
{
WebGestureEvent web_gesture_event(
- WebInputEvent::kGestureShowPress, WebInputEvent::kNoModifiers,
+ WebInputEvent::Type::kGestureShowPress, WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests(),
WebGestureDevice::kTouchscreen);
web_gesture_event.data.show_press.width = 30;
@@ -506,7 +508,7 @@ TEST(WebInputEventConversionTest, InputEventsTransform) {
{
WebGestureEvent web_gesture_event(
- WebInputEvent::kGestureLongPress, WebInputEvent::kNoModifiers,
+ WebInputEvent::Type::kGestureLongPress, WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests(),
WebGestureDevice::kTouchscreen);
web_gesture_event.data.long_press.width = 30;
@@ -522,7 +524,7 @@ TEST(WebInputEventConversionTest, InputEventsTransform) {
{
WebGestureEvent web_gesture_event(
- WebInputEvent::kGestureTwoFingerTap, WebInputEvent::kNoModifiers,
+ WebInputEvent::Type::kGestureTwoFingerTap, WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests(),
WebGestureDevice::kTouchscreen);
web_gesture_event.data.two_finger_tap.first_finger_width = 30;
@@ -538,7 +540,7 @@ TEST(WebInputEventConversionTest, InputEventsTransform) {
{
WebPointerEvent web_pointer_event(
- WebInputEvent::kPointerDown,
+ WebInputEvent::Type::kPointerDown,
WebPointerProperties(1, WebPointerProperties::PointerType::kTouch,
WebPointerProperties::Button::kLeft,
gfx::PointF(90, 90), gfx::PointF(90, 90)),
@@ -558,22 +560,22 @@ TEST(WebInputEventConversionTest, InputEventsTransform) {
{
WebPointerEvent web_pointer_event1(
- WebInputEvent::kPointerDown,
+ WebInputEvent::Type::kPointerDown,
WebPointerProperties(1, WebPointerProperties::PointerType::kTouch,
WebPointerProperties::Button::kLeft,
gfx::PointF(90, 90), gfx::PointF(90, 90)),
30, 30);
WebPointerEvent web_pointer_event2(
- WebInputEvent::kPointerDown,
+ WebInputEvent::Type::kPointerDown,
WebPointerProperties(1, WebPointerProperties::PointerType::kTouch,
WebPointerProperties::Button::kLeft,
gfx::PointF(120, 90), gfx::PointF(120, 90)),
60, 30);
- WebVector<const WebInputEvent*> events;
- events.emplace_back(&web_pointer_event1);
- events.emplace_back(&web_pointer_event2);
+ std::vector<std::unique_ptr<WebInputEvent>> events;
+ events.emplace_back(web_pointer_event1.Clone());
+ events.emplace_back(web_pointer_event2.Clone());
Vector<WebPointerEvent> coalescedevents =
TransformWebPointerEventVector(view, events);
@@ -616,7 +618,7 @@ TEST(WebInputEventConversionTest, InputEventsConversions) {
To<LocalFrame>(web_view->GetPage()->MainFrame())->View();
{
WebGestureEvent web_gesture_event(
- WebInputEvent::kGestureTap, WebInputEvent::kNoModifiers,
+ WebInputEvent::Type::kGestureTap, WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests(),
WebGestureDevice::kTouchscreen);
web_gesture_event.SetPositionInWidget(gfx::PointF(10, 10));
@@ -660,7 +662,7 @@ TEST(WebInputEventConversionTest, VisualViewportOffset) {
To<LocalFrame>(web_view->GetPage()->MainFrame())->View();
{
- WebMouseEvent web_mouse_event(WebInputEvent::kMouseMove,
+ WebMouseEvent web_mouse_event(WebInputEvent::Type::kMouseMove,
WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests());
web_mouse_event.SetPositionInWidget(10, 10);
@@ -678,7 +680,7 @@ TEST(WebInputEventConversionTest, VisualViewportOffset) {
{
WebMouseWheelEvent web_mouse_wheel_event(
- WebInputEvent::kMouseWheel, WebInputEvent::kNoModifiers,
+ WebInputEvent::Type::kMouseWheel, WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests());
web_mouse_wheel_event.SetPositionInWidget(10, 10);
web_mouse_wheel_event.SetPositionInScreen(10, 10);
@@ -695,7 +697,7 @@ TEST(WebInputEventConversionTest, VisualViewportOffset) {
{
WebGestureEvent web_gesture_event(
- WebInputEvent::kGestureScrollUpdate, WebInputEvent::kNoModifiers,
+ WebInputEvent::Type::kGestureScrollUpdate, WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests(),
WebGestureDevice::kTouchscreen);
web_gesture_event.SetPositionInWidget(gfx::PointF(10, 10));
@@ -713,7 +715,7 @@ TEST(WebInputEventConversionTest, VisualViewportOffset) {
{
WebPointerEvent web_pointer_event(
- WebInputEvent::kPointerDown,
+ WebInputEvent::Type::kPointerDown,
WebPointerProperties(1, WebPointerProperties::PointerType::kTouch,
WebPointerProperties::Button::kLeft,
gfx::PointF(10.6f, 10.4f),
@@ -760,7 +762,7 @@ TEST(WebInputEventConversionTest, ElasticOverscroll) {
// Just elastic overscroll.
{
- WebMouseEvent web_mouse_event(WebInputEvent::kMouseMove,
+ WebMouseEvent web_mouse_event(WebInputEvent::Type::kMouseMove,
WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests());
web_mouse_event.SetPositionInWidget(10, 50);
@@ -789,7 +791,7 @@ TEST(WebInputEventConversionTest, ElasticOverscroll) {
FloatPoint visual_offset(35, 60);
web_view->GetPage()->GetVisualViewport().SetLocation(visual_offset);
{
- WebMouseEvent web_mouse_event(WebInputEvent::kMouseMove,
+ WebMouseEvent web_mouse_event(WebInputEvent::Type::kMouseMove,
WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests());
web_mouse_event.SetPositionInWidget(10, 10);
@@ -838,7 +840,7 @@ TEST(WebInputEventConversionTest, ElasticOverscrollWithPageReload) {
// Just elastic overscroll.
{
- WebMouseEvent web_mouse_event(WebInputEvent::kMouseMove,
+ WebMouseEvent web_mouse_event(WebInputEvent::Type::kMouseMove,
WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests());
web_mouse_event.SetPositionInWidget(10, 50);
diff --git a/chromium/third_party/blink/renderer/core/execution_context/agent_metrics_collector.cc b/chromium/third_party/blink/renderer/core/execution_context/agent_metrics_collector.cc
index 202a52d8614..e2709000828 100644
--- a/chromium/third_party/blink/renderer/core/execution_context/agent_metrics_collector.cc
+++ b/chromium/third_party/blink/renderer/core/execution_context/agent_metrics_collector.cc
@@ -12,6 +12,7 @@
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/execution_context/window_agent.h"
#include "third_party/blink/renderer/platform/instrumentation/histogram.h"
+#include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h"
#include "third_party/blink/renderer/platform/web_test_support.h"
#include "third_party/blink/renderer/platform/wtf/hash_set.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
@@ -41,7 +42,8 @@ AgentMetricsCollector::AgentMetricsCollector()
: nullptr,
this,
&AgentMetricsCollector::ReportingTimerFired)),
- clock_(base::DefaultTickClock::GetInstance()) {
+ clock_(base::DefaultTickClock::GetInstance()),
+ agent_metrics_collector_host_(nullptr) {
// From now until we call CreatedNewAgent will be reported as having 0
// agents.
time_last_reported_ = clock_->NowTicks();
@@ -160,17 +162,19 @@ void AgentMetricsCollector::ReportingTimerFired(TimerBase*) {
ReportToBrowser();
}
-mojo::Remote<blink::mojom::blink::AgentMetricsCollectorHost>&
+blink::mojom::blink::AgentMetricsCollectorHost*
AgentMetricsCollector::GetAgentMetricsCollectorHost() {
- if (!agent_metrics_collector_host_) {
+ if (!agent_metrics_collector_host_.is_bound()) {
blink::Platform::Current()->GetBrowserInterfaceBroker()->GetInterface(
- agent_metrics_collector_host_.BindNewPipeAndPassReceiver());
+ agent_metrics_collector_host_.BindNewPipeAndPassReceiver(
+ ThreadScheduler::Current()->IPCTaskRunner()));
}
- return agent_metrics_collector_host_;
+ return agent_metrics_collector_host_.get();
}
void AgentMetricsCollector::Trace(Visitor* visitor) {
visitor->Trace(agent_to_documents_map_);
+ visitor->Trace(agent_metrics_collector_host_);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/execution_context/agent_metrics_collector.h b/chromium/third_party/blink/renderer/core/execution_context/agent_metrics_collector.h
index b92e88b857d..6776517dc78 100644
--- a/chromium/third_party/blink/renderer/core/execution_context/agent_metrics_collector.h
+++ b/chromium/third_party/blink/renderer/core/execution_context/agent_metrics_collector.h
@@ -6,8 +6,9 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_EXECUTION_CONTEXT_AGENT_METRICS_COLLECTOR_H_
#include "base/time/time.h"
-#include "mojo/public/cpp/bindings/remote.h"
#include "third_party/blink/public/mojom/agents/agent_metrics.mojom-blink.h"
+#include "third_party/blink/renderer/platform/mojo/heap_mojo_remote.h"
+#include "third_party/blink/renderer/platform/mojo/heap_mojo_wrapper_mode.h"
#include "third_party/blink/renderer/platform/timer.h"
namespace base {
@@ -61,7 +62,7 @@ class AgentMetricsCollector final
void ReportingTimerFired(TimerBase*);
- mojo::Remote<blink::mojom::blink::AgentMetricsCollectorHost>&
+ blink::mojom::blink::AgentMetricsCollectorHost*
GetAgentMetricsCollectorHost();
std::unique_ptr<TaskRunnerTimer<AgentMetricsCollector>> reporting_timer_;
@@ -77,7 +78,8 @@ class AgentMetricsCollector final
const base::TickClock* clock_;
- mojo::Remote<blink::mojom::blink::AgentMetricsCollectorHost>
+ HeapMojoRemote<blink::mojom::blink::AgentMetricsCollectorHost,
+ HeapMojoWrapperMode::kWithoutContextObserver>
agent_metrics_collector_host_;
};
diff --git a/chromium/third_party/blink/renderer/core/execution_context/execution_context.cc b/chromium/third_party/blink/renderer/core/execution_context/execution_context.cc
index eaa55b5533c..fa809d6a4bc 100644
--- a/chromium/third_party/blink/renderer/core/execution_context/execution_context.cc
+++ b/chromium/third_party/blink/renderer/core/execution_context/execution_context.cc
@@ -239,11 +239,13 @@ ContentSecurityPolicy* ExecutionContext::GetContentSecurityPolicy() const {
return GetSecurityContext().GetContentSecurityPolicy();
}
-mojom::blink::WebSandboxFlags ExecutionContext::GetSandboxFlags() const {
+network::mojom::blink::WebSandboxFlags ExecutionContext::GetSandboxFlags()
+ const {
return GetSecurityContext().GetSandboxFlags();
}
-bool ExecutionContext::IsSandboxed(mojom::blink::WebSandboxFlags mask) const {
+bool ExecutionContext::IsSandboxed(
+ network::mojom::blink::WebSandboxFlags mask) const {
return GetSecurityContext().IsSandboxed(mask);
}
@@ -347,9 +349,7 @@ bool ExecutionContext::IsSameAgentCluster(
}
v8::MicrotaskQueue* ExecutionContext::GetMicrotaskQueue() const {
- // TODO(keishi): Convert to DCHECK once we assign agents everywhere.
- if (!GetAgent())
- return nullptr;
+ DCHECK(GetAgent());
DCHECK(GetAgent()->event_loop());
return GetAgent()->event_loop()->microtask_queue();
}
@@ -393,24 +393,7 @@ void ExecutionContext::FeaturePolicyPotentialBehaviourChangeObserved(
bool ExecutionContext::IsFeatureEnabled(
mojom::blink::FeaturePolicyFeature feature,
ReportOptions report_on_failure,
- const String& message,
- const String& source_file) const {
- PolicyValue threshold_value =
- PolicyValue::CreateMaxPolicyValue(GetSecurityContext()
- .GetFeaturePolicy()
- ->GetFeatureList()
- .at(feature)
- .second);
- return IsFeatureEnabled(feature, threshold_value, report_on_failure, message,
- source_file);
-}
-
-bool ExecutionContext::IsFeatureEnabled(
- mojom::blink::FeaturePolicyFeature feature,
- PolicyValue threshold_value,
- ReportOptions report_on_failure,
- const String& message,
- const String& source_file) const {
+ const String& message) const {
if (report_on_failure == ReportOptions::kReportOnFailure) {
// We are expecting a violation report in case the feature is disabled in
// the context. Therefore, this qualifies as a potential violation (i.e.,
@@ -419,16 +402,14 @@ bool ExecutionContext::IsFeatureEnabled(
}
bool should_report;
- bool enabled = GetSecurityContext().IsFeatureEnabled(feature, threshold_value,
- &should_report);
+ bool enabled = GetSecurityContext().IsFeatureEnabled(feature, &should_report);
if (enabled) {
// Report if the proposed header semantics change would have affected the
// outcome. (https://crbug.com/937131)
const FeaturePolicy* policy = GetSecurityContext().GetFeaturePolicy();
url::Origin origin = GetSecurityOrigin()->ToUrlOrigin();
- if (policy->GetProposedFeatureValueForOrigin(feature, origin) <
- threshold_value) {
+ if (!policy->GetProposedFeatureValueForOrigin(feature, origin)) {
// Count that there was a change in this page load.
const_cast<ExecutionContext*>(this)->CountUse(
WebFeature::kFeaturePolicyProposalWouldChangeBehaviour);
@@ -441,7 +422,7 @@ bool ExecutionContext::IsFeatureEnabled(
mojom::blink::PolicyDisposition disposition =
enabled ? mojom::blink::PolicyDisposition::kReport
: mojom::blink::PolicyDisposition::kEnforce;
- ReportFeaturePolicyViolation(feature, disposition, message, source_file);
+ ReportFeaturePolicyViolation(feature, disposition, message);
}
return enabled;
}
diff --git a/chromium/third_party/blink/renderer/core/execution_context/execution_context.h b/chromium/third_party/blink/renderer/core/execution_context/execution_context.h
index b92345fd50d..67c8ee23660 100644
--- a/chromium/third_party/blink/renderer/core/execution_context/execution_context.h
+++ b/chromium/third_party/blink/renderer/core/execution_context/execution_context.h
@@ -36,6 +36,7 @@
#include "base/optional.h"
#include "base/unguessable_token.h"
#include "services/network/public/mojom/referrer_policy.mojom-blink-forward.h"
+#include "third_party/blink/public/mojom/devtools/inspector_issue.mojom-blink-forward.h"
#include "third_party/blink/public/mojom/feature_policy/feature_policy.mojom-blink-forward.h"
#include "third_party/blink/public/mojom/feature_policy/feature_policy_feature.mojom-blink-forward.h"
#include "third_party/blink/public/mojom/feature_policy/policy_disposition.mojom-blink-forward.h"
@@ -155,8 +156,8 @@ class CORE_EXPORT ExecutionContext : public Supplementable<ExecutionContext>,
ContentSecurityPolicy* GetContentSecurityPolicy() const;
- mojom::blink::WebSandboxFlags GetSandboxFlags() const;
- bool IsSandboxed(mojom::blink::WebSandboxFlags mask) const;
+ network::mojom::blink::WebSandboxFlags GetSandboxFlags() const;
+ bool IsSandboxed(network::mojom::blink::WebSandboxFlags mask) const;
// Returns the content security policy to be used based on the current
// JavaScript world we are in.
@@ -171,7 +172,6 @@ class CORE_EXPORT ExecutionContext : public Supplementable<ExecutionContext>,
virtual const KURL& BaseURL() const = 0;
virtual KURL CompleteURL(const String& url) const = 0;
virtual void DisableEval(const String& error_message) = 0;
- virtual LocalDOMWindow* ExecutingWindow() const { return nullptr; }
virtual String UserAgent() const = 0;
virtual HttpsState GetHttpsState() const = 0;
@@ -191,10 +191,7 @@ class CORE_EXPORT ExecutionContext : public Supplementable<ExecutionContext>,
virtual const SecurityContext& GetSecurityContext() const = 0;
// https://tc39.github.io/ecma262/#sec-agent-clusters
- // TODO(dtapuska): Remove this virtual once all execution_contexts
- // always have an agent. Worklets currently override this because
- // they don't have agents.
- virtual const base::UnguessableToken& GetAgentClusterID() const;
+ const base::UnguessableToken& GetAgentClusterID() const;
bool IsSameAgentCluster(const base::UnguessableToken&) const;
@@ -221,6 +218,7 @@ class CORE_EXPORT ExecutionContext : public Supplementable<ExecutionContext>,
bool discard_duplicates = false) {
AddConsoleMessageImpl(message, discard_duplicates);
}
+ virtual void AddInspectorIssue(mojom::blink::InspectorIssueInfoPtr) = 0;
bool IsContextPaused() const;
bool IsContextDestroyed() const { return is_context_destroyed_; }
@@ -303,14 +301,7 @@ class CORE_EXPORT ExecutionContext : public Supplementable<ExecutionContext>,
bool IsFeatureEnabled(
mojom::blink::FeaturePolicyFeature,
ReportOptions report_on_failure = ReportOptions::kDoNotReport,
- const String& message = g_empty_string,
- const String& source_file = g_empty_string) const;
- bool IsFeatureEnabled(
- mojom::blink::FeaturePolicyFeature,
- PolicyValue threshold_value,
- ReportOptions report_on_failure = ReportOptions::kDoNotReport,
- const String& message = g_empty_string,
- const String& source_file = g_empty_string) const;
+ const String& message = g_empty_string) const;
bool IsFeatureEnabled(
mojom::blink::DocumentPolicyFeature,
ReportOptions report_option = ReportOptions::kDoNotReport,
@@ -332,8 +323,7 @@ class CORE_EXPORT ExecutionContext : public Supplementable<ExecutionContext>,
virtual void ReportFeaturePolicyViolation(
mojom::blink::FeaturePolicyFeature,
mojom::blink::PolicyDisposition,
- const String& message = g_empty_string,
- const String& source_file = g_empty_string) const {}
+ const String& message = g_empty_string) const {}
virtual void ReportDocumentPolicyViolation(
mojom::blink::DocumentPolicyFeature,
mojom::blink::PolicyDisposition,
diff --git a/chromium/third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.cc b/chromium/third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.cc
index b8fdc6e4d37..a0a4c1b0566 100644
--- a/chromium/third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.cc
+++ b/chromium/third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.cc
@@ -15,8 +15,7 @@ ExecutionContextClient::ExecutionContextClient(
: execution_context_(execution_context) {}
ExecutionContextClient::ExecutionContextClient(LocalFrame* frame)
- : execution_context_(frame ? frame->GetDocument()->ToExecutionContext()
- : nullptr) {}
+ : execution_context_(frame ? frame->DomWindow() : nullptr) {}
ExecutionContext* ExecutionContextClient::GetExecutionContext() const {
return execution_context_ && !execution_context_->IsContextDestroyed()
@@ -24,32 +23,19 @@ ExecutionContext* ExecutionContextClient::GetExecutionContext() const {
: nullptr;
}
-Document* ExecutionContextClient::GetDocument() const {
- return execution_context_
- ? Document::DynamicFrom(
- static_cast<ExecutionContext*>(execution_context_))
- : nullptr;
+LocalDOMWindow* ExecutionContextClient::DomWindow() const {
+ return DynamicTo<LocalDOMWindow>(GetExecutionContext());
}
LocalFrame* ExecutionContextClient::GetFrame() const {
- auto* document = GetDocument();
- return document ? document->GetFrame() : nullptr;
+ auto* window = DomWindow();
+ return window ? window->GetFrame() : nullptr;
}
void ExecutionContextClient::Trace(Visitor* visitor) {
visitor->Trace(execution_context_);
}
-ExecutionContextLifecycleObserver::ExecutionContextLifecycleObserver()
- : observer_type_(kGenericType) {}
-
-ExecutionContextLifecycleObserver::ExecutionContextLifecycleObserver(
- Document* document,
- Type type)
- : ExecutionContextLifecycleObserver(
- document ? document->ToExecutionContext() : nullptr,
- type) {}
-
ExecutionContextLifecycleObserver::ExecutionContextLifecycleObserver(
ExecutionContext* execution_context,
Type type)
@@ -68,29 +54,12 @@ void ExecutionContextLifecycleObserver::SetExecutionContext(
}
LocalFrame* ExecutionContextLifecycleObserver::GetFrame() const {
- auto* document = Document::DynamicFrom(GetExecutionContext());
- return document ? document->GetFrame() : nullptr;
+ auto* window = DynamicTo<LocalDOMWindow>(GetExecutionContext());
+ return window ? window->GetFrame() : nullptr;
}
void ExecutionContextLifecycleObserver::Trace(Visitor* visitor) {
ContextLifecycleObserver::Trace(visitor);
}
-DOMWindowClient::DOMWindowClient(LocalDOMWindow* window)
- : dom_window_(window) {}
-
-DOMWindowClient::DOMWindowClient(LocalFrame* frame)
- : dom_window_(frame ? frame->DomWindow() : nullptr) {}
-
-LocalDOMWindow* DOMWindowClient::DomWindow() const {
- return dom_window_ && dom_window_->GetFrame() ? dom_window_ : nullptr;
-}
-
-LocalFrame* DOMWindowClient::GetFrame() const {
- return dom_window_ ? dom_window_->GetFrame() : nullptr;
-}
-
-void DOMWindowClient::Trace(Visitor* visitor) {
- visitor->Trace(dom_window_);
-}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.h b/chromium/third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.h
index c3d1d99bcf8..1ec555f1dd8 100644
--- a/chromium/third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.h
+++ b/chromium/third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.h
@@ -33,7 +33,6 @@
namespace blink {
class ExecutionContext;
-class Document;
class LocalDOMWindow;
class LocalFrame;
@@ -43,8 +42,8 @@ class LocalFrame;
// destructor of a GC object.
//
// To discourage incorrect usage, these objects both start returning null
-// once the execution context shuts down. For a document, this occurs when
-// the frame navigates to another document or is detached. For a worker global
+// once the execution context shuts down. For a window, this occurs when
+// the frame navigates to another window or is detached. For a worker global
// scope, this occurs when it shuts down.
//
// * If an object only needs to refer to a valid ExecutionContext but does not
@@ -63,17 +62,18 @@ class LocalFrame;
// derive from ActiveScriptWrappable.
// ExecutionContextClient provides access to the associated execution context
-// until it is shut down (e.g. for a document, at navigation or frame detach).
+// until it is shut down (e.g. for a window, at navigation or frame detach).
class CORE_EXPORT ExecutionContextClient : public GarbageCollectedMixin {
public:
// Returns the execution context until it is detached.
// From then on, returns null instead.
ExecutionContext* GetExecutionContext() const;
- // Return a live document if associated with it. Returns null otherwise.
- Document* GetDocument() const;
+ // If the execution context is a window, returns it. Returns nullptr if the
+ // execution context is not a window or if it has been detached.
+ LocalDOMWindow* DomWindow() const;
- // If associated with a live document, returns the associated frame.
+ // If associated with a live window, returns the associated frame.
// Returns null otherwise.
LocalFrame* GetFrame() const;
@@ -127,12 +127,6 @@ class CORE_EXPORT ExecutionContextLifecycleObserver
void Trace(Visitor*) override;
protected:
- ExecutionContextLifecycleObserver();
- // TODO(crbug.com/1029822): This is a shim to enable migrating
- // ExecutionContext to LocalDOMWindow.
- explicit ExecutionContextLifecycleObserver(Document*,
- Type type = kGenericType);
-
explicit ExecutionContextLifecycleObserver(
ExecutionContext* execution_context,
Type type = kGenericType);
@@ -141,44 +135,6 @@ class CORE_EXPORT ExecutionContextLifecycleObserver
Type observer_type_;
};
-// DOMWindowClient is a helper to associate an object with a LocalDOMWindow.
-//
-// - domWindow() returns null after the window is detached.
-// - frame() is a syntax sugar for domWindow()->frame(). It returns
-// null after the window is detached.
-//
-// Both can safely be used up until destruction; i.e., unsafe to
-// call upon in a destructor.
-//
-// If the object is a per-ExecutionContext thing, use ExecutionContextClient/
-// ExecutionContextLifecycleObserver. If the object is a per-DOMWindow thing,
-// use DOMWindowClient. Basically, DOMWindowClient is expected to be used (only)
-// for objects directly held by LocalDOMWindow. Other objects should use
-// ExecutionContextClient/ExecutionContextLifecycleObserver.
-//
-// There is a subtle difference between the timing when the context gets
-// detached and the timing when the window gets detached. In common cases,
-// these two happen at the same timing. The only exception is a case where
-// a frame navigates from an initial empty document to another same-origin
-// document. In this case, a Document is recreated but a DOMWindow is reused.
-// Hence, in the navigated document
-// ExecutionContextClient::GetExecutionContext() returns null while
-// DOMWindowClient::domWindow() keeps returning the window.
-class CORE_EXPORT DOMWindowClient : public GarbageCollectedMixin {
- public:
- LocalDOMWindow* DomWindow() const;
- LocalFrame* GetFrame() const;
-
- void Trace(Visitor*) override;
-
- protected:
- explicit DOMWindowClient(LocalDOMWindow*);
- explicit DOMWindowClient(LocalFrame*);
-
- private:
- WeakMember<LocalDOMWindow> dom_window_;
-};
-
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_CORE_EXECUTION_CONTEXT_EXECUTION_CONTEXT_LIFECYCLE_OBSERVER_H_
diff --git a/chromium/third_party/blink/renderer/core/execution_context/execution_context_lifecycle_state_observer.cc b/chromium/third_party/blink/renderer/core/execution_context/execution_context_lifecycle_state_observer.cc
index 328edfa5c62..25ae020d6bd 100644
--- a/chromium/third_party/blink/renderer/core/execution_context/execution_context_lifecycle_state_observer.cc
+++ b/chromium/third_party/blink/renderer/core/execution_context/execution_context_lifecycle_state_observer.cc
@@ -27,7 +27,6 @@
#include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_state_observer.h"
#include "third_party/blink/public/mojom/frame/lifecycle.mojom-blink.h"
-#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/platform/instrumentation/instance_counters.h"
@@ -41,11 +40,6 @@ ExecutionContextLifecycleStateObserver::ExecutionContextLifecycleStateObserver(
InstanceCounters::kContextLifecycleStateObserverCounter);
}
-ExecutionContextLifecycleStateObserver::ExecutionContextLifecycleStateObserver(
- Document* document)
- : ExecutionContextLifecycleStateObserver(
- document ? document->ToExecutionContext() : nullptr) {}
-
ExecutionContextLifecycleStateObserver::
~ExecutionContextLifecycleStateObserver() {
InstanceCounters::DecrementCounter(
diff --git a/chromium/third_party/blink/renderer/core/execution_context/execution_context_lifecycle_state_observer.h b/chromium/third_party/blink/renderer/core/execution_context/execution_context_lifecycle_state_observer.h
index 01f0955e521..58fe02e5f54 100644
--- a/chromium/third_party/blink/renderer/core/execution_context/execution_context_lifecycle_state_observer.h
+++ b/chromium/third_party/blink/renderer/core/execution_context/execution_context_lifecycle_state_observer.h
@@ -55,9 +55,6 @@ class CORE_EXPORT ExecutionContextLifecycleStateObserver
: public ExecutionContextLifecycleObserver {
public:
explicit ExecutionContextLifecycleStateObserver(ExecutionContext*);
- // TODO(crbug.com/1029822): This is a shim to enable migrating
- // ExecutionContext to LocalDOMWindow.
- explicit ExecutionContextLifecycleStateObserver(Document*);
// UpdateStateIfNeeded() should be called exactly once after object
// construction to synchronize the suspend state with that in
diff --git a/chromium/third_party/blink/renderer/core/execution_context/execution_context_lifecycle_state_observer_test.cc b/chromium/third_party/blink/renderer/core/execution_context/execution_context_lifecycle_state_observer_test.cc
index 4382e97201c..f15af12c7b3 100644
--- a/chromium/third_party/blink/renderer/core/execution_context/execution_context_lifecycle_state_observer_test.cc
+++ b/chromium/third_party/blink/renderer/core/execution_context/execution_context_lifecycle_state_observer_test.cc
@@ -33,7 +33,7 @@
#include <memory>
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/renderer/core/dom/document.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/testing/dummy_page_holder.h"
using testing::AnyNumber;
@@ -61,8 +61,14 @@ class ExecutionContextLifecycleStateObserverTest : public testing::Test {
protected:
ExecutionContextLifecycleStateObserverTest();
- Document& SrcDocument() const { return src_page_holder_->GetDocument(); }
- Document& DestDocument() const { return dest_page_holder_->GetDocument(); }
+ LocalDOMWindow* SrcWindow() const {
+ return src_page_holder_->GetFrame().DomWindow();
+ }
+ LocalDOMWindow* DestWindow() const {
+ return dest_page_holder_->GetFrame().DomWindow();
+ }
+
+ void ClearDestPage() { dest_page_holder_.reset(); }
MockExecutionContextLifecycleStateObserver& Observer() { return *observer_; }
private:
@@ -77,57 +83,48 @@ ExecutionContextLifecycleStateObserverTest::
dest_page_holder_(std::make_unique<DummyPageHolder>(IntSize(800, 600))),
observer_(
MakeGarbageCollected<MockExecutionContextLifecycleStateObserver>(
- src_page_holder_->GetDocument().ToExecutionContext())) {
+ src_page_holder_->GetFrame().DomWindow())) {
observer_->UpdateStateIfNeeded();
}
TEST_F(ExecutionContextLifecycleStateObserverTest, NewContextObserved) {
unsigned initial_src_count =
- SrcDocument()
- .ToExecutionContext()
- ->ContextLifecycleStateObserverCountForTesting();
+ SrcWindow()->ContextLifecycleStateObserverCountForTesting();
unsigned initial_dest_count =
- DestDocument()
- .ToExecutionContext()
- ->ContextLifecycleStateObserverCountForTesting();
+ DestWindow()->ContextLifecycleStateObserverCountForTesting();
EXPECT_CALL(Observer(), ContextLifecycleStateChanged(
mojom::FrameLifecycleState::kRunning));
EXPECT_CALL(Observer(), ContextDestroyed()).Times(AnyNumber());
- Observer().SetExecutionContext(DestDocument().ToExecutionContext());
+ Observer().SetExecutionContext(DestWindow());
EXPECT_EQ(initial_src_count - 1,
- SrcDocument()
- .ToExecutionContext()
- ->ContextLifecycleStateObserverCountForTesting());
+ SrcWindow()->ContextLifecycleStateObserverCountForTesting());
EXPECT_EQ(initial_dest_count + 1,
- DestDocument()
- .ToExecutionContext()
- ->ContextLifecycleStateObserverCountForTesting());
+ DestWindow()->ContextLifecycleStateObserverCountForTesting());
}
-TEST_F(ExecutionContextLifecycleStateObserverTest, MoveToActiveDocument) {
+TEST_F(ExecutionContextLifecycleStateObserverTest, MoveToActiveContext) {
EXPECT_CALL(Observer(), ContextLifecycleStateChanged(
mojom::FrameLifecycleState::kRunning));
EXPECT_CALL(Observer(), ContextDestroyed()).Times(AnyNumber());
- Observer().SetExecutionContext(DestDocument().ToExecutionContext());
+ Observer().SetExecutionContext(DestWindow());
}
-TEST_F(ExecutionContextLifecycleStateObserverTest, MoveToSuspendedDocument) {
- DestDocument().ToExecutionContext()->SetLifecycleState(
- mojom::FrameLifecycleState::kFrozen);
+TEST_F(ExecutionContextLifecycleStateObserverTest, MoveToSuspendedContext) {
+ DestWindow()->SetLifecycleState(mojom::FrameLifecycleState::kFrozen);
EXPECT_CALL(Observer(), ContextLifecycleStateChanged(
mojom::FrameLifecycleState::kFrozen));
EXPECT_CALL(Observer(), ContextDestroyed()).Times(AnyNumber());
- Observer().SetExecutionContext(DestDocument().ToExecutionContext());
+ Observer().SetExecutionContext(DestWindow());
}
-TEST_F(ExecutionContextLifecycleStateObserverTest, MoveToStoppedDocument) {
- DestDocument().Shutdown();
-
+TEST_F(ExecutionContextLifecycleStateObserverTest, MoveToStoppedContext) {
+ Persistent<LocalDOMWindow> window = DestWindow();
+ ClearDestPage();
EXPECT_CALL(Observer(), ContextDestroyed());
- Observer().SetExecutionContext(DestDocument().ToExecutionContext());
+ Observer().SetExecutionContext(window.Get());
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/execution_context/remote_security_context.cc b/chromium/third_party/blink/renderer/core/execution_context/remote_security_context.cc
index e97fffea95a..7a69758005a 100644
--- a/chromium/third_party/blink/renderer/core/execution_context/remote_security_context.cc
+++ b/chromium/third_party/blink/renderer/core/execution_context/remote_security_context.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/core/execution_context/remote_security_context.h"
+#include "services/network/public/mojom/web_sandbox_flags.mojom-blink.h"
#include "third_party/blink/renderer/core/execution_context/security_context_init.h"
#include "third_party/blink/renderer/core/frame/csp/content_security_policy.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
@@ -13,7 +14,7 @@
namespace blink {
RemoteSecurityContext::RemoteSecurityContext()
- : SecurityContext(SecurityContextInit(), kRemote) {
+ : SecurityContext(SecurityContextInit(), kRemoteFrame) {
// RemoteSecurityContext's origin is expected to stay uninitialized until
// we set it using replicated origin data from the browser process.
DCHECK(!GetSecurityOrigin());
@@ -40,10 +41,10 @@ void RemoteSecurityContext::ResetReplicatedContentSecurityPolicy() {
}
void RemoteSecurityContext::ResetAndEnforceSandboxFlags(
- mojom::blink::WebSandboxFlags flags) {
+ network::mojom::blink::WebSandboxFlags flags) {
sandbox_flags_ = flags;
- if (IsSandboxed(mojom::blink::WebSandboxFlags::kOrigin) &&
+ if (IsSandboxed(network::mojom::blink::WebSandboxFlags::kOrigin) &&
GetSecurityOrigin() && !GetSecurityOrigin()->IsOpaque()) {
SetSecurityOrigin(GetSecurityOrigin()->DeriveNewOpaqueOrigin());
}
diff --git a/chromium/third_party/blink/renderer/core/execution_context/remote_security_context.h b/chromium/third_party/blink/renderer/core/execution_context/remote_security_context.h
index 00042b460d8..b8005eead04 100644
--- a/chromium/third_party/blink/renderer/core/execution_context/remote_security_context.h
+++ b/chromium/third_party/blink/renderer/core/execution_context/remote_security_context.h
@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_EXECUTION_CONTEXT_REMOTE_SECURITY_CONTEXT_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_EXECUTION_CONTEXT_REMOTE_SECURITY_CONTEXT_H_
+#include "services/network/public/mojom/web_sandbox_flags.mojom-blink-forward.h"
#include "third_party/blink/public/common/feature_policy/feature_policy.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/execution_context/security_context.h"
@@ -18,7 +19,8 @@ class CORE_EXPORT RemoteSecurityContext final : public SecurityContext {
void SetReplicatedOrigin(scoped_refptr<SecurityOrigin>);
void ResetReplicatedContentSecurityPolicy();
- void ResetAndEnforceSandboxFlags(mojom::blink::WebSandboxFlags flags);
+ void ResetAndEnforceSandboxFlags(
+ network::mojom::blink::WebSandboxFlags flags);
// Constructs the enforcement FeaturePolicy struct for this security context.
// The resulting FeaturePolicy is a combination of:
diff --git a/chromium/third_party/blink/renderer/core/execution_context/security_context.cc b/chromium/third_party/blink/renderer/core/execution_context/security_context.cc
index 0d2018299ae..625a8f1339b 100644
--- a/chromium/third_party/blink/renderer/core/execution_context/security_context.cc
+++ b/chromium/third_party/blink/renderer/core/execution_context/security_context.cc
@@ -27,10 +27,13 @@
#include "third_party/blink/renderer/core/execution_context/security_context.h"
#include "base/metrics/histogram_macros.h"
+#include "services/network/public/cpp/web_sandbox_flags.h"
#include "services/network/public/mojom/ip_address_space.mojom-blink.h"
+#include "services/network/public/mojom/web_sandbox_flags.mojom-blink.h"
#include "third_party/blink/public/common/feature_policy/document_policy_features.h"
#include "third_party/blink/public/common/feature_policy/feature_policy.h"
#include "third_party/blink/public/mojom/feature_policy/feature_policy.mojom-blink.h"
+#include "third_party/blink/public/mojom/feature_policy/policy_value.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/renderer/core/execution_context/agent.h"
@@ -69,7 +72,7 @@ SecurityContext::SecurityContext(const SecurityContextInit& init,
insecure_request_policy_(
mojom::blink::InsecureRequestPolicy::kLeaveInsecureRequestsAlone),
require_safe_types_(false),
- context_type_(context_type),
+ context_type_for_asserts_(context_type),
agent_(init.GetAgent()),
secure_context_mode_(init.GetSecureContextMode()),
origin_trial_context_(init.GetOriginTrialContext()),
@@ -88,13 +91,21 @@ void SecurityContext::SetSecurityOrigin(
CHECK(security_origin);
// The purpose of this check is to ensure that the SecurityContext does not
// change after script has executed in the ExecutionContext. If this is a
- // RemoteSecurityContext, then there is no local script execution, so it is
- // safe for the SecurityOrigin to change.
- // Exempting null ExecutionContexts is also necessary because RemoteFrames and
- // RemoteSecurityContexts do not change when a cross-origin navigation happens
- // remotely.
- CHECK(context_type_ == kRemote || !security_origin_ ||
- security_origin_->CanAccess(security_origin.get()));
+ // RemoteSecurityContext, then there is no local script execution and the
+ // context is permitted to represent multiple origins over its lifetime, so it
+ // is safe for the SecurityOrigin to change.
+ // NOTE: A worker may need to make its origin opaque after the main worker
+ // script is loaded if the worker is origin-sandboxed. Specifically exempt
+ // that transition. See https://crbug.com/1068008. It would be great if we
+ // could get rid of this exemption.
+ bool is_worker_transition_to_opaque =
+ context_type_for_asserts_ == kWorker &&
+ IsSandboxed(network::mojom::blink::WebSandboxFlags::kOrigin) &&
+ security_origin->IsOpaque() &&
+ security_origin->GetOriginOrPrecursorOriginIfOpaque() == security_origin_;
+ CHECK(context_type_for_asserts_ == kRemoteFrame || !security_origin_ ||
+ security_origin_->CanAccess(security_origin.get()) ||
+ is_worker_transition_to_opaque);
security_origin_ = std::move(security_origin);
}
@@ -108,14 +119,21 @@ void SecurityContext::SetContentSecurityPolicy(
content_security_policy_ = content_security_policy;
}
-bool SecurityContext::IsSandboxed(mojom::blink::WebSandboxFlags mask) const {
+bool SecurityContext::IsSandboxed(
+ network::mojom::blink::WebSandboxFlags mask) const {
if (RuntimeEnabledFeatures::FeaturePolicyForSandboxEnabled()) {
mojom::blink::FeaturePolicyFeature feature =
FeaturePolicy::FeatureForSandboxFlag(mask);
if (feature != mojom::blink::FeaturePolicyFeature::kNotFound)
return !feature_policy_->IsFeatureEnabled(feature);
}
- return (sandbox_flags_ & mask) != mojom::blink::WebSandboxFlags::kNone;
+ return (sandbox_flags_ & mask) !=
+ network::mojom::blink::WebSandboxFlags::kNone;
+}
+
+void SecurityContext::ApplySandboxFlags(
+ network::mojom::blink::WebSandboxFlags flags) {
+ sandbox_flags_ |= flags;
}
void SecurityContext::SetRequireTrustedTypes() {
@@ -143,22 +161,13 @@ void SecurityContext::SetDocumentPolicyForTesting(
}
bool SecurityContext::IsFeatureEnabled(
- mojom::blink::FeaturePolicyFeature feature) const {
- return IsFeatureEnabled(
- feature, PolicyValue::CreateMaxPolicyValue(
- feature_policy_->GetFeatureList().at(feature).second));
-}
-
-bool SecurityContext::IsFeatureEnabled(
mojom::blink::FeaturePolicyFeature feature,
- PolicyValue threshold_value,
bool* should_report) const {
DCHECK(feature_policy_);
- bool feature_policy_result =
- feature_policy_->IsFeatureEnabled(feature, threshold_value);
+ bool feature_policy_result = feature_policy_->IsFeatureEnabled(feature);
bool report_only_feature_policy_result =
!report_only_feature_policy_ ||
- report_only_feature_policy_->IsFeatureEnabled(feature, threshold_value);
+ report_only_feature_policy_->IsFeatureEnabled(feature);
if (should_report) {
*should_report =
diff --git a/chromium/third_party/blink/renderer/core/execution_context/security_context.h b/chromium/third_party/blink/renderer/core/execution_context/security_context.h
index 1f7d760a026..f3621b043d1 100644
--- a/chromium/third_party/blink/renderer/core/execution_context/security_context.h
+++ b/chromium/third_party/blink/renderer/core/execution_context/security_context.h
@@ -32,8 +32,8 @@
#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "services/network/public/mojom/ip_address_space.mojom-blink-forward.h"
+#include "services/network/public/mojom/web_sandbox_flags.mojom-blink-forward.h"
#include "third_party/blink/public/common/feature_policy/document_policy.h"
-#include "third_party/blink/public/common/frame/sandbox_flags.h"
#include "third_party/blink/public/mojom/feature_policy/document_policy_feature.mojom-blink-forward.h"
#include "third_party/blink/public/mojom/feature_policy/feature_policy.mojom-blink-forward.h"
#include "third_party/blink/public/mojom/feature_policy/feature_policy_feature.mojom-blink-forward.h"
@@ -76,7 +76,8 @@ class CORE_EXPORT SecurityContext {
DISALLOW_NEW();
public:
- enum SecurityContextType { kLocal, kRemote };
+ // Used only for safety CHECKs.
+ enum SecurityContextType { kWindow, kWorker, kRemoteFrame };
SecurityContext(const SecurityContextInit&, SecurityContextType context_type);
virtual ~SecurityContext() = default;
@@ -104,13 +105,11 @@ class CORE_EXPORT SecurityContext {
// Like SetSecurityOrigin(), but no security CHECKs.
void SetSecurityOriginForTesting(scoped_refptr<SecurityOrigin>);
- mojom::blink::WebSandboxFlags GetSandboxFlags() const {
+ network::mojom::blink::WebSandboxFlags GetSandboxFlags() const {
return sandbox_flags_;
}
- bool IsSandboxed(mojom::blink::WebSandboxFlags mask) const;
- void ApplySandboxFlags(mojom::blink::WebSandboxFlags flags) {
- sandbox_flags_ |= flags;
- }
+ bool IsSandboxed(network::mojom::blink::WebSandboxFlags mask) const;
+ void ApplySandboxFlags(network::mojom::blink::WebSandboxFlags flags);
void SetAddressSpace(network::mojom::IPAddressSpace space) {
address_space_ = space;
@@ -165,9 +164,7 @@ class CORE_EXPORT SecurityContext {
// Use ExecutionContext::IsFeatureEnabled if a failure should be reported.
// |should_report| is an extra return value that indicates whether
// the potential violation should be reported.
- bool IsFeatureEnabled(mojom::blink::FeaturePolicyFeature) const;
bool IsFeatureEnabled(mojom::blink::FeaturePolicyFeature,
- PolicyValue threshold_value,
bool* should_report = nullptr) const;
bool IsFeatureEnabled(mojom::blink::DocumentPolicyFeature) const;
@@ -186,7 +183,7 @@ class CORE_EXPORT SecurityContext {
SecureContextMode GetSecureContextMode() const {
// secure_context_mode_ is not initialized for RemoteSecurityContexts.
- DCHECK_EQ(context_type_, kLocal);
+ DCHECK_NE(context_type_for_asserts_, kRemoteFrame);
return secure_context_mode_;
}
@@ -197,7 +194,7 @@ class CORE_EXPORT SecurityContext {
bool BindCSPImmediately() const { return bind_csp_immediately_; }
protected:
- mojom::blink::WebSandboxFlags sandbox_flags_;
+ network::mojom::blink::WebSandboxFlags sandbox_flags_;
scoped_refptr<SecurityOrigin> security_origin_;
std::unique_ptr<FeaturePolicy> feature_policy_;
std::unique_ptr<FeaturePolicy> report_only_feature_policy_;
@@ -211,7 +208,7 @@ class CORE_EXPORT SecurityContext {
mojom::blink::InsecureRequestPolicy insecure_request_policy_;
InsecureNavigationsSet insecure_navigations_to_upgrade_;
bool require_safe_types_;
- const SecurityContextType context_type_;
+ const SecurityContextType context_type_for_asserts_;
Member<Agent> agent_;
SecureContextMode secure_context_mode_;
Member<OriginTrialContext> origin_trial_context_;
diff --git a/chromium/third_party/blink/renderer/core/execution_context/security_context_init.cc b/chromium/third_party/blink/renderer/core/execution_context/security_context_init.cc
index b667fa50ad6..960e816f9b1 100644
--- a/chromium/third_party/blink/renderer/core/execution_context/security_context_init.cc
+++ b/chromium/third_party/blink/renderer/core/execution_context/security_context_init.cc
@@ -4,6 +4,8 @@
#include "third_party/blink/renderer/core/execution_context/security_context_init.h"
+#include "base/metrics/histogram_macros.h"
+#include "services/network/public/cpp/web_sandbox_flags.h"
#include "third_party/blink/public/mojom/devtools/console_message.mojom-blink.h"
#include "third_party/blink/renderer/core/dom/document_init.h"
#include "third_party/blink/renderer/core/dom/element.h"
@@ -14,6 +16,7 @@
#include "third_party/blink/renderer/core/frame/csp/content_security_policy.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/local_frame_client.h"
+#include "third_party/blink/renderer/core/frame/sandbox_flags.h"
#include "third_party/blink/renderer/core/frame/settings.h"
#include "third_party/blink/renderer/core/html/imports/html_imports_controller.h"
#include "third_party/blink/renderer/core/inspector/console_message.h"
@@ -118,7 +121,7 @@ void SecurityContextInit::ApplyPendingDataToDocument(Document& document) const {
for (auto feature : feature_count_)
UseCounter::Count(document, feature);
for (auto feature : parsed_feature_policies_)
- document.ToExecutionContext()->FeaturePolicyFeatureObserved(feature);
+ document.GetExecutionContext()->FeaturePolicyFeatureObserved(feature);
for (const auto& message : feature_policy_parse_messages_) {
document.AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>(
mojom::ConsoleMessageSource::kSecurity,
@@ -133,78 +136,40 @@ void SecurityContextInit::ApplyPendingDataToDocument(Document& document) const {
}
if (!report_only_feature_policy_header_.empty())
UseCounter::Count(document, WebFeature::kFeaturePolicyReportOnlyHeader);
-}
-
-void SecurityContextInit::InitializeContentSecurityPolicy(
- const DocumentInit& initializer) {
- auto* frame = initializer.GetFrame();
- ContentSecurityPolicy* last_origin_document_csp =
- frame ? frame->Loader().GetLastOriginDocumentCSP() : nullptr;
-
- KURL url;
- if (initializer.ShouldSetURL())
- url = initializer.Url().IsEmpty() ? BlankURL() : initializer.Url();
- // Alias certain security properties from |owner_document|. Used for the
- // case of about:blank pages inheriting the security properties of their
- // requestor context.
- //
- // Note that this is currently somewhat broken; Blink always inherits from
- // the parent or opener, even though it should actually be inherited from
- // the request initiator.
- if (url.IsEmpty() && initializer.HasSecurityContext() &&
- !initializer.OriginToCommit() && initializer.OwnerDocument()) {
- last_origin_document_csp =
- initializer.OwnerDocument()->GetContentSecurityPolicy();
- }
-
- csp_ = initializer.GetContentSecurityPolicy();
+ if (!document_policy_.feature_state.empty())
+ UseCounter::Count(document, WebFeature::kDocumentPolicyHeader);
- if (!csp_) {
- if (initializer.ImportsController()) {
- // If this document is an HTML import, grab a reference to its master
- // document's Content Security Policy. We don't bind the CSP's delegate
- // in 'InitSecurityPolicy' in this case, as we can't rebind the master
- // document's policy object: The Content Security Policy's delegate
- // needs to remain set to the master document.
- csp_ =
- initializer.ImportsController()->Master()->GetContentSecurityPolicy();
- return;
- }
+ if (!report_only_document_policy_.feature_state.empty())
+ UseCounter::Count(document, WebFeature::kDocumentPolicyReportOnlyHeader);
- csp_ = MakeGarbageCollected<ContentSecurityPolicy>();
- bind_csp_immediately_ = true;
+ for (const auto& policy_entry : document_policy_.feature_state) {
+ UMA_HISTOGRAM_ENUMERATION("Blink.UseCounter.DocumentPolicy.Header",
+ policy_entry.first);
}
+}
- // We should inherit the navigation initiator CSP if the document is loaded
- // using a local-scheme url.
+void SecurityContextInit::InitializeContentSecurityPolicy(
+ const DocumentInit& initializer) {
+ // --------------
+ // THE MAIN PATH:
+ // --------------
//
- // Note: about:srcdoc inherits CSP from its parent, not from its initiator.
- // In this case, the initializer.GetContentSecurityPolicy() is used.
- if (last_origin_document_csp && !url.IsAboutSrcdocURL() &&
- (url.IsEmpty() || url.ProtocolIsAbout() || url.ProtocolIsData() ||
- url.ProtocolIs("blob") || url.ProtocolIs("filesystem"))) {
- csp_->CopyStateFrom(last_origin_document_csp);
- }
-
- if (initializer.GetType() == DocumentInit::Type::kPlugin) {
- if (last_origin_document_csp) {
- csp_->CopyPluginTypesFrom(last_origin_document_csp);
- return;
- }
+ // This path is used (among others) to load a document inside a frame. In this
+ // case, the CSP is computed by:
+ // - FrameLoader::CreateCSPForInitialEmptyDocument() or
+ // - FrameLoader::CreateCSP().
+ csp_ = initializer.GetContentSecurityPolicy();
+ if (csp_)
+ return;
- // TODO(andypaicu): This should inherit the origin document's plugin types
- // but because this could be a OOPIF document it might not have access. In
- // this situation we fallback on using the parent/opener:
- if (frame) {
- Frame* inherit_from = frame->Tree().Parent() ? frame->Tree().Parent()
- : frame->Client()->Opener();
- if (inherit_from && frame != inherit_from) {
- csp_->CopyPluginTypesFrom(
- inherit_from->GetSecurityContext()->GetContentSecurityPolicy());
- }
- }
- }
+ // A few users of DocumentInit do not specify the CSP to be used. An empty CSP
+ // is used in this case.
+ // TODO(arthursonzogni): Audit every users of DocumentInit::Create() that do
+ // not specify a CSP to be used. Ideally they should be forced to explicitly
+ // choose one.
+ csp_ = MakeGarbageCollected<ContentSecurityPolicy>();
+ bind_csp_immediately_ = true;
}
void SecurityContextInit::InitializeSandboxFlags(
@@ -218,9 +183,9 @@ void SecurityContextInit::InitializeSandboxFlags(
// Document's URL and origin. Instead, force a Document loaded from a
// MHTML archive to be sandboxed, providing exceptions only for creating
// new windows.
- sandbox_flags_ |= (mojom::blink::WebSandboxFlags::kAll &
- ~(mojom::blink::WebSandboxFlags::kPopups |
- mojom::blink::WebSandboxFlags::
+ sandbox_flags_ |= (network::mojom::blink::WebSandboxFlags::kAll &
+ ~(network::mojom::blink::WebSandboxFlags::kPopups |
+ network::mojom::blink::WebSandboxFlags::
kPropagatesToAuxiliaryBrowsingContexts));
}
}
@@ -228,8 +193,8 @@ void SecurityContextInit::InitializeSandboxFlags(
void SecurityContextInit::InitializeOrigin(const DocumentInit& initializer) {
scoped_refptr<SecurityOrigin> document_origin =
initializer.GetDocumentOrigin();
- if ((sandbox_flags_ & mojom::blink::WebSandboxFlags::kOrigin) !=
- mojom::blink::WebSandboxFlags::kNone) {
+ if ((sandbox_flags_ & network::mojom::blink::WebSandboxFlags::kOrigin) !=
+ network::mojom::blink::WebSandboxFlags::kNone) {
scoped_refptr<SecurityOrigin> sandboxed_origin =
initializer.OriginToCommit() ? initializer.OriginToCommit()
: document_origin->DeriveNewOpaqueOrigin();
@@ -300,15 +265,26 @@ void SecurityContextInit::InitializeOrigin(const DocumentInit& initializer) {
void SecurityContextInit::InitializeDocumentPolicy(
const DocumentInit& initializer) {
+ if (!RuntimeEnabledFeatures::DocumentPolicyEnabled(this))
+ return;
+
// Because Document-Policy http header is parsed in DocumentLoader,
// when origin trial context is not initialized yet.
// Needs to filter out features that are not in origin trial after
// we have origin trial information available.
document_policy_ = FilterByOriginTrial(initializer.GetDocumentPolicy(), this);
+ // Handle Report-Only-Document-Policy HTTP header.
+ // Console messages generated from logger are discarded, because currently
+ // there is no way to output them to console.
+ // Calling |Document::AddConsoleMessage| in
+ // |SecurityContextInit::ApplyPendingDataToDocument| will have no effect,
+ // because when the function is called, the document is not fully initialized
+ // yet (|document_| field in current frame is not yet initialized yet).
+ PolicyParserMessageBuffer logger("%s", /* discard_message */ true);
base::Optional<DocumentPolicy::ParsedDocumentPolicy>
report_only_parsed_policy = DocumentPolicyParser::Parse(
- initializer.ReportOnlyDocumentPolicyHeader());
+ initializer.ReportOnlyDocumentPolicyHeader(), logger);
if (report_only_parsed_policy) {
report_only_document_policy_ =
FilterByOriginTrial(*report_only_parsed_policy, this);
@@ -337,7 +313,7 @@ void SecurityContextInit::InitializeFeaturePolicy(
initializer.ReportOnlyFeaturePolicyHeader(), security_origin_,
&report_only_feature_policy_parse_messages_, this);
- if (sandbox_flags_ != mojom::blink::WebSandboxFlags::kNone &&
+ if (sandbox_flags_ != network::mojom::blink::WebSandboxFlags::kNone &&
RuntimeEnabledFeatures::FeaturePolicyForSandboxEnabled()) {
// The sandbox flags might have come from CSP header or the browser; in
// such cases the sandbox is not part of the container policy. They are
@@ -356,8 +332,8 @@ void SecurityContextInit::InitializeFeaturePolicy(
// feature policy is initialized.
if (RuntimeEnabledFeatures::BlockingFocusWithoutUserActivationEnabled() &&
frame && frame->Tree().Parent() &&
- (sandbox_flags_ & mojom::blink::WebSandboxFlags::kNavigation) !=
- mojom::blink::WebSandboxFlags::kNone) {
+ (sandbox_flags_ & network::mojom::blink::WebSandboxFlags::kNavigation) !=
+ network::mojom::blink::WebSandboxFlags::kNone) {
// Enforcing the policy for sandbox frames (for context see
// https://crbug.com/954349).
DisallowFeatureIfNotPresent(
@@ -464,7 +440,7 @@ void SecurityContextInit::InitializeSecureContextMode(
secure_context_mode_ = SecureContextMode::kInsecureContext;
}
bool is_secure = secure_context_mode_ == SecureContextMode::kSecureContext;
- if (GetSandboxFlags() != mojom::blink::WebSandboxFlags::kNone) {
+ if (GetSandboxFlags() != network::mojom::blink::WebSandboxFlags::kNone) {
feature_count_.insert(
is_secure ? WebFeature::kSecureContextCheckForSandboxedOriginPassed
: WebFeature::kSecureContextCheckForSandboxedOriginFailed);
diff --git a/chromium/third_party/blink/renderer/core/execution_context/security_context_init.h b/chromium/third_party/blink/renderer/core/execution_context/security_context_init.h
index 5546eafbd70..e6157437da6 100644
--- a/chromium/third_party/blink/renderer/core/execution_context/security_context_init.h
+++ b/chromium/third_party/blink/renderer/core/execution_context/security_context_init.h
@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_EXECUTION_CONTEXT_SECURITY_CONTEXT_INIT_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_EXECUTION_CONTEXT_SECURITY_CONTEXT_INIT_H_
+#include "services/network/public/mojom/web_sandbox_flags.mojom-blink.h"
#include "third_party/blink/public/common/feature_policy/feature_policy.h"
#include "third_party/blink/public/mojom/feature_policy/feature_policy_feature.mojom-blink.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
@@ -38,7 +39,7 @@ class CORE_EXPORT SecurityContextInit : public FeaturePolicyParserDelegate {
return security_origin_;
}
- mojom::blink::WebSandboxFlags GetSandboxFlags() const {
+ network::mojom::blink::WebSandboxFlags GetSandboxFlags() const {
return sandbox_flags_;
}
@@ -91,8 +92,8 @@ class CORE_EXPORT SecurityContextInit : public FeaturePolicyParserDelegate {
void InitializeAgent(const DocumentInit&);
scoped_refptr<SecurityOrigin> security_origin_;
- mojom::blink::WebSandboxFlags sandbox_flags_ =
- mojom::blink::WebSandboxFlags::kNone;
+ network::mojom::blink::WebSandboxFlags sandbox_flags_ =
+ network::mojom::blink::WebSandboxFlags::kNone;
DocumentPolicy::ParsedDocumentPolicy document_policy_;
DocumentPolicy::ParsedDocumentPolicy report_only_document_policy_;
bool initialized_feature_policy_state_ = false;
diff --git a/chromium/third_party/blink/renderer/core/exported/BUILD.gn b/chromium/third_party/blink/renderer/core/exported/BUILD.gn
index 347d7237ce5..f1ed480efe6 100644
--- a/chromium/third_party/blink/renderer/core/exported/BUILD.gn
+++ b/chromium/third_party/blink/renderer/core/exported/BUILD.gn
@@ -87,7 +87,7 @@ blink_core_sources("exported") {
deps = [
"//ui/base/cursor",
- "//ui/base/mojom:cursor_type_blink",
+ "//ui/base/cursor/mojom:cursor_type_blink",
]
defines = [ "BLINK_IMPLEMENTATION=1" ]
diff --git a/chromium/third_party/blink/renderer/core/exported/local_frame_client_impl.cc b/chromium/third_party/blink/renderer/core/exported/local_frame_client_impl.cc
index cb7aa76af1c..e8cc8ddcd59 100644
--- a/chromium/third_party/blink/renderer/core/exported/local_frame_client_impl.cc
+++ b/chromium/third_party/blink/renderer/core/exported/local_frame_client_impl.cc
@@ -71,6 +71,7 @@
#include "third_party/blink/renderer/core/exported/web_view_impl.h"
#include "third_party/blink/renderer/core/fileapi/public_url_manager.h"
#include "third_party/blink/renderer/core/frame/frame.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
#include "third_party/blink/renderer/core/frame/settings.h"
#include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
@@ -90,6 +91,7 @@
#include "third_party/blink/renderer/core/origin_trials/origin_trial_context.h"
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/core/page/plugin_data.h"
+#include "third_party/blink/renderer/core/probe/core_probes.h"
#include "third_party/blink/renderer/platform/exported/wrapped_resource_request.h"
#include "third_party/blink/renderer/platform/exported/wrapped_resource_response.h"
#include "third_party/blink/renderer/platform/instrumentation/histogram.h"
@@ -198,8 +200,6 @@ WebString ConvertToPublic(
return "frame-src";
case CSPDirectiveName::FormAction:
return "form-action";
- case CSPDirectiveName::UpgradeInsecureRequests:
- return "upgrade-insecure-requests";
case CSPDirectiveName::NavigateTo:
return "navigate-to";
case CSPDirectiveName::FrameAncestors:
@@ -222,9 +222,13 @@ WebContentSecurityPolicy ConvertToPublic(
ConvertToPublic(std::move(directive.value))};
}
- return {policy->header->type, policy->header->source,
- std::move(directives), std::move(policy->report_endpoints),
- policy->header->header_value, policy->use_reporting_api};
+ return {policy->header->type,
+ policy->header->source,
+ std::move(directives),
+ policy->upgrade_insecure_requests,
+ std::move(policy->report_endpoints),
+ policy->header->header_value,
+ policy->use_reporting_api};
}
} // namespace
@@ -253,10 +257,10 @@ void LocalFrameClientImpl::DidCreateInitialEmptyDocument() {
web_frame_->Client()->DidCreateInitialEmptyDocument();
}
-void LocalFrameClientImpl::DidCommitJavascriptUrlNavigation(
+void LocalFrameClientImpl::DidCommitDocumentReplacementNavigation(
DocumentLoader* loader) {
if (web_frame_->Client()) {
- web_frame_->Client()->DidCommitJavascriptUrlNavigation(
+ web_frame_->Client()->DidCommitDocumentReplacementNavigation(
WebDocumentLoaderImpl::FromDocumentLoader(loader));
}
}
@@ -510,8 +514,6 @@ void LocalFrameClientImpl::DispatchDidCommitLoad(
}
if (WebDevToolsAgentImpl* dev_tools = DevToolsAgent())
dev_tools->DidCommitLoadForLocalFrame(web_frame_->GetFrame());
-
- CoreInitializer::GetInstance().DidCommitLoad(*web_frame_->GetFrame());
}
void LocalFrameClientImpl::DispatchDidFailLoad(
@@ -531,7 +533,6 @@ void LocalFrameClientImpl::BeginNavigation(
DocumentLoader* document_loader,
WebNavigationType type,
NavigationPolicy policy,
- bool has_transient_activation,
WebFrameLoadType frame_load_type,
bool is_client_redirect,
TriggeringEventInfo triggering_event_info,
@@ -541,6 +542,7 @@ void LocalFrameClientImpl::BeginNavigation(
mojo::PendingRemote<mojom::blink::BlobURLToken> blob_url_token,
base::TimeTicks input_start_time,
const String& href_translate,
+ const base::Optional<WebImpression>& impression,
WTF::Vector<network::mojom::blink::ContentSecurityPolicyPtr> initiator_csp,
network::mojom::blink::CSPSourcePtr initiator_self_source,
network::mojom::IPAddressSpace initiator_address_space,
@@ -554,7 +556,7 @@ void LocalFrameClientImpl::BeginNavigation(
navigation_info->frame_type = frame_type;
navigation_info->navigation_type = type;
navigation_info->navigation_policy = static_cast<WebNavigationPolicy>(policy);
- navigation_info->has_transient_user_activation = has_transient_activation;
+ navigation_info->has_transient_user_activation = request.HasUserGesture();
navigation_info->frame_load_type = frame_load_type;
navigation_info->is_client_redirect = is_client_redirect;
navigation_info->triggering_event_info = triggering_event_info;
@@ -562,6 +564,12 @@ void LocalFrameClientImpl::BeginNavigation(
should_check_main_world_content_security_policy;
navigation_info->blob_url_token = blob_url_token.PassPipe();
navigation_info->input_start = input_start_time;
+ if (origin_document && origin_document->GetFrame()) {
+ navigation_info->initiator_frame =
+ origin_document->GetFrame()->Client()->GetWebFrame();
+ } else {
+ navigation_info->initiator_frame = nullptr;
+ }
for (auto& policy : initiator_csp) {
navigation_info->initiator_csp.emplace_back(
ConvertToPublic(std::move(policy)));
@@ -574,6 +582,8 @@ void LocalFrameClientImpl::BeginNavigation(
navigation_info->navigation_initiator_remote =
std::move(navigation_initiator);
+ navigation_info->impression = impression;
+
// Can be null.
LocalFrame* local_parent_frame = GetLocalParentFrame(web_frame_);
@@ -604,7 +614,7 @@ void LocalFrameClientImpl::BeginNavigation(
navigation_info->initiator_frame_has_download_sandbox_flag =
frame->GetSecurityContext() &&
frame->GetSecurityContext()->IsSandboxed(
- mojom::blink::WebSandboxFlags::kDownloads);
+ network::mojom::blink::WebSandboxFlags::kDownloads);
navigation_info->initiator_frame_is_ad = frame->IsAdSubframe();
}
@@ -620,9 +630,8 @@ void LocalFrameClientImpl::BeginNavigation(
// stack is not available here.
std::unique_ptr<SourceLocation> source_location =
origin_document
- ? SourceLocation::Capture(origin_document->ToExecutionContext())
- : SourceLocation::Capture(
- web_frame_->GetFrame()->GetDocument()->ToExecutionContext());
+ ? SourceLocation::Capture(origin_document->GetExecutionContext())
+ : SourceLocation::Capture(web_frame_->GetFrame()->DomWindow());
if (source_location && !source_location->IsUnknown()) {
navigation_info->source_location.url = source_location->Url();
navigation_info->source_location.line_number =
@@ -633,7 +642,7 @@ void LocalFrameClientImpl::BeginNavigation(
std::unique_ptr<Vector<OriginTrialFeature>> initiator_origin_trial_features =
OriginTrialContext::GetEnabledNavigationFeatures(
- web_frame_->GetFrame()->GetDocument()->ToExecutionContext());
+ web_frame_->GetFrame()->DomWindow());
if (initiator_origin_trial_features) {
navigation_info->initiator_origin_trial_features.reserve(
initiator_origin_trial_features->size());
@@ -762,6 +771,16 @@ void LocalFrameClientImpl::DidObserveLayoutShift(double score,
client->DidObserveLayoutShift(score, after_input_or_scroll);
}
+void LocalFrameClientImpl::DidObserveLayoutNg(uint32_t all_block_count,
+ uint32_t ng_block_count,
+ uint32_t all_call_count,
+ uint32_t ng_call_count) {
+ if (WebLocalFrameClient* client = web_frame_->Client()) {
+ client->DidObserveLayoutNg(all_block_count, ng_block_count, all_call_count,
+ ng_call_count);
+ }
+}
+
void LocalFrameClientImpl::DidObserveLazyLoadBehavior(
WebLocalFrameClient::LazyLoadBehavior lazy_load_behavior) {
if (WebLocalFrameClient* client = web_frame_->Client())
@@ -821,12 +840,15 @@ String LocalFrameClientImpl::UserAgent() {
base::Optional<UserAgentMetadata> LocalFrameClientImpl::UserAgentMetadata() {
bool ua_override_on = web_frame_->Client() &&
!web_frame_->Client()->UserAgentOverride().IsEmpty();
- if (ua_override_on)
- return web_frame_->Client()->UserAgentMetadataOverride();
+ base::Optional<blink::UserAgentMetadata> user_agent_metadata =
+ ua_override_on ? web_frame_->Client()->UserAgentMetadataOverride()
+ : Platform::Current()->UserAgentMetadata();
- if (user_agent_metadata_.brand.empty())
- user_agent_metadata_ = Platform::Current()->UserAgentMetadata();
- return user_agent_metadata_;
+ Document* document = web_frame_->GetDocument();
+ probe::ApplyUserAgentMetadataOverride(probe::ToCoreProbeSink(document),
+ &user_agent_metadata);
+
+ return user_agent_metadata;
}
String LocalFrameClientImpl::DoNotTrackValue() {
@@ -931,31 +953,16 @@ void LocalFrameClientImpl::DidChangeFramePolicy(
}
void LocalFrameClientImpl::DidSetFramePolicyHeaders(
- mojom::blink::WebSandboxFlags sandbox_flags,
+ network::mojom::blink::WebSandboxFlags sandbox_flags,
const ParsedFeaturePolicy& feature_policy_header,
const DocumentPolicy::FeatureState& document_policy_header) {
if (web_frame_->Client()) {
web_frame_->Client()->DidSetFramePolicyHeaders(
- static_cast<mojom::blink::WebSandboxFlags>(sandbox_flags),
+ static_cast<network::mojom::blink::WebSandboxFlags>(sandbox_flags),
feature_policy_header, document_policy_header);
}
}
-void LocalFrameClientImpl::DidChangeFrameOwnerProperties(
- HTMLFrameOwnerElement* frame_element) {
- if (!web_frame_->Client())
- return;
-
- web_frame_->Client()->DidChangeFrameOwnerProperties(
- WebFrame::FromFrame(frame_element->ContentFrame()),
- WebFrameOwnerProperties(
- frame_element->BrowsingContextContainerName(),
- frame_element->ScrollbarMode(), frame_element->MarginWidth(),
- frame_element->MarginHeight(), frame_element->AllowFullscreen(),
- frame_element->AllowPaymentRequest(), frame_element->IsDisplayNone(),
- frame_element->RequiredCsp()));
-}
-
std::unique_ptr<WebServiceWorkerProvider>
LocalFrameClientImpl::CreateServiceWorkerProvider() {
if (!web_frame_->Client())
diff --git a/chromium/third_party/blink/renderer/core/exported/local_frame_client_impl.h b/chromium/third_party/blink/renderer/core/exported/local_frame_client_impl.h
index 74f08e06333..cac29c6af0f 100644
--- a/chromium/third_party/blink/renderer/core/exported/local_frame_client_impl.h
+++ b/chromium/third_party/blink/renderer/core/exported/local_frame_client_impl.h
@@ -66,7 +66,7 @@ class LocalFrameClientImpl final : public LocalFrameClient {
// LocalFrameClient ----------------------------------------------
WebContentCaptureClient* GetWebContentCaptureClient() const override;
void DidCreateInitialEmptyDocument() override;
- void DidCommitJavascriptUrlNavigation(DocumentLoader*) override;
+ void DidCommitDocumentReplacementNavigation(DocumentLoader*) override;
// Notifies the WebView delegate that the JS window object has been cleared,
// giving it a chance to bind native objects to the window before script
// parsing begins.
@@ -116,7 +116,6 @@ class LocalFrameClientImpl final : public LocalFrameClient {
DocumentLoader*,
WebNavigationType,
NavigationPolicy,
- bool has_transient_activation,
WebFrameLoadType,
bool is_client_redirect,
TriggeringEventInfo,
@@ -125,6 +124,7 @@ class LocalFrameClientImpl final : public LocalFrameClient {
mojo::PendingRemote<mojom::blink::BlobURLToken>,
base::TimeTicks input_start_time,
const String& href_translate,
+ const base::Optional<WebImpression>& impression,
WTF::Vector<network::mojom::blink::ContentSecurityPolicyPtr>
initiator_csp,
network::mojom::blink::CSPSourcePtr initiator_self_source,
@@ -146,6 +146,10 @@ class LocalFrameClientImpl final : public LocalFrameClient {
void DidObserveNewFeatureUsage(mojom::WebFeature) override;
void DidObserveNewCssPropertyUsage(mojom::CSSSampleId, bool) override;
void DidObserveLayoutShift(double score, bool after_input_or_scroll) override;
+ void DidObserveLayoutNg(uint32_t all_block_count,
+ uint32_t ng_block_count,
+ uint32_t all_call_count,
+ uint32_t ng_call_count) override;
void DidObserveLazyLoadBehavior(
WebLocalFrameClient::LazyLoadBehavior lazy_load_behavior) override;
bool ShouldTrackUseCounter(const KURL&) override;
@@ -199,10 +203,9 @@ class LocalFrameClientImpl final : public LocalFrameClient {
void DidChangeName(const String&) override;
void DidChangeFramePolicy(Frame* child_frame, const FramePolicy&) override;
void DidSetFramePolicyHeaders(
- mojom::blink::WebSandboxFlags,
+ network::mojom::blink::WebSandboxFlags,
const ParsedFeaturePolicy& fp_header,
const blink::DocumentPolicy::FeatureState& dp_header) override;
- void DidChangeFrameOwnerProperties(HTMLFrameOwnerElement*) override;
std::unique_ptr<WebServiceWorkerProvider> CreateServiceWorkerProvider()
override;
@@ -284,7 +287,6 @@ class LocalFrameClientImpl final : public LocalFrameClient {
Member<WebLocalFrameImpl> web_frame_;
String user_agent_;
- blink::UserAgentMetadata user_agent_metadata_;
};
template <>
diff --git a/chromium/third_party/blink/renderer/core/exported/web_console_message.cc b/chromium/third_party/blink/renderer/core/exported/web_console_message.cc
index 050b19c235f..0cdd05b6b51 100644
--- a/chromium/third_party/blink/renderer/core/exported/web_console_message.cc
+++ b/chromium/third_party/blink/renderer/core/exported/web_console_message.cc
@@ -5,8 +5,8 @@
#include "third_party/blink/public/web/web_console_message.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
-#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/inspector/console_message.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
#include "third_party/blink/renderer/platform/wtf/casting.h"
@@ -20,8 +20,8 @@ void WebConsoleMessage::LogWebConsoleMessage(v8::Local<v8::Context> context,
return;
LocalFrame* frame = nullptr;
- if (auto* document = Document::DynamicFrom(execution_context))
- frame = document->GetFrame();
+ if (auto* window = DynamicTo<LocalDOMWindow>(execution_context))
+ frame = window->GetFrame();
execution_context->AddConsoleMessage(
MakeGarbageCollected<ConsoleMessage>(message, frame));
}
diff --git a/chromium/third_party/blink/renderer/core/exported/web_dev_tools_agent_impl.cc b/chromium/third_party/blink/renderer/core/exported/web_dev_tools_agent_impl.cc
index 68112cb646e..8681f8fc39a 100644
--- a/chromium/third_party/blink/renderer/core/exported/web_dev_tools_agent_impl.cc
+++ b/chromium/third_party/blink/renderer/core/exported/web_dev_tools_agent_impl.cc
@@ -385,7 +385,7 @@ void WebDevToolsAgentImpl::InspectElement(
HitTestRequest::kMove | HitTestRequest::kReadOnly |
HitTestRequest::kAllowChildFrameContent;
HitTestRequest request(hit_type);
- WebMouseEvent dummy_event(WebInputEvent::kMouseDown,
+ WebMouseEvent dummy_event(WebInputEvent::Type::kMouseDown,
WebInputEvent::kNoModifiers,
base::TimeTicks::Now());
dummy_event.SetPositionInWidget(point);
diff --git a/chromium/third_party/blink/renderer/core/exported/web_document.cc b/chromium/third_party/blink/renderer/core/exported/web_document.cc
index eeff125b12b..fa67cdafef0 100644
--- a/chromium/third_party/blink/renderer/core/exported/web_document.cc
+++ b/chromium/third_party/blink/renderer/core/exported/web_document.cc
@@ -176,19 +176,18 @@ WebElementCollection WebDocument::All() {
return WebElementCollection(Unwrap<Document>()->all());
}
-void WebDocument::Forms(WebVector<WebFormElement>& results) const {
+WebVector<WebFormElement> WebDocument::Forms() const {
HTMLCollection* forms =
const_cast<Document*>(ConstUnwrap<Document>())->forms();
- size_t source_length = forms->length();
- Vector<WebFormElement> temp;
- temp.ReserveCapacity(source_length);
- for (size_t i = 0; i < source_length; ++i) {
- Element* element = forms->item(i);
+
+ Vector<WebFormElement> form_elements;
+ form_elements.ReserveCapacity(forms->length());
+ for (Element* element : *forms) {
// Strange but true, sometimes node can be 0.
if (auto* html_form_element = DynamicTo<HTMLFormElement>(element))
- temp.push_back(WebFormElement(html_form_element));
+ form_elements.emplace_back(html_form_element);
}
- results.Assign(temp);
+ return form_elements;
}
WebURL WebDocument::CompleteURL(const WebString& partial_url) const {
diff --git a/chromium/third_party/blink/renderer/core/exported/web_document_loader_impl.cc b/chromium/third_party/blink/renderer/core/exported/web_document_loader_impl.cc
index ac9c8e538ab..5f0864cc2c8 100644
--- a/chromium/third_party/blink/renderer/core/exported/web_document_loader_impl.cc
+++ b/chromium/third_party/blink/renderer/core/exported/web_document_loader_impl.cc
@@ -42,7 +42,7 @@
#include "third_party/blink/public/platform/web_url.h"
#include "third_party/blink/public/platform/web_url_error.h"
#include "third_party/blink/public/platform/web_vector.h"
-#include "third_party/blink/renderer/core/dom/document.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/loader/subresource_filter.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
@@ -143,16 +143,14 @@ void WebDocumentLoaderImpl::DetachFromFrame(bool flush_microtask_queue) {
void WebDocumentLoaderImpl::SetSubresourceFilter(
WebDocumentSubresourceFilter* subresource_filter) {
DocumentLoader::SetSubresourceFilter(MakeGarbageCollected<SubresourceFilter>(
- GetFrame()->GetDocument()->ToExecutionContext(),
- base::WrapUnique(subresource_filter)));
+ GetFrame()->DomWindow(), base::WrapUnique(subresource_filter)));
}
void WebDocumentLoaderImpl::SetLoadingHintsProvider(
std::unique_ptr<blink::WebLoadingHintsProvider> loading_hints_provider) {
DocumentLoader::SetPreviewsResourceLoadingHints(
PreviewsResourceLoadingHints::CreateFromLoadingHintsProvider(
- *GetFrame()->GetDocument()->ToExecutionContext(),
- std::move(loading_hints_provider)));
+ *GetFrame()->DomWindow(), std::move(loading_hints_provider)));
}
void WebDocumentLoaderImpl::SetServiceWorkerNetworkProvider(
diff --git a/chromium/third_party/blink/renderer/core/exported/web_document_test.cc b/chromium/third_party/blink/renderer/core/exported/web_document_test.cc
index 1ec21b5b683..4fe241470b3 100644
--- a/chromium/third_party/blink/renderer/core/exported/web_document_test.cc
+++ b/chromium/third_party/blink/renderer/core/exported/web_document_test.cc
@@ -367,6 +367,15 @@ TEST_F(WebDocumentFirstPartyTest, NestedOriginA) {
OriginsEqual(g_nested_origin_a, NestedDocument()->TopFrameOrigin()));
}
+TEST_F(WebDocumentFirstPartyTest, NestedOriginASchemefulSiteForCookies) {
+ Load(g_nested_origin_a);
+
+ // TopDocument is same scheme with itself so expect true.
+ ASSERT_TRUE(TopDocument()->SiteForCookies().schemefully_same());
+ // NestedDocument is same scheme with TopDocument so expect true.
+ ASSERT_TRUE(NestedDocument()->SiteForCookies().schemefully_same());
+}
+
TEST_F(WebDocumentFirstPartyTest, NestedOriginSubA) {
Load(g_nested_origin_sub_a);
@@ -395,6 +404,17 @@ TEST_F(WebDocumentFirstPartyTest, NestedOriginSecureA) {
NestedDocument()->TopFrameOrigin()));
}
+TEST_F(WebDocumentFirstPartyTest, NestedOriginSecureASchemefulSiteForCookies) {
+ Load(g_nested_origin_secure_a);
+
+ // TopDocument is same scheme with itself so expect true.
+ ASSERT_TRUE(TopDocument()->SiteForCookies().schemefully_same());
+
+ // Since NestedDocument is secure, and the parent is insecure, the scheme will
+ // differ.
+ ASSERT_FALSE(NestedDocument()->SiteForCookies().schemefully_same());
+}
+
TEST_F(WebDocumentFirstPartyTest, NestedOriginAInOriginA) {
Load(g_nested_origin_a_in_origin_a);
diff --git a/chromium/third_party/blink/renderer/core/exported/web_dom_message_event.cc b/chromium/third_party/blink/renderer/core/exported/web_dom_message_event.cc
index 2a867cd9bb1..7b2058b124a 100644
--- a/chromium/third_party/blink/renderer/core/exported/web_dom_message_event.cc
+++ b/chromium/third_party/blink/renderer/core/exported/web_dom_message_event.cc
@@ -57,7 +57,7 @@ WebDOMMessageEvent::WebDOMMessageEvent(
MessagePortArray* ports = nullptr;
if (!target_document.IsNull()) {
Document* core_document = target_document;
- ports = MessagePort::EntanglePorts(*core_document->ToExecutionContext(),
+ ports = MessagePort::EntanglePorts(*core_document->GetExecutionContext(),
std::move(channels));
}
// TODO(esprehn): Chromium always passes empty string for lastEventId, is that
@@ -80,7 +80,7 @@ WebDOMMessageEvent::WebDOMMessageEvent(TransferableMessage message,
MessagePortArray* ports = nullptr;
if (!target_document.IsNull()) {
Document* core_document = target_document;
- ports = MessagePort::EntanglePorts(*core_document->ToExecutionContext(),
+ ports = MessagePort::EntanglePorts(*core_document->GetExecutionContext(),
std::move(msg.ports));
}
diff --git a/chromium/third_party/blink/renderer/core/exported/web_element.cc b/chromium/third_party/blink/renderer/core/exported/web_element.cc
index ae143342c1e..1c0ed71bd73 100644
--- a/chromium/third_party/blink/renderer/core/exported/web_element.cc
+++ b/chromium/third_party/blink/renderer/core/exported/web_element.cc
@@ -31,6 +31,8 @@
#include "third_party/blink/public/web/web_element.h"
#include "third_party/blink/public/platform/web_rect.h"
+#include "third_party/blink/renderer/core/css/css_computed_style_declaration.h"
+#include "third_party/blink/renderer/core/css/css_property_names.h"
#include "third_party/blink/renderer/core/dom/element.h"
#include "third_party/blink/renderer/core/editing/editing_utilities.h"
#include "third_party/blink/renderer/core/fullscreen/fullscreen.h"
@@ -182,6 +184,22 @@ void WebElement::RequestFullscreen() {
Fullscreen::RequestFullscreen(*element);
}
+WebString WebElement::GetComputedValue(const WebString& property_name) {
+ if (IsNull())
+ return WebString();
+
+ Element* element = Unwrap<Element>();
+ CSSPropertyID property_id = cssPropertyID(
+ element->GetDocument().GetExecutionContext(), property_name);
+ if (property_id == CSSPropertyID::kInvalid)
+ return WebString();
+
+ element->GetDocument().UpdateStyleAndLayoutTree();
+ auto* computed_style =
+ MakeGarbageCollected<CSSComputedStyleDeclaration>(element);
+ return computed_style->GetPropertyCSSValue(property_id)->CssText();
+}
+
WebElement::WebElement(Element* elem) : WebNode(elem) {}
DEFINE_WEB_NODE_TYPE_CASTS(WebElement, IsElementNode())
diff --git a/chromium/third_party/blink/renderer/core/exported/web_element_test.cc b/chromium/third_party/blink/renderer/core/exported/web_element_test.cc
index afb7af9a7a5..febcef17306 100644
--- a/chromium/third_party/blink/renderer/core/exported/web_element_test.cc
+++ b/chromium/third_party/blink/renderer/core/exported/web_element_test.cc
@@ -83,21 +83,9 @@ TEST_F(WebElementTest, IsAutonomousCustomElement) {
{ extends:'button' });
document.body.appendChild(
document.createElement('button', { is: 'v1-builtin' }));
-
- document.registerElement('v0-custom');
- document.body.appendChild(document.createElement('v0-custom'));
- document.registerElement('v0-typext', {
- prototype: Object.create(HTMLInputElement.prototype),
- extends: 'input' });
- document.body.appendChild(document.createElement('input', 'v0-typeext'));
)JS");
GetDocument().body()->appendChild(script);
- auto* v0typeext = GetDocument().body()->lastChild();
- EXPECT_FALSE(WebElement(To<Element>(v0typeext)).IsAutonomousCustomElement());
- auto* v0autonomous = v0typeext->previousSibling();
- EXPECT_TRUE(
- WebElement(To<Element>(v0autonomous)).IsAutonomousCustomElement());
- auto* v1builtin = v0autonomous->previousSibling();
+ auto* v1builtin = GetDocument().body()->lastChild();
EXPECT_FALSE(WebElement(To<Element>(v1builtin)).IsAutonomousCustomElement());
auto* v1autonomous = v1builtin->previousSibling();
EXPECT_TRUE(
@@ -140,4 +128,46 @@ TEST_F(WebElementTest, ShadowRoot) {
}
}
+TEST_F(WebElementTest, ComputedStyleProperties) {
+ InsertHTML(R"HTML(
+ <body>
+ <div id=testElement></div>
+ </body>
+ )HTML");
+
+ WebElement element = TestElement();
+ element.GetDocument().InsertStyleSheet(
+ "body { font-size: 16px; text-decoration: underline; color: blue;}");
+ // font-size
+ {
+ EXPECT_EQ(element.GetComputedValue("font-size"), "16px");
+ element.SetAttribute("style", "font-size: 3em");
+ EXPECT_EQ(element.GetComputedValue("font-size"), "48px");
+ }
+
+ // text-decoration
+ {
+ EXPECT_EQ(element.GetComputedValue("text-decoration"),
+ "none solid rgb(0, 0, 255)");
+ element.SetAttribute("style", "text-decoration: line-through");
+ EXPECT_EQ(element.GetComputedValue("text-decoration-line"), "line-through");
+ EXPECT_EQ(element.GetComputedValue("-Webkit-text-decorations-in-effect"),
+ "underline line-through");
+ }
+
+ // font-weight
+ {
+ EXPECT_EQ(element.GetComputedValue("font-weight"), "400");
+ element.SetAttribute("style", "font-weight: bold");
+ EXPECT_EQ(element.GetComputedValue("font-weight"), "700");
+ }
+
+ // color
+ {
+ EXPECT_EQ(element.GetComputedValue("color"), "rgb(0, 0, 255)");
+ element.SetAttribute("style", "color: red");
+ EXPECT_EQ(element.GetComputedValue("color"), "rgb(255, 0, 0)");
+ }
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/exported/web_external_widget_impl.cc b/chromium/third_party/blink/renderer/core/exported/web_external_widget_impl.cc
index c755f171654..7ba828c0f6f 100644
--- a/chromium/third_party/blink/renderer/core/exported/web_external_widget_impl.cc
+++ b/chromium/third_party/blink/renderer/core/exported/web_external_widget_impl.cc
@@ -5,6 +5,8 @@
#include "third_party/blink/renderer/core/exported/web_external_widget_impl.h"
#include "cc/trees/layer_tree_host.h"
+#include "cc/trees/ukm_manager.h"
+#include "third_party/blink/public/platform/scheduler/web_render_widget_scheduling_state.h"
#include "third_party/blink/renderer/platform/widget/widget_base.h"
namespace blink {
@@ -37,25 +39,27 @@ WebExternalWidgetImpl::WebExternalWidgetImpl(
WebExternalWidgetImpl::~WebExternalWidgetImpl() = default;
-void WebExternalWidgetImpl::SetCompositorHosts(
- cc::LayerTreeHost* layer_tree_host,
- cc::AnimationHost* animation_host) {
- widget_base_->SetCompositorHosts(layer_tree_host, animation_host);
+cc::LayerTreeHost* WebExternalWidgetImpl::InitializeCompositing(
+ cc::TaskGraphRunner* task_graph_runner,
+ const cc::LayerTreeSettings& settings,
+ std::unique_ptr<cc::UkmRecorderFactory> ukm_recorder_factory) {
+ widget_base_->InitializeCompositing(task_graph_runner, settings,
+ std::move(ukm_recorder_factory));
+ return widget_base_->LayerTreeHost();
}
-void WebExternalWidgetImpl::SetCompositorVisible(bool visible) {
- widget_base_->SetCompositorVisible(visible);
-}
-
-void WebExternalWidgetImpl::UpdateVisualState() {
- widget_base_->UpdateVisualState();
+void WebExternalWidgetImpl::Close(
+ scoped_refptr<base::SingleThreadTaskRunner> cleanup_runner,
+ base::OnceCallback<void()> cleanup_task) {
+ widget_base_->Shutdown(std::move(cleanup_runner), std::move(cleanup_task));
+ widget_base_.reset();
}
-void WebExternalWidgetImpl::WillBeginCompositorFrame() {
- widget_base_->WillBeginCompositorFrame();
+void WebExternalWidgetImpl::SetCompositorVisible(bool visible) {
+ widget_base_->SetCompositorVisible(visible);
}
-WebHitTestResult WebExternalWidgetImpl::HitTestResultAt(const gfx::Point&) {
+WebHitTestResult WebExternalWidgetImpl::HitTestResultAt(const gfx::PointF&) {
NOTIMPLEMENTED();
return {};
}
@@ -84,13 +88,31 @@ WebInputEventResult WebExternalWidgetImpl::DispatchBufferedTouchEvents() {
return client_->DispatchBufferedTouchEvents();
}
+scheduler::WebRenderWidgetSchedulingState*
+WebExternalWidgetImpl::RendererWidgetSchedulingState() {
+ return widget_base_->RendererWidgetSchedulingState();
+}
+
+void WebExternalWidgetImpl::SetCursor(const ui::Cursor& cursor) {
+ widget_base_->SetCursor(cursor);
+}
+
void WebExternalWidgetImpl::SetRootLayer(scoped_refptr<cc::Layer> layer) {
widget_base_->LayerTreeHost()->SetNonBlinkManagedRootLayer(layer);
}
+void WebExternalWidgetImpl::RequestNewLayerTreeFrameSink(
+ LayerTreeFrameSinkCallback callback) {
+ client_->RequestNewLayerTreeFrameSink(std::move(callback));
+}
+
void WebExternalWidgetImpl::RecordTimeToFirstActivePaint(
base::TimeDelta duration) {
client_->RecordTimeToFirstActivePaint(duration);
}
+void WebExternalWidgetImpl::DidCommitAndDrawCompositorFrame() {
+ client_->DidCommitAndDrawCompositorFrame();
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/exported/web_external_widget_impl.h b/chromium/third_party/blink/renderer/core/exported/web_external_widget_impl.h
index 7f014b64c9c..7b6ce058a13 100644
--- a/chromium/third_party/blink/renderer/core/exported/web_external_widget_impl.h
+++ b/chromium/third_party/blink/renderer/core/exported/web_external_widget_impl.h
@@ -28,17 +28,23 @@ class WebExternalWidgetImpl : public WebExternalWidget,
~WebExternalWidgetImpl() override;
// WebWidget overrides:
- void SetCompositorHosts(cc::LayerTreeHost*, cc::AnimationHost*) override;
+ cc::LayerTreeHost* InitializeCompositing(
+ cc::TaskGraphRunner* task_graph_runner,
+ const cc::LayerTreeSettings& settings,
+ std::unique_ptr<cc::UkmRecorderFactory> ukm_recorder_factory) override;
void SetCompositorVisible(bool visible) override;
- void UpdateVisualState() override;
- void WillBeginCompositorFrame() override;
- WebHitTestResult HitTestResultAt(const gfx::Point&) override;
+ void Close(scoped_refptr<base::SingleThreadTaskRunner> cleanup_runner,
+ base::OnceCallback<void()> cleanup_task) override;
+ WebHitTestResult HitTestResultAt(const gfx::PointF&) override;
WebURL GetURLForDebugTrace() override;
WebSize Size() override;
void Resize(const WebSize& size) override;
WebInputEventResult HandleInputEvent(
const WebCoalescedInputEvent& coalesced_event) override;
WebInputEventResult DispatchBufferedTouchEvents() override;
+ scheduler::WebRenderWidgetSchedulingState* RendererWidgetSchedulingState()
+ override;
+ void SetCursor(const ui::Cursor& cursor) override;
// WebExternalWidget overrides:
void SetRootLayer(scoped_refptr<cc::Layer>) override;
@@ -49,6 +55,9 @@ class WebExternalWidgetImpl : public WebExternalWidget,
void RecordTimeToFirstActivePaint(base::TimeDelta duration) override;
void UpdateLifecycle(WebLifecycleUpdate requested_update,
DocumentUpdateReason reason) override {}
+ void RequestNewLayerTreeFrameSink(
+ LayerTreeFrameSinkCallback callback) override;
+ void DidCommitAndDrawCompositorFrame() override;
private:
WebExternalWidgetClient* const client_;
diff --git a/chromium/third_party/blink/renderer/core/exported/web_form_control_element.cc b/chromium/third_party/blink/renderer/core/exported/web_form_control_element.cc
index 9db79042d88..03ebe0db377 100644
--- a/chromium/third_party/blink/renderer/core/exported/web_form_control_element.cc
+++ b/chromium/third_party/blink/renderer/core/exported/web_form_control_element.cc
@@ -85,6 +85,13 @@ bool WebFormControlElement::UserHasEditedTheField() const {
return true;
}
+void WebFormControlElement::SetUserHasEditedTheField(bool value) {
+ if (auto* input = DynamicTo<HTMLInputElement>(*private_))
+ input->SetUserHasEditedTheField(value);
+ if (auto* select_element = DynamicTo<HTMLSelectElement>(*private_))
+ select_element->SetUserHasEditedTheField(value);
+}
+
void WebFormControlElement::SetUserHasEditedTheFieldForTest() {
if (auto* input = DynamicTo<HTMLInputElement>(*private_))
input->SetUserHasEditedTheFieldForTest();
diff --git a/chromium/third_party/blink/renderer/core/exported/web_form_element.cc b/chromium/third_party/blink/renderer/core/exported/web_form_element.cc
index cb8ebcc1717..39408830520 100644
--- a/chromium/third_party/blink/renderer/core/exported/web_form_element.cc
+++ b/chromium/third_party/blink/renderer/core/exported/web_form_element.cc
@@ -62,8 +62,8 @@ unsigned WebFormElement::UniqueRendererFormId() const {
return ConstUnwrap<HTMLFormElement>()->UniqueRendererFormId();
}
-void WebFormElement::GetFormControlElements(
- WebVector<WebFormControlElement>& result) const {
+WebVector<WebFormControlElement> WebFormElement::GetFormControlElements()
+ const {
const HTMLFormElement* form = ConstUnwrap<HTMLFormElement>();
Vector<WebFormControlElement> form_control_elements;
for (const auto& element : form->ListedElements()) {
@@ -73,7 +73,7 @@ void WebFormElement::GetFormControlElements(
}
}
- result.Assign(form_control_elements);
+ return form_control_elements;
}
WebFormElement::WebFormElement(HTMLFormElement* e) : WebElement(e) {}
diff --git a/chromium/third_party/blink/renderer/core/exported/web_form_element_observer_impl.cc b/chromium/third_party/blink/renderer/core/exported/web_form_element_observer_impl.cc
index a4065dbc2eb..af156496334 100644
--- a/chromium/third_party/blink/renderer/core/exported/web_form_element_observer_impl.cc
+++ b/chromium/third_party/blink/renderer/core/exported/web_form_element_observer_impl.cc
@@ -62,7 +62,7 @@ WebFormElementObserverImpl::ObserverCallback::ObserverCallback(
ExecutionContext*
WebFormElementObserverImpl::ObserverCallback::GetExecutionContext() const {
- return element_ ? element_->GetDocument().ToExecutionContext() : nullptr;
+ return element_ ? element_->GetExecutionContext() : nullptr;
}
void WebFormElementObserverImpl::ObserverCallback::Deliver(
diff --git a/chromium/third_party/blink/renderer/core/exported/web_frame.cc b/chromium/third_party/blink/renderer/core/exported/web_frame.cc
index 91353f0821a..fa45c32b6d4 100644
--- a/chromium/third_party/blink/renderer/core/exported/web_frame.cc
+++ b/chromium/third_party/blink/renderer/core/exported/web_frame.cc
@@ -5,7 +5,7 @@
#include "third_party/blink/public/web/web_frame.h"
#include <algorithm>
-#include "third_party/blink/public/common/frame/sandbox_flags.h"
+#include "third_party/blink/public/mojom/frame/tree_scope_type.mojom-blink.h"
#include "third_party/blink/public/mojom/scroll/scrollbar_mode.mojom-blink.h"
#include "third_party/blink/public/mojom/security_context/insecure_request_policy.mojom-blink.h"
#include "third_party/blink/public/web/web_element.h"
@@ -288,15 +288,19 @@ WebFrame* WebFrame::FromFrame(Frame* frame) {
return WebRemoteFrameImpl::FromFrame(To<RemoteFrame>(*frame));
}
-WebFrame::WebFrame(WebTreeScopeType scope)
+WebFrame::WebFrame(mojom::blink::TreeScopeType scope,
+ const base::UnguessableToken& frame_token)
: scope_(scope),
+ frame_token_(frame_token),
parent_(nullptr),
previous_sibling_(nullptr),
next_sibling_(nullptr),
first_child_(nullptr),
last_child_(nullptr),
opener_(nullptr),
- opened_frame_tracker_(new OpenedFrameTracker) {}
+ opened_frame_tracker_(new OpenedFrameTracker) {
+ DCHECK(frame_token_);
+}
WebFrame::~WebFrame() {
opened_frame_tracker_.reset(nullptr);
diff --git a/chromium/third_party/blink/renderer/core/exported/web_frame_content_dumper.cc b/chromium/third_party/blink/renderer/core/exported/web_frame_content_dumper.cc
index f71a66f0a10..892c7b3e213 100644
--- a/chromium/third_party/blink/renderer/core/exported/web_frame_content_dumper.cc
+++ b/chromium/third_party/blink/renderer/core/exported/web_frame_content_dumper.cc
@@ -12,8 +12,10 @@
#include "third_party/blink/renderer/core/editing/ephemeral_range.h"
#include "third_party/blink/renderer/core/editing/iterators/text_iterator.h"
#include "third_party/blink/renderer/core/editing/serializers/serialization.h"
+#include "third_party/blink/renderer/core/exported/web_view_impl.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
+#include "third_party/blink/renderer/core/frame/web_frame_widget_base.h"
#include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
#include "third_party/blink/renderer/core/html_element_type_helpers.h"
#include "third_party/blink/renderer/core/layout/layout_embedded_content.h"
@@ -102,8 +104,13 @@ WebString WebFrameContentDumper::DumpWebViewAsText(WebView* web_view,
if (!frame)
return WebString();
- DCHECK(web_view->MainFrameWidget());
- web_view->MainFrameWidget()->UpdateAllLifecyclePhases(
+ WebViewImpl* web_view_impl = static_cast<WebViewImpl*>(web_view);
+ DCHECK(web_view_impl->MainFrameWidgetBase());
+ // Updating the document lifecycle isn't enough, the BeginFrame() step
+ // should come first which runs events such as notifying of media query
+ // changes or raf-based events.
+ web_view_impl->MainFrameWidgetBase()->BeginMainFrame(base::TimeTicks::Now());
+ web_view_impl->MainFrameWidgetBase()->UpdateAllLifecyclePhases(
DocumentUpdateReason::kTest);
StringBuilder text;
diff --git a/chromium/third_party/blink/renderer/core/exported/web_frame_serializer_sanitization_test.cc b/chromium/third_party/blink/renderer/core/exported/web_frame_serializer_sanitization_test.cc
index 7417837c7a2..224132811f2 100644
--- a/chromium/third_party/blink/renderer/core/exported/web_frame_serializer_sanitization_test.cc
+++ b/chromium/third_party/blink/renderer/core/exported/web_frame_serializer_sanitization_test.cc
@@ -94,21 +94,23 @@ class WebFrameSerializerSanitizationTest : public testing::Test {
test::RunPendingTasks();
}
- ShadowRoot* SetShadowContent(TreeScope& scope,
- const char* host,
- ShadowRootType shadow_type,
- const char* shadow_content,
- bool delegates_focus = false) {
+ ShadowRoot* SetShadowContent(
+ TreeScope& scope,
+ const char* host,
+ ShadowRootType shadow_type,
+ const char* shadow_content,
+ FocusDelegation focus_delegation = FocusDelegation::kNone) {
Element* host_element = scope.getElementById(AtomicString::FromUTF8(host));
ShadowRoot* shadow_root;
if (shadow_type == ShadowRootType::V0) {
- DCHECK(!delegates_focus);
+ DCHECK_EQ(focus_delegation, FocusDelegation::kNone);
shadow_root = &host_element->CreateV0ShadowRootForTesting();
} else {
- shadow_root =
- &host_element->AttachShadowRootInternal(shadow_type, delegates_focus);
+ shadow_root = &host_element->AttachShadowRootInternal(shadow_type,
+ focus_delegation);
}
- shadow_root->SetDelegatesFocus(delegates_focus);
+ shadow_root->SetDelegatesFocus(focus_delegation ==
+ FocusDelegation::kDelegateFocus);
shadow_root->setInnerHTML(String::FromUTF8(shadow_content),
ASSERT_NO_EXCEPTION);
scope.GetDocument().View()->UpdateAllLifecyclePhases(
@@ -337,9 +339,9 @@ TEST_F(WebFrameSerializerSanitizationTest, ShadowDOM) {
LoadFrame("http://www.test.com", "shadow_dom.html", "text/html");
Document* document = MainFrameImpl()->GetFrame()->GetDocument();
SetShadowContent(*document, "h1", ShadowRootType::V0, "V0 shadow");
- ShadowRoot* shadowRoot =
- SetShadowContent(*document, "h2", ShadowRootType::kOpen,
- "Parent shadow\n<p id=\"h3\">Foo</p>", true);
+ ShadowRoot* shadowRoot = SetShadowContent(
+ *document, "h2", ShadowRootType::kOpen,
+ "Parent shadow\n<p id=\"h3\">Foo</p>", FocusDelegation::kDelegateFocus);
SetShadowContent(*shadowRoot, "h3", ShadowRootType::kClosed, "Nested shadow");
String mhtml = WebFrameSerializerTestHelper::GenerateMHTML(MainFrameImpl());
diff --git a/chromium/third_party/blink/renderer/core/exported/web_frame_test.cc b/chromium/third_party/blink/renderer/core/exported/web_frame_test.cc
index 2fdbd4b3e2a..195abffa156 100644
--- a/chromium/third_party/blink/renderer/core/exported/web_frame_test.cc
+++ b/chromium/third_party/blink/renderer/core/exported/web_frame_test.cc
@@ -35,7 +35,9 @@
#include <memory>
#include "base/bind_helpers.h"
+#include "base/optional.h"
#include "base/stl_util.h"
+#include "base/unguessable_token.h"
#include "build/build_config.h"
#include "cc/input/overscroll_behavior.h"
#include "cc/layers/picture_layer.h"
@@ -51,16 +53,17 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
#include "third_party/blink/public/common/context_menu_data/edit_flags.h"
-#include "third_party/blink/public/common/frame/frame_owner_element_type.h"
+#include "third_party/blink/public/common/input/web_coalesced_input_event.h"
#include "third_party/blink/public/common/input/web_keyboard_event.h"
+#include "third_party/blink/public/common/messaging/transferable_message.h"
#include "third_party/blink/public/common/page/launching_process_state.h"
#include "third_party/blink/public/mojom/blob/blob.mojom-blink.h"
#include "third_party/blink/public/mojom/blob/data_element.mojom-blink.h"
#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h"
#include "third_party/blink/public/mojom/frame/find_in_page.mojom-blink.h"
+#include "third_party/blink/public/mojom/frame/frame_owner_element_type.mojom-blink.h"
#include "third_party/blink/public/mojom/scroll/scrollbar_mode.mojom-blink.h"
#include "third_party/blink/public/platform/web_cache.h"
-#include "third_party/blink/public/platform/web_coalesced_input_event.h"
#include "third_party/blink/public/platform/web_float_rect.h"
#include "third_party/blink/public/platform/web_security_origin.h"
#include "third_party/blink/public/platform/web_url.h"
@@ -144,6 +147,7 @@
#include "third_party/blink/renderer/core/layout/layout_view.h"
#include "third_party/blink/renderer/core/loader/document_loader.h"
#include "third_party/blink/renderer/core/loader/frame_load_request.h"
+#include "third_party/blink/renderer/core/messaging/blink_transferable_message.h"
#include "third_party/blink/renderer/core/page/chrome_client.h"
#include "third_party/blink/renderer/core/page/drag_image.h"
#include "third_party/blink/renderer/core/page/page.h"
@@ -662,8 +666,8 @@ TEST_F(WebFrameTest, FormWithNullFrame) {
frame_test_helpers::WebViewHelper web_view_helper;
web_view_helper.InitializeAndLoad(base_url_ + "form.html");
- WebVector<WebFormElement> forms;
- web_view_helper.LocalMainFrame()->GetDocument().Forms(forms);
+ WebVector<WebFormElement> forms =
+ web_view_helper.LocalMainFrame()->GetDocument().Forms();
web_view_helper.Reset();
EXPECT_EQ(forms.size(), 1U);
@@ -1112,28 +1116,30 @@ TEST_F(WebFrameCSSCallbackTest, InvalidSelector) {
<< "An invalid selector shouldn't prevent other selectors from matching.";
}
-TEST_F(WebFrameTest, DispatchMessageEventWithOriginCheck) {
+TEST_F(WebFrameTest, PostMessageEvent) {
RegisterMockedHttpURLLoad("postmessage_test.html");
frame_test_helpers::WebViewHelper web_view_helper;
web_view_helper.InitializeAndLoad(base_url_ + "postmessage_test.html");
- // Send a message with the correct origin.
- WebSecurityOrigin correct_origin(
- WebSecurityOrigin::Create(ToKURL(base_url_)));
- WebDocument document = web_view_helper.LocalMainFrame()->GetDocument();
WebSerializedScriptValue data(WebSerializedScriptValue::CreateInvalid());
WebDOMMessageEvent message(data, "http://origin.com");
- web_view_helper.GetWebView()
- ->MainFrameImpl()
- ->DispatchMessageEventWithOriginCheck(correct_origin, message);
+ auto* frame =
+ To<LocalFrame>(web_view_helper.GetWebView()->GetPage()->MainFrame());
+
+ // Send a message with the correct origin.
+ scoped_refptr<SecurityOrigin> correct_origin =
+ SecurityOrigin::Create(ToKURL(base_url_));
+ frame->PostMessageEvent(base::nullopt, g_empty_string,
+ correct_origin->ToString(),
+ ToBlinkTransferableMessage(message.AsMessage()));
// Send another message with incorrect origin.
- WebSecurityOrigin incorrect_origin(
- WebSecurityOrigin::Create(ToKURL(chrome_url_)));
- web_view_helper.GetWebView()
- ->MainFrameImpl()
- ->DispatchMessageEventWithOriginCheck(incorrect_origin, message);
+ scoped_refptr<SecurityOrigin> incorrect_origin =
+ SecurityOrigin::Create(ToKURL(chrome_url_));
+ frame->PostMessageEvent(base::nullopt, g_empty_string,
+ incorrect_origin->ToString(),
+ ToBlinkTransferableMessage(message.AsMessage()));
// Verify that only the first addition is in the body of the page.
std::string content = WebFrameContentDumper::DumpWebViewAsText(
@@ -2069,7 +2075,7 @@ TEST_F(WebFrameTest,
ASSERT_NE(nullptr, element);
EXPECT_EQ(String("oldValue"), element->innerText());
- WebGestureEvent gesture_event(WebInputEvent::kGestureTap,
+ WebGestureEvent gesture_event(WebInputEvent::Type::kGestureTap,
WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests(),
WebGestureDevice::kTouchscreen);
@@ -2886,77 +2892,6 @@ TEST_F(WebFrameTest, DesktopPageCanBeZoomedInWhenWideViewportIsTurnedOff) {
0.01f);
}
-TEST_F(WebFrameTest, AtViewportInsideAtMediaInitialViewport) {
- RegisterMockedHttpURLLoad("viewport-inside-media.html");
-
- FixedLayoutTestWebWidgetClient client;
- frame_test_helpers::WebViewHelper web_view_helper;
- web_view_helper.InitializeAndLoad(base_url_ + "viewport-inside-media.html",
- nullptr, nullptr, &client,
- ConfigureAndroid);
- web_view_helper.Resize(WebSize(640, 480));
-
- EXPECT_EQ(2000, web_view_helper.GetWebView()
- ->MainFrameImpl()
- ->GetFrameView()
- ->GetLayoutSize()
- .Width());
-
- web_view_helper.Resize(WebSize(1200, 480));
-
- EXPECT_EQ(1200, web_view_helper.GetWebView()
- ->MainFrameImpl()
- ->GetFrameView()
- ->GetLayoutSize()
- .Width());
-}
-
-TEST_F(WebFrameTest, AtViewportAffectingAtMediaRecalcCount) {
- RegisterMockedHttpURLLoad("viewport-and-media.html");
-
- FixedLayoutTestWebWidgetClient client;
- frame_test_helpers::WebViewHelper web_view_helper;
- web_view_helper.Initialize(nullptr, nullptr, &client, ConfigureAndroid);
- web_view_helper.Resize(WebSize(640, 480));
- frame_test_helpers::LoadFrame(web_view_helper.GetWebView()->MainFrameImpl(),
- base_url_ + "viewport-and-media.html");
-
- Document* document =
- web_view_helper.LocalMainFrame()->GetFrame()->GetDocument();
- EXPECT_EQ(2000, web_view_helper.GetWebView()
- ->MainFrameImpl()
- ->GetFrameView()
- ->GetLayoutSize()
- .Width());
-
- // The styleForElementCount() should match the number of elements for a single
- // pass of computed styles construction for the document.
- EXPECT_EQ(8u, document->GetStyleEngine().StyleForElementCount());
- EXPECT_EQ(Color(0, 128, 0),
- document->body()->GetComputedStyle()->VisitedDependentColor(
- GetCSSPropertyColor()));
-}
-
-TEST_F(WebFrameTest, AtViewportWithViewportLengths) {
- RegisterMockedHttpURLLoad("viewport-lengths.html");
-
- FixedLayoutTestWebWidgetClient client;
- frame_test_helpers::WebViewHelper web_view_helper;
- web_view_helper.Initialize(nullptr, nullptr, &client, ConfigureAndroid);
- web_view_helper.Resize(WebSize(800, 600));
- frame_test_helpers::LoadFrame(web_view_helper.GetWebView()->MainFrameImpl(),
- base_url_ + "viewport-lengths.html");
-
- LocalFrameView* view = web_view_helper.LocalMainFrame()->GetFrameView();
- EXPECT_EQ(400, view->GetLayoutSize().Width());
- EXPECT_EQ(300, view->GetLayoutSize().Height());
-
- web_view_helper.Resize(WebSize(1000, 400));
-
- EXPECT_EQ(500, view->GetLayoutSize().Width());
- EXPECT_EQ(200, view->GetLayoutSize().Height());
-}
-
class WebFrameResizeTest : public WebFrameTest {
protected:
static FloatSize ComputeRelativeOffset(const IntPoint& absolute_offset,
@@ -4185,29 +4120,6 @@ TEST_F(WebFrameTest, DivScrollIntoEditableTestWithDeviceScaleFactor) {
EXPECT_NEAR(min_readable_caret_height / caret_bounds.Height(), scale, 0.1);
}
-TEST_F(WebFrameTest, CharacterIndexAtPointWithPinchZoom) {
- RegisterMockedHttpURLLoad("sometext.html");
-
- frame_test_helpers::WebViewHelper web_view_helper;
- web_view_helper.InitializeAndLoad(base_url_ + "sometext.html");
- web_view_helper.LoadAhem();
- web_view_helper.Resize(WebSize(640, 480));
-
- // Move the visual viewport to the start of the target div containing the
- // text.
- web_view_helper.GetWebView()->SetPageScaleFactor(2);
- web_view_helper.GetWebView()->SetVisualViewportOffset(gfx::PointF(100, 50));
-
- WebLocalFrame* main_frame =
- web_view_helper.GetWebView()->MainFrame()->ToWebLocalFrame();
-
- // Since we're zoomed in to 2X, each char of Ahem is 20px wide/tall in
- // viewport space. We expect to hit the fifth char on the first line.
- size_t ix = main_frame->CharacterIndexForPoint(gfx::Point(100, 15));
-
- EXPECT_EQ(5ul, ix);
-}
-
TEST_F(WebFrameTest, FirstRectForCharacterRangeWithPinchZoom) {
RegisterMockedHttpURLLoad("textbox.html");
@@ -4397,10 +4309,11 @@ TEST_F(WebFrameTest, TabKeyCursorMoveTriggersOneSelectionChange) {
WebViewImpl* web_view = web_view_helper.InitializeAndLoad(
base_url_ + "editable_elements.html", &counter);
- WebKeyboardEvent tab_down(WebInputEvent::kKeyDown,
+ WebKeyboardEvent tab_down(WebInputEvent::Type::kKeyDown,
WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests());
- WebKeyboardEvent tab_up(WebInputEvent::kKeyUp, WebInputEvent::kNoModifiers,
+ WebKeyboardEvent tab_up(WebInputEvent::Type::kKeyUp,
+ WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests());
tab_down.dom_key = ui::DomKey::TAB;
tab_up.dom_key = ui::DomKey::TAB;
@@ -4410,32 +4323,37 @@ TEST_F(WebFrameTest, TabKeyCursorMoveTriggersOneSelectionChange) {
// Move to the next text-field: 1 cursor change.
counter.Reset();
web_view->MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(tab_down));
- web_view->MainFrameWidget()->HandleInputEvent(WebCoalescedInputEvent(tab_up));
+ WebCoalescedInputEvent(tab_down, ui::LatencyInfo()));
+ web_view->MainFrameWidget()->HandleInputEvent(
+ WebCoalescedInputEvent(tab_up, ui::LatencyInfo()));
EXPECT_EQ(1, counter.Count());
// Move to another text-field: 1 cursor change.
web_view->MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(tab_down));
- web_view->MainFrameWidget()->HandleInputEvent(WebCoalescedInputEvent(tab_up));
+ WebCoalescedInputEvent(tab_down, ui::LatencyInfo()));
+ web_view->MainFrameWidget()->HandleInputEvent(
+ WebCoalescedInputEvent(tab_up, ui::LatencyInfo()));
EXPECT_EQ(2, counter.Count());
// Move to a number-field: 1 cursor change.
web_view->MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(tab_down));
- web_view->MainFrameWidget()->HandleInputEvent(WebCoalescedInputEvent(tab_up));
+ WebCoalescedInputEvent(tab_down, ui::LatencyInfo()));
+ web_view->MainFrameWidget()->HandleInputEvent(
+ WebCoalescedInputEvent(tab_up, ui::LatencyInfo()));
EXPECT_EQ(3, counter.Count());
// Move to an editable element: 1 cursor change.
web_view->MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(tab_down));
- web_view->MainFrameWidget()->HandleInputEvent(WebCoalescedInputEvent(tab_up));
+ WebCoalescedInputEvent(tab_down, ui::LatencyInfo()));
+ web_view->MainFrameWidget()->HandleInputEvent(
+ WebCoalescedInputEvent(tab_up, ui::LatencyInfo()));
EXPECT_EQ(4, counter.Count());
// Move to a non-editable element: 0 cursor changes.
web_view->MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(tab_down));
- web_view->MainFrameWidget()->HandleInputEvent(WebCoalescedInputEvent(tab_up));
+ WebCoalescedInputEvent(tab_down, ui::LatencyInfo()));
+ web_view->MainFrameWidget()->HandleInputEvent(
+ WebCoalescedInputEvent(tab_up, ui::LatencyInfo()));
EXPECT_EQ(4, counter.Count());
}
@@ -4478,13 +4396,14 @@ class ContextLifetimeTestWebFrameClient
}
// WebLocalFrameClient:
- WebLocalFrame* CreateChildFrame(WebLocalFrame* parent,
- WebTreeScopeType scope,
- const WebString& name,
- const WebString& fallback_name,
- const FramePolicy&,
- const WebFrameOwnerProperties&,
- FrameOwnerElementType) override {
+ WebLocalFrame* CreateChildFrame(
+ WebLocalFrame* parent,
+ mojom::blink::TreeScopeType scope,
+ const WebString& name,
+ const WebString& fallback_name,
+ const FramePolicy&,
+ const WebFrameOwnerProperties&,
+ mojom::blink::FrameOwnerElementType) override {
return CreateLocalChild(*parent, scope,
std::make_unique<ContextLifetimeTestWebFrameClient>(
create_notifications_, release_notifications_));
@@ -6236,7 +6155,7 @@ class CompositedSelectionBoundsTest
3);
}
- WebGestureEvent gesture_event(WebInputEvent::kGestureTap,
+ WebGestureEvent gesture_event(WebInputEvent::Type::kGestureTap,
WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests(),
WebGestureDevice::kTouchscreen);
@@ -7084,7 +7003,7 @@ class TestNewWindowWebViewClient
const WebWindowFeatures&,
const WebString&,
WebNavigationPolicy,
- mojom::blink::WebSandboxFlags,
+ network::mojom::blink::WebSandboxFlags,
const FeaturePolicy::FeatureState&,
const SessionStorageNamespaceId&) override {
EXPECT_TRUE(false);
@@ -7237,12 +7156,12 @@ class TestCachePolicyWebFrameClient
// frame_test_helpers::TestWebFrameClient:
WebLocalFrame* CreateChildFrame(
WebLocalFrame* parent,
- WebTreeScopeType scope,
+ mojom::blink::TreeScopeType scope,
const WebString&,
const WebString&,
const FramePolicy&,
const WebFrameOwnerProperties& frame_owner_properties,
- FrameOwnerElementType) override {
+ mojom::blink::FrameOwnerElementType) override {
auto child = std::make_unique<TestCachePolicyWebFrameClient>();
auto* child_ptr = child.get();
child_clients_.push_back(std::move(child));
@@ -7516,10 +7435,8 @@ TEST_F(WebFrameTest, IPAddressSpace) {
frame_test_helpers::PumpPendingRequestsForFrameToLoad(
web_view_helper.LocalMainFrame());
- ExecutionContext* context = web_view->MainFrameImpl()
- ->GetFrame()
- ->GetDocument()
- ->ToExecutionContext();
+ ExecutionContext* context =
+ web_view->MainFrameImpl()->GetFrame()->DomWindow();
EXPECT_EQ(value, context->GetSecurityContext().AddressSpace());
}
}
@@ -7685,12 +7602,12 @@ class FailCreateChildFrame : public frame_test_helpers::TestWebFrameClient {
// frame_test_helpers::TestWebFrameClient:
WebLocalFrame* CreateChildFrame(
WebLocalFrame* parent,
- WebTreeScopeType scope,
+ mojom::blink::TreeScopeType scope,
const WebString& name,
const WebString& fallback_name,
const FramePolicy&,
const WebFrameOwnerProperties& frame_owner_properties,
- FrameOwnerElementType) override {
+ mojom::blink::FrameOwnerElementType) override {
++call_count_;
return nullptr;
}
@@ -8860,23 +8777,28 @@ TEST_F(WebFrameTest, EmbedderTriggeredDetachWithRemoteMainFrame) {
class WebFrameSwapTestClient : public frame_test_helpers::TestWebFrameClient {
public:
- WebFrameSwapTestClient() {}
-
- WebLocalFrame* CreateChildFrame(WebLocalFrame* parent,
- WebTreeScopeType scope,
- const WebString& name,
- const WebString& fallback_name,
- const FramePolicy&,
- const WebFrameOwnerProperties&,
- FrameOwnerElementType) override {
+ explicit WebFrameSwapTestClient(WebFrameSwapTestClient* parent = nullptr) {
+ local_frame_host_ =
+ std::make_unique<TestLocalFrameHostForFrameOwnerPropertiesChanges>(
+ parent);
+ local_frame_host_->Init(GetRemoteNavigationAssociatedInterfaces());
+ }
+
+ WebLocalFrame* CreateChildFrame(
+ WebLocalFrame* parent,
+ mojom::blink::TreeScopeType scope,
+ const WebString& name,
+ const WebString& fallback_name,
+ const FramePolicy&,
+ const WebFrameOwnerProperties&,
+ mojom::blink::FrameOwnerElementType) override {
return CreateLocalChild(*parent, scope,
- std::make_unique<WebFrameSwapTestClient>());
+ std::make_unique<WebFrameSwapTestClient>(this));
}
void DidChangeFrameOwnerProperties(
- WebFrame* child_frame,
- const WebFrameOwnerProperties& properties) override {
- did_propagate_display_none_ |= properties.is_display_none;
+ mojom::blink::FrameOwnerPropertiesPtr properties) {
+ did_propagate_display_none_ |= properties->is_display_none;
}
bool DidPropagateDisplayNoneProperty() const {
@@ -8884,6 +8806,28 @@ class WebFrameSwapTestClient : public frame_test_helpers::TestWebFrameClient {
}
private:
+ class TestLocalFrameHostForFrameOwnerPropertiesChanges
+ : public FakeLocalFrameHost {
+ public:
+ explicit TestLocalFrameHostForFrameOwnerPropertiesChanges(
+ WebFrameSwapTestClient* parent)
+ : parent_(parent) {}
+ ~TestLocalFrameHostForFrameOwnerPropertiesChanges() override = default;
+
+ // FakeLocalFrameHost:
+ void DidChangeFrameOwnerProperties(
+ const base::UnguessableToken& child_frame_token,
+ mojom::blink::FrameOwnerPropertiesPtr properties) override {
+ if (parent_)
+ parent_->DidChangeFrameOwnerProperties(std::move(properties));
+ }
+
+ bool did_propagate_display_none_ = false;
+ WebFrameSwapTestClient* parent_ = nullptr;
+ };
+
+ std::unique_ptr<TestLocalFrameHostForFrameOwnerPropertiesChanges>
+ local_frame_host_;
bool did_propagate_display_none_ = false;
};
@@ -9530,12 +9474,14 @@ class RemoteNavigationClient
// frame_test_helpers::TestWebRemoteFrameClient:
void Navigate(const WebURLRequest& request,
+ blink::WebLocalFrame* initiator_frame,
bool should_replace_current_entry,
bool is_opener_navigation,
bool initiator_frame_has_download_sandbox_flag,
bool blocking_downloads_in_sandbox_enabled,
bool initiator_frame_is_ad,
- mojo::ScopedMessagePipeHandle) override {
+ mojo::ScopedMessagePipeHandle,
+ const base::Optional<WebImpression>& impression) override {
last_request_.CopyFrom(request);
}
@@ -9746,11 +9692,13 @@ TEST_F(WebFrameTest, FrameWidgetTest) {
helper.GetWebView()->Resize(WebSize(1000, 1000));
- WebGestureEvent event(WebInputEvent::kGestureTap, WebInputEvent::kNoModifiers,
+ WebGestureEvent event(WebInputEvent::Type::kGestureTap,
+ WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests(),
WebGestureDevice::kTouchscreen);
event.SetPositionInWidget(gfx::PointF(20, 20));
- child_frame->FrameWidget()->HandleInputEvent(WebCoalescedInputEvent(event));
+ child_frame->FrameWidget()->HandleInputEvent(
+ WebCoalescedInputEvent(event, ui::LatencyInfo()));
EXPECT_TRUE(child_widget_client.DidHandleGestureEvent());
helper.Reset();
@@ -10087,21 +10035,21 @@ class WebFrameOverscrollTest
// TODO(wjmaclean): Make sure that touchpad device is only ever used for
// gesture scrolling event types.
event.SetPositionInWidget(gfx::PointF(100, 100));
- if (type == WebInputEvent::kGestureScrollUpdate) {
+ if (type == WebInputEvent::Type::kGestureScrollUpdate) {
event.data.scroll_update.delta_x = delta_x;
event.data.scroll_update.delta_y = delta_y;
- } else if (type == WebInputEvent::kGestureScrollBegin) {
+ } else if (type == WebInputEvent::Type::kGestureScrollBegin) {
event.data.scroll_begin.delta_x_hint = delta_x;
event.data.scroll_begin.delta_y_hint = delta_y;
}
- return WebCoalescedInputEvent(event);
+ return WebCoalescedInputEvent(event, ui::LatencyInfo());
}
void ScrollBegin(frame_test_helpers::WebViewHelper* web_view_helper,
float delta_x_hint,
float delta_y_hint) {
web_view_helper->GetWebView()->MainFrameWidget()->HandleInputEvent(
- GenerateEvent(WebInputEvent::kGestureScrollBegin, delta_x_hint,
+ GenerateEvent(WebInputEvent::Type::kGestureScrollBegin, delta_x_hint,
delta_y_hint));
}
@@ -10109,12 +10057,13 @@ class WebFrameOverscrollTest
float delta_x,
float delta_y) {
web_view_helper->GetWebView()->MainFrameWidget()->HandleInputEvent(
- GenerateEvent(WebInputEvent::kGestureScrollUpdate, delta_x, delta_y));
+ GenerateEvent(WebInputEvent::Type::kGestureScrollUpdate, delta_x,
+ delta_y));
}
void ScrollEnd(frame_test_helpers::WebViewHelper* web_view_helper) {
web_view_helper->GetWebView()->MainFrameWidget()->HandleInputEvent(
- GenerateEvent(WebInputEvent::kGestureScrollEnd));
+ GenerateEvent(WebInputEvent::Type::kGestureScrollEnd));
}
};
@@ -10502,16 +10451,21 @@ TEST_F(WebFrameTest, OrientationFrameDetach) {
web_view_impl->MainFrameImpl()->SendOrientationChangeEvent();
}
-#if defined(THREAD_SANITIZER)
-TEST_F(WebFrameTest, DISABLED_MaxFramesDetach) {
-#else
-TEST_F(WebFrameTest, MaxFramesDetach) {
-#endif // defined(THREAD_SANITIZER)
- RegisterMockedHttpURLLoad("max-frames-detach.html");
+TEST_F(WebFrameTest, MaxFrames) {
frame_test_helpers::WebViewHelper web_view_helper;
- WebViewImpl* web_view_impl =
- web_view_helper.InitializeAndLoad(base_url_ + "max-frames-detach.html");
- web_view_impl->MainFrameImpl()->CollectGarbageForTesting();
+ web_view_helper.InitializeRemote();
+ Page* page = web_view_helper.GetWebView()->GetPage();
+
+ WebLocalFrameImpl* frame =
+ frame_test_helpers::CreateLocalChild(*web_view_helper.RemoteMainFrame());
+ while (page->SubframeCount() < Page::kMaxNumberOfFrames) {
+ frame_test_helpers::CreateRemoteChild(*web_view_helper.RemoteMainFrame());
+ }
+ auto* iframe = MakeGarbageCollected<HTMLIFrameElement>(
+ *frame->GetFrame()->GetDocument());
+ iframe->setAttribute(html_names::kSrcAttr, "");
+ frame->GetFrame()->GetDocument()->body()->appendChild(iframe);
+ EXPECT_FALSE(iframe->ContentFrame());
}
TEST_F(WebFrameTest, ImageDocumentLoadResponseEnd) {
@@ -10762,13 +10716,14 @@ class WebLocalFrameVisibilityChangeTest
WebLocalFrame* MainFrame() { return frame_; }
// frame_test_helpers::TestWebFrameClient:
- WebLocalFrame* CreateChildFrame(WebLocalFrame* parent,
- WebTreeScopeType scope,
- const WebString& name,
- const WebString& fallback_name,
- const FramePolicy&,
- const WebFrameOwnerProperties&,
- FrameOwnerElementType) override {
+ WebLocalFrame* CreateChildFrame(
+ WebLocalFrame* parent,
+ mojom::blink::TreeScopeType scope,
+ const WebString& name,
+ const WebString& fallback_name,
+ const FramePolicy&,
+ const WebFrameOwnerProperties&,
+ mojom::blink::FrameOwnerElementType) override {
return CreateLocalChild(*parent, scope, &child_client_);
}
@@ -11392,29 +11347,29 @@ TEST_F(WebFrameTest, ScrollBeforeLayoutDoesntCrash) {
document->documentElement()->SetLayoutObject(nullptr);
WebGestureEvent begin_event(
- WebInputEvent::kGestureScrollBegin, WebInputEvent::kNoModifiers,
+ WebInputEvent::Type::kGestureScrollBegin, WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests(), WebGestureDevice::kTouchpad);
WebGestureEvent update_event(
- WebInputEvent::kGestureScrollUpdate, WebInputEvent::kNoModifiers,
+ WebInputEvent::Type::kGestureScrollUpdate, WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests(), WebGestureDevice::kTouchpad);
WebGestureEvent end_event(
- WebInputEvent::kGestureScrollEnd, WebInputEvent::kNoModifiers,
+ WebInputEvent::Type::kGestureScrollEnd, WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests(), WebGestureDevice::kTouchpad);
// Try GestureScrollEnd and GestureScrollUpdate first to make sure that not
// seeing a Begin first doesn't break anything. (This currently happens).
web_view_helper.GetWebView()->MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(end_event));
+ WebCoalescedInputEvent(end_event, ui::LatencyInfo()));
web_view_helper.GetWebView()->MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(update_event));
+ WebCoalescedInputEvent(update_event, ui::LatencyInfo()));
// Try a full Begin/Update/End cycle.
web_view_helper.GetWebView()->MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(begin_event));
+ WebCoalescedInputEvent(begin_event, ui::LatencyInfo()));
web_view_helper.GetWebView()->MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(update_event));
+ WebCoalescedInputEvent(update_event, ui::LatencyInfo()));
web_view_helper.GetWebView()->MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(end_event));
+ WebCoalescedInputEvent(end_event, ui::LatencyInfo()));
}
TEST_F(WebFrameTest, MouseOverDifferntNodeClearsTooltip) {
@@ -11450,13 +11405,13 @@ TEST_F(WebFrameTest, MouseOverDifferntNodeClearsTooltip) {
Element* div1_tag = document->getElementById("div1");
HitTestResult hit_test_result = web_view->CoreHitTestResultAt(
- gfx::Point(div1_tag->OffsetLeft() + 5, div1_tag->OffsetTop() + 5));
+ gfx::PointF(div1_tag->OffsetLeft() + 5, div1_tag->OffsetTop() + 5));
EXPECT_TRUE(hit_test_result.InnerElement());
// Mouse over link. Mouse cursor should be hand.
WebMouseEvent mouse_move_over_link_event(
- WebInputEvent::kMouseMove,
+ WebInputEvent::Type::kMouseMove,
gfx::PointF(div1_tag->OffsetLeft() + 5, div1_tag->OffsetTop() + 5),
gfx::PointF(div1_tag->OffsetLeft() + 5, div1_tag->OffsetTop() + 5),
WebPointerProperties::Button::kNoButton, 0, WebInputEvent::kNoModifiers,
@@ -11476,7 +11431,7 @@ TEST_F(WebFrameTest, MouseOverDifferntNodeClearsTooltip) {
Element* div2_tag = document->getElementById("div2");
WebMouseEvent mouse_move_event(
- WebInputEvent::kMouseMove,
+ WebInputEvent::Type::kMouseMove,
gfx::PointF(div2_tag->OffsetLeft() + 5, div2_tag->OffsetTop() + 5),
gfx::PointF(div2_tag->OffsetLeft() + 5, div2_tag->OffsetTop() + 5),
WebPointerProperties::Button::kNoButton, 0, WebInputEvent::kNoModifiers,
@@ -11718,28 +11673,28 @@ TEST_F(WebFrameSimTest, ScrollToEndBubblingCrash) {
// Focus the iframe.
WebView().AdvanceFocus(false);
- WebKeyboardEvent key_event(WebInputEvent::kRawKeyDown,
+ WebKeyboardEvent key_event(WebInputEvent::Type::kRawKeyDown,
WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests());
key_event.windows_key_code = VKEY_END;
// Scroll the iframe to the end.
- key_event.SetType(WebInputEvent::kRawKeyDown);
+ key_event.SetType(WebInputEvent::Type::kRawKeyDown);
WebView().MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(key_event));
- key_event.SetType(WebInputEvent::kKeyUp);
+ WebCoalescedInputEvent(key_event, ui::LatencyInfo()));
+ key_event.SetType(WebInputEvent::Type::kKeyUp);
WebView().MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(key_event));
+ WebCoalescedInputEvent(key_event, ui::LatencyInfo()));
Compositor().BeginFrame();
// End key should now bubble from the iframe up to the main viewport.
- key_event.SetType(WebInputEvent::kRawKeyDown);
+ key_event.SetType(WebInputEvent::Type::kRawKeyDown);
WebView().MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(key_event));
- key_event.SetType(WebInputEvent::kKeyUp);
+ WebCoalescedInputEvent(key_event, ui::LatencyInfo()));
+ key_event.SetType(WebInputEvent::Type::kKeyUp);
WebView().MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(key_event));
+ WebCoalescedInputEvent(key_event, ui::LatencyInfo()));
}
TEST_F(WebFrameSimTest, TestScrollFocusedEditableElementIntoView) {
@@ -12460,13 +12415,14 @@ TEST_F(WebFrameTest, NoLoadingCompletionCallbacksInDetach) {
~MainFrameClient() override = default;
// frame_test_helpers::TestWebFrameClient:
- WebLocalFrame* CreateChildFrame(WebLocalFrame* parent,
- WebTreeScopeType scope,
- const WebString& name,
- const WebString& fallback_name,
- const FramePolicy&,
- const WebFrameOwnerProperties&,
- FrameOwnerElementType) override {
+ WebLocalFrame* CreateChildFrame(
+ WebLocalFrame* parent,
+ mojom::blink::TreeScopeType scope,
+ const WebString& name,
+ const WebString& fallback_name,
+ const FramePolicy&,
+ const WebFrameOwnerProperties&,
+ mojom::blink::FrameOwnerElementType) override {
return CreateLocalChild(*parent, scope, &child_client_);
}
@@ -12577,10 +12533,10 @@ bool TestSelectAll(const std::string& html) {
web_view->MainFrameWidget()->UpdateAllLifecyclePhases(
DocumentUpdateReason::kTest);
RunPendingTasks();
- web_view->SetInitialFocus(false);
+ web_view->MainFrameImpl()->GetFrame()->SetInitialFocus(false);
RunPendingTasks();
- WebMouseEvent mouse_event(WebInputEvent::kMouseDown,
+ WebMouseEvent mouse_event(WebInputEvent::Type::kMouseDown,
WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests());
@@ -12588,7 +12544,7 @@ bool TestSelectAll(const std::string& html) {
mouse_event.SetPositionInWidget(8, 8);
mouse_event.click_count = 1;
web_view->MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(mouse_event));
+ WebCoalescedInputEvent(mouse_event, ui::LatencyInfo()));
RunPendingTasks();
web_view_helper.Reset();
return frame.GetMenuData().edit_flags &
@@ -12615,12 +12571,12 @@ TEST_F(WebFrameTest, ContextMenuDataSelectedText) {
web_view->MainFrameWidget()->Resize(WebSize(500, 300));
UpdateAllLifecyclePhases(web_view);
RunPendingTasks();
- web_view->SetInitialFocus(false);
+ web_view->MainFrameImpl()->GetFrame()->SetInitialFocus(false);
RunPendingTasks();
web_view->MainFrameImpl()->ExecuteCommand(WebString::FromUTF8("SelectAll"));
- WebMouseEvent mouse_event(WebInputEvent::kMouseDown,
+ WebMouseEvent mouse_event(WebInputEvent::Type::kMouseDown,
WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests());
@@ -12628,7 +12584,7 @@ TEST_F(WebFrameTest, ContextMenuDataSelectedText) {
mouse_event.SetPositionInWidget(8, 8);
mouse_event.click_count = 1;
web_view->MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(mouse_event));
+ WebCoalescedInputEvent(mouse_event, ui::LatencyInfo()));
RunPendingTasks();
web_view_helper.Reset();
EXPECT_EQ(frame.GetMenuData().selected_text, " ");
@@ -12644,12 +12600,12 @@ TEST_F(WebFrameTest, ContextMenuDataPasswordSelectedText) {
web_view->MainFrameWidget()->Resize(WebSize(500, 300));
UpdateAllLifecyclePhases(web_view);
RunPendingTasks();
- web_view->SetInitialFocus(false);
+ web_view->MainFrameImpl()->GetFrame()->SetInitialFocus(false);
RunPendingTasks();
web_view->MainFrameImpl()->ExecuteCommand(WebString::FromUTF8("SelectAll"));
- WebMouseEvent mouse_event(WebInputEvent::kMouseDown,
+ WebMouseEvent mouse_event(WebInputEvent::Type::kMouseDown,
WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests());
@@ -12657,7 +12613,7 @@ TEST_F(WebFrameTest, ContextMenuDataPasswordSelectedText) {
mouse_event.SetPositionInWidget(8, 8);
mouse_event.click_count = 1;
web_view->MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(mouse_event));
+ WebCoalescedInputEvent(mouse_event, ui::LatencyInfo()));
RunPendingTasks();
web_view_helper.Reset();
@@ -12678,10 +12634,10 @@ TEST_F(WebFrameTest, ContextMenuDataNonLocatedMenu) {
web_view->MainFrameWidget()->Resize(WebSize(500, 300));
UpdateAllLifecyclePhases(web_view);
RunPendingTasks();
- web_view->SetInitialFocus(false);
+ web_view->MainFrameImpl()->GetFrame()->SetInitialFocus(false);
RunPendingTasks();
- WebMouseEvent mouse_event(WebInputEvent::kMouseDown,
+ WebMouseEvent mouse_event(WebInputEvent::Type::kMouseDown,
WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests());
@@ -12689,7 +12645,7 @@ TEST_F(WebFrameTest, ContextMenuDataNonLocatedMenu) {
mouse_event.SetPositionInWidget(0, 0);
mouse_event.click_count = 2;
web_view->MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(mouse_event));
+ WebCoalescedInputEvent(mouse_event, ui::LatencyInfo()));
web_view->MainFrameWidget()->ShowContextMenu(kMenuSourceTouch);
@@ -12725,12 +12681,12 @@ class TestFallbackWebFrameClient
// frame_test_helpers::TestWebFrameClient:
WebLocalFrame* CreateChildFrame(
WebLocalFrame* parent,
- WebTreeScopeType scope,
+ mojom::blink::TreeScopeType scope,
const WebString&,
const WebString&,
const FramePolicy&,
const WebFrameOwnerProperties& frameOwnerProperties,
- FrameOwnerElementType) override {
+ mojom::blink::FrameOwnerElementType) override {
DCHECK(child_client_);
return CreateLocalChild(*parent, scope, child_client_);
}
@@ -12775,7 +12731,7 @@ TEST_F(WebFrameTest, FallbackForNonexistentProvisionalNavigation) {
// page.
EXPECT_EQ(WebNavigationControl::NoLoadInProgress,
To<WebLocalFrameImpl>(child)->MaybeRenderFallbackContent(
- ResourceError::Failure(request.Url())));
+ WebURLError(ResourceError::Failure(request.Url()))));
}
TEST_F(WebFrameTest, AltTextOnAboutBlankPage) {
@@ -13065,7 +13021,7 @@ TEST_F(WebFrameSimTest, GetPageSizeType) {
EXPECT_EQ(PageSizeType::kAuto, main_frame->GetPageSizeType(1));
for (const auto& test : test_cases) {
- style_decl->setProperty(doc->ToExecutionContext(), "size", test.size, "",
+ style_decl->setProperty(doc->GetExecutionContext(), "size", test.size, "",
ASSERT_NO_EXCEPTION);
EXPECT_EQ(test.page_size_type, main_frame->GetPageSizeType(1));
}
diff --git a/chromium/third_party/blink/renderer/core/exported/web_hit_test_result.cc b/chromium/third_party/blink/renderer/core/exported/web_hit_test_result.cc
index e10a1a25bc1..a5b6c36bab2 100644
--- a/chromium/third_party/blink/renderer/core/exported/web_hit_test_result.cc
+++ b/chromium/third_party/blink/renderer/core/exported/web_hit_test_result.cc
@@ -61,16 +61,12 @@ WebNode WebHitTestResult::GetNode() const {
return WebNode(private_->Result().InnerNode());
}
-gfx::Point WebHitTestResult::LocalPoint() const {
- return RoundedIntPoint(private_->Result().LocalPoint());
-}
-
-gfx::Point WebHitTestResult::LocalPointWithoutContentBoxOffset() const {
- IntPoint local_point = RoundedIntPoint(private_->Result().LocalPoint());
+gfx::PointF WebHitTestResult::LocalPointWithoutContentBoxOffset() const {
+ FloatPoint local_point = FloatPoint(private_->Result().LocalPoint());
LayoutObject* object = private_->Result().GetLayoutObject();
if (object->IsBox()) {
LayoutBox* box = ToLayoutBox(object);
- local_point.MoveBy(-RoundedIntPoint(box->PhysicalContentBoxOffset()));
+ local_point.MoveBy(-FloatPoint(box->PhysicalContentBoxOffset()));
}
return local_point;
}
diff --git a/chromium/third_party/blink/renderer/core/exported/web_page_popup_impl.cc b/chromium/third_party/blink/renderer/core/exported/web_page_popup_impl.cc
index 68313af7437..2c6f9c8b977 100644
--- a/chromium/third_party/blink/renderer/core/exported/web_page_popup_impl.cc
+++ b/chromium/third_party/blink/renderer/core/exported/web_page_popup_impl.cc
@@ -33,12 +33,15 @@
#include "cc/animation/animation_host.h"
#include "cc/layers/picture_layer.h"
+#include "cc/trees/ukm_manager.h"
+#include "third_party/blink/public/platform/scheduler/web_render_widget_scheduling_state.h"
#include "third_party/blink/public/platform/web_float_rect.h"
#include "third_party/blink/public/web/web_view_client.h"
#include "third_party/blink/renderer/core/accessibility/ax_object_cache_base.h"
#include "third_party/blink/renderer/core/dom/context_features.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/events/event_dispatch_forbidden_scope.h"
+#include "third_party/blink/renderer/core/dom/node_computed_style.h"
#include "third_party/blink/renderer/core/events/message_event.h"
#include "third_party/blink/renderer/core/events/web_input_event_conversion.h"
#include "third_party/blink/renderer/core/exported/web_settings_impl.h"
@@ -52,6 +55,7 @@
#include "third_party/blink/renderer/core/frame/visual_viewport.h"
#include "third_party/blink/renderer/core/frame/web_frame_widget_base.h"
#include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
+#include "third_party/blink/renderer/core/geometry/dom_rect.h"
#include "third_party/blink/renderer/core/input/event_handler.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
#include "third_party/blink/renderer/core/loader/empty_clients.h"
@@ -59,7 +63,7 @@
#include "third_party/blink/renderer/core/page/focus_controller.h"
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/core/page/page_popup_client.h"
-#include "third_party/blink/renderer/core/page/page_popup_supplement.h"
+#include "third_party/blink/renderer/core/page/page_popup_controller.h"
#include "third_party/blink/renderer/platform/animation/compositor_animation_timeline.h"
#include "third_party/blink/renderer/platform/bindings/script_forbidden_scope.h"
#include "third_party/blink/renderer/platform/graphics/graphics_layer.h"
@@ -289,19 +293,36 @@ void WebPagePopupImpl::Initialize(WebViewImpl* web_view,
page_->GetSettings().SetPrimaryPointerType(
main_settings.GetPrimaryPointerType());
+ // The style can be out-of-date if e.g. a key event handler modified the
+ // OwnerElement()'s style before the default handler started opening the
+ // popup. If the key handler forced a style update the style may be up-to-date
+ // and null.
+ // Note that if there's a key event handler which changes the color-scheme
+ // between the key is pressed and the popup is opened, the color-scheme of the
+ // form element and its popup may not match.
+ // If we think it's important to have an up-to-date style here, we need to run
+ // an UpdateStyleAndLayoutTree() before opening the popup in the various
+ // default event handlers.
+ if (const auto* style = popup_client_->OwnerElement().GetComputedStyle()) {
+ page_->GetSettings().SetPreferredColorScheme(
+ style->UsedColorScheme() == WebColorScheme::kDark
+ ? PreferredColorScheme::kDark
+ : PreferredColorScheme::kLight);
+ }
+ popup_client_->CreatePagePopupController(*page_, *this);
+
ProvideContextFeaturesTo(*page_, std::make_unique<PagePopupFeaturesClient>());
DEFINE_STATIC_LOCAL(Persistent<LocalFrameClient>, empty_local_frame_client,
(MakeGarbageCollected<EmptyLocalFrameClient>()));
// Creating new WindowAgentFactory because page popup content is owned by the
// user agent and should be isolated from the main frame.
- auto* frame =
- MakeGarbageCollected<LocalFrame>(empty_local_frame_client, *page_,
- /* FrameOwner* */ nullptr,
- /* WindowAgentFactory* */ nullptr,
- /* InterfaceRegistry* */ nullptr);
+ auto* frame = MakeGarbageCollected<LocalFrame>(
+ empty_local_frame_client, *page_,
+ /* FrameOwner* */ nullptr, base::UnguessableToken::Create(),
+ /* WindowAgentFactory* */ nullptr,
+ /* InterfaceRegistry* */ nullptr);
frame->SetPagePopupOwner(popup_client_->OwnerElement());
frame->SetView(MakeGarbageCollected<LocalFrameView>(*frame));
- PagePopupSupplement::Install(*frame, *this, popup_client_);
frame->Init();
frame->View()->SetParentVisible(true);
frame->View()->SetSelfVisible(true);
@@ -321,27 +342,34 @@ void WebPagePopupImpl::Initialize(WebViewImpl* web_view,
frame->SetPageZoomFactor(popup_client_->ZoomFactor());
frame->ForceSynchronousDocumentInstall("text/html", std::move(data));
+ popup_owner_client_rect_ =
+ popup_client_->OwnerElement().getBoundingClientRect();
WidgetClient()->Show(WebNavigationPolicy());
SetFocus(true);
}
-void WebPagePopupImpl::SetCompositorHosts(cc::LayerTreeHost* layer_tree_host,
- cc::AnimationHost* animation_host) {
- // Careful Initialize() is called after SetCompositorHosts, so don't do
+cc::LayerTreeHost* WebPagePopupImpl::InitializeCompositing(
+ cc::TaskGraphRunner* task_graph_runner,
+ const cc::LayerTreeSettings& settings,
+ std::unique_ptr<cc::UkmRecorderFactory> ukm_recorder_factory) {
+ // Careful Initialize() is called after InitializeCompositing, so don't do
// much work here.
- widget_base_->SetCompositorHosts(layer_tree_host, animation_host);
+ widget_base_->InitializeCompositing(task_graph_runner, settings,
+ std::move(ukm_recorder_factory));
+ return widget_base_->LayerTreeHost();
}
-void WebPagePopupImpl::SetCompositorVisible(bool visible) {
- widget_base_->SetCompositorVisible(visible);
+scheduler::WebRenderWidgetSchedulingState*
+WebPagePopupImpl::RendererWidgetSchedulingState() {
+ return widget_base_->RendererWidgetSchedulingState();
}
-void WebPagePopupImpl::UpdateVisualState() {
- widget_base_->UpdateVisualState();
+void WebPagePopupImpl::SetCursor(const ui::Cursor& cursor) {
+ widget_base_->SetCursor(cursor);
}
-void WebPagePopupImpl::WillBeginCompositorFrame() {
- widget_base_->WillBeginCompositorFrame();
+void WebPagePopupImpl::SetCompositorVisible(bool visible) {
+ widget_base_->SetCompositorVisible(visible);
}
void WebPagePopupImpl::PostMessageToPopup(const String& message) {
@@ -351,6 +379,20 @@ void WebPagePopupImpl::PostMessageToPopup(const String& message) {
MainFrame().DomWindow()->DispatchEvent(*MessageEvent::Create(message));
}
+void WebPagePopupImpl::Update() {
+ if (!page_ && !popup_client_)
+ return;
+
+ DOMRect* dom_rect = popup_client_->OwnerElement().getBoundingClientRect();
+ bool forced_update = (*dom_rect != *popup_owner_client_rect_);
+ if (forced_update)
+ popup_owner_client_rect_ = dom_rect;
+
+ popup_client_->Update(forced_update);
+ if (forced_update)
+ SetWindowRect(WindowRectInScreen());
+}
+
void WebPagePopupImpl::DestroyPage() {
page_->WillCloseAnimationHost(nullptr);
page_->WillBeDestroyed();
@@ -387,8 +429,9 @@ void WebPagePopupImpl::SetSuppressFrameRequestsWorkaroundFor704763Only(
suppress_frame_requests);
}
-void WebPagePopupImpl::BeginFrame(base::TimeTicks last_frame_time) {
- widget_base_->BeginMainFrame(last_frame_time);
+void WebPagePopupImpl::RequestNewLayerTreeFrameSink(
+ LayerTreeFrameSinkCallback callback) {
+ WidgetClient()->RequestNewLayerTreeFrameSink(std::move(callback));
}
void WebPagePopupImpl::RecordTimeToFirstActivePaint(base::TimeDelta duration) {
@@ -429,7 +472,7 @@ WebInputEventResult WebPagePopupImpl::HandleKeyEvent(
if (closing_)
return WebInputEventResult::kNotHandled;
- if (WebInputEvent::kRawKeyDown == event.GetType()) {
+ if (WebInputEvent::Type::kRawKeyDown == event.GetType()) {
Element* focused_element = FocusedElement();
if (event.windows_key_code == VKEY_TAB && focused_element &&
focused_element->IsKeyboardFocusable()) {
@@ -466,8 +509,8 @@ WebInputEventResult WebPagePopupImpl::HandleGestureEvent(
const WebGestureEvent& event) {
if (closing_)
return WebInputEventResult::kNotHandled;
- if ((event.GetType() == WebInputEvent::kGestureTap ||
- event.GetType() == WebInputEvent::kGestureTapDown) &&
+ if ((event.GetType() == WebInputEvent::Type::kGestureTap ||
+ event.GetType() == WebInputEvent::Type::kGestureTapDown) &&
!IsViewportPointInWindow(event.PositionInWidget().x(),
event.PositionInWidget().y())) {
Cancel();
@@ -557,7 +600,9 @@ WebURL WebPagePopupImpl::GetURLForDebugTrace() {
return {};
}
-void WebPagePopupImpl::Close() {
+void WebPagePopupImpl::Close(
+ scoped_refptr<base::SingleThreadTaskRunner> cleanup_runner,
+ base::OnceCallback<void()> cleanup_task) {
// If the popup is closed from the renderer via Cancel(), then ClosePopup()
// has already run on another stack, and destroyed |page_|. If the popup is
// closed from the browser via IPC to RenderWidget, then we come here first
@@ -570,8 +615,9 @@ void WebPagePopupImpl::Close() {
Cancel();
}
- web_page_popup_client_ = nullptr;
+ widget_base_->Shutdown(std::move(cleanup_runner), std::move(cleanup_task));
widget_base_.reset();
+ web_page_popup_client_ = nullptr;
// Self-delete on Close().
Release();
@@ -612,7 +658,7 @@ void WebPagePopupImpl::ClosePopup() {
EventDispatchForbiddenScope::AllowUserAgentEvents allow_events;
MainFrame().Loader().StopAllLoaders();
- PagePopupSupplement::Uninstall(MainFrame());
+ PagePopupController::From(*page_)->ClearPagePopupClient();
DestroyPage();
}
diff --git a/chromium/third_party/blink/renderer/core/exported/web_page_popup_impl.h b/chromium/third_party/blink/renderer/core/exported/web_page_popup_impl.h
index fbdb7bad95e..723cb08faba 100644
--- a/chromium/third_party/blink/renderer/core/exported/web_page_popup_impl.h
+++ b/chromium/third_party/blink/renderer/core/exported/web_page_popup_impl.h
@@ -55,6 +55,7 @@ class PagePopupClient;
class WebViewImpl;
class LocalDOMWindow;
class WidgetBase;
+class DOMRect;
class CORE_EXPORT WebPagePopupImpl final : public WebPagePopup,
public PageWidgetEventHandler,
@@ -98,12 +99,6 @@ class CORE_EXPORT WebPagePopupImpl final : public WebPagePopup,
LocalDOMWindow* Window();
- // WebWidget implementation.
- WebInputEventResult DispatchBufferedTouchEvents() override;
- void SetCompositorVisible(bool visible) override;
- void UpdateVisualState() override;
- void WillBeginCompositorFrame() override;
-
// WebPagePopup implementation.
gfx::Point PositionRelativeToOwner() override;
WebDocument GetDocument() override;
@@ -111,6 +106,7 @@ class CORE_EXPORT WebPagePopupImpl final : public WebPagePopup,
// PagePopup implementation.
void PostMessageToPopup(const String& message) override;
+ void Update() override;
// PageWidgetEventHandler implementation.
WebInputEventResult HandleKeyEvent(const WebKeyboardEvent&) override;
@@ -119,8 +115,11 @@ class CORE_EXPORT WebPagePopupImpl final : public WebPagePopup,
// WidgetBaseClient overrides:
void DispatchRafAlignedInput(base::TimeTicks frame_time) override;
void BeginMainFrame(base::TimeTicks last_frame_time) override;
+ void RequestNewLayerTreeFrameSink(
+ LayerTreeFrameSinkCallback callback) override;
void RecordTimeToFirstActivePaint(base::TimeDelta duration) override;
void SetSuppressFrameRequestsWorkaroundFor704763Only(bool) final;
+ WebInputEventResult DispatchBufferedTouchEvents() override;
// WebWidget implementation.
// NOTE: The WebWidget may still be used after requesting the popup to be
@@ -128,16 +127,23 @@ class CORE_EXPORT WebPagePopupImpl final : public WebPagePopup,
// immediately. So all methods (outside of initialization) that are part
// of the WebWidget need to check if close has already been initiated (they
// can do so by checking |page_|) and not crash! https://crbug.com/906340
- void SetCompositorHosts(cc::LayerTreeHost*, cc::AnimationHost*) override;
- void BeginFrame(base::TimeTicks last_frame_time) override;
+ void SetCompositorVisible(bool visible) override;
void UpdateLifecycle(WebLifecycleUpdate requested_update,
DocumentUpdateReason reason) override;
void Resize(const WebSize&) override;
- void Close() override;
+ void Close(scoped_refptr<base::SingleThreadTaskRunner> cleanup_runner,
+ base::OnceCallback<void()> cleanup_task) override;
WebInputEventResult HandleInputEvent(const WebCoalescedInputEvent&) override;
void SetFocus(bool) override;
WebURL GetURLForDebugTrace() override;
- WebHitTestResult HitTestResultAt(const gfx::Point&) override { return {}; }
+ WebHitTestResult HitTestResultAt(const gfx::PointF&) override { return {}; }
+ cc::LayerTreeHost* InitializeCompositing(
+ cc::TaskGraphRunner* task_graph_runner,
+ const cc::LayerTreeSettings& settings,
+ std::unique_ptr<cc::UkmRecorderFactory> ukm_recorder_factory) override;
+ scheduler::WebRenderWidgetSchedulingState* RendererWidgetSchedulingState()
+ override;
+ void SetCursor(const ui::Cursor& cursor) override;
// PageWidgetEventHandler functions
WebInputEventResult HandleCharEvent(const WebKeyboardEvent&) override;
@@ -184,6 +190,7 @@ class CORE_EXPORT WebPagePopupImpl final : public WebPagePopup,
base::TimeTicks raf_aligned_input_start_time_;
bool suppress_next_keypress_event_ = false;
+ Persistent<DOMRect> popup_owner_client_rect_;
// Base functionality all widgets have. This is a member as to avoid
// complicated inheritance structures.
diff --git a/chromium/third_party/blink/renderer/core/exported/web_plugin_container_impl.cc b/chromium/third_party/blink/renderer/core/exported/web_plugin_container_impl.cc
index dc8ef5e532a..27ea627f185 100644
--- a/chromium/third_party/blink/renderer/core/exported/web_plugin_container_impl.cc
+++ b/chromium/third_party/blink/renderer/core/exported/web_plugin_container_impl.cc
@@ -32,9 +32,9 @@
#include "third_party/blink/renderer/core/exported/web_plugin_container_impl.h"
#include "build/build_config.h"
+#include "third_party/blink/public/common/input/web_coalesced_input_event.h"
#include "third_party/blink/public/common/input/web_input_event.h"
#include "third_party/blink/public/platform/platform.h"
-#include "third_party/blink/public/platform/web_coalesced_input_event.h"
#include "third_party/blink/public/platform/web_drag_data.h"
#include "third_party/blink/public/platform/web_rect.h"
#include "third_party/blink/public/platform/web_string.h"
@@ -107,7 +107,7 @@
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h"
#include "ui/base/cursor/cursor.h"
-#include "ui/base/mojom/cursor_type.mojom-blink.h"
+#include "ui/base/cursor/mojom/cursor_type.mojom-blink.h"
namespace blink {
@@ -691,7 +691,7 @@ void WebPluginContainerImpl::DidFinishLoading() {
}
void WebPluginContainerImpl::DidFailLoading(const ResourceError& error) {
- web_plugin_->DidFailLoading(error);
+ web_plugin_->DidFailLoading(WebURLError(error));
}
cc::Layer* WebPluginContainerImpl::CcLayer() const {
@@ -809,16 +809,17 @@ void WebPluginContainerImpl::HandleMouseEvent(MouseEvent& event) {
// in this class.
WebMouseEventBuilder transformed_event(parent, element_->GetLayoutObject(),
event);
- if (transformed_event.GetType() == WebInputEvent::kUndefined)
+ if (transformed_event.GetType() == WebInputEvent::Type::kUndefined)
return;
if (event.type() == event_type_names::kMousedown)
FocusPlugin();
ui::Cursor cursor(ui::mojom::blink::CursorType::kPointer);
- if (web_plugin_ && web_plugin_->HandleInputEvent(
- WebCoalescedInputEvent(transformed_event), &cursor) !=
- WebInputEventResult::kNotHandled)
+ if (web_plugin_ &&
+ web_plugin_->HandleInputEvent(
+ WebCoalescedInputEvent(transformed_event, ui::LatencyInfo()),
+ &cursor) != WebInputEventResult::kNotHandled)
event.SetDefaultHandled();
// A windowless plugin can change the cursor in response to a mouse move
@@ -875,15 +876,15 @@ void WebPluginContainerImpl::HandleWheelEvent(WheelEvent& event) {
translated_event.SetPositionInWidget(local_point.X(), local_point.Y());
ui::Cursor dummy_cursor;
- if (web_plugin_->HandleInputEvent(WebCoalescedInputEvent(translated_event),
- &dummy_cursor) !=
- WebInputEventResult::kNotHandled)
+ if (web_plugin_->HandleInputEvent(
+ WebCoalescedInputEvent(translated_event, ui::LatencyInfo()),
+ &dummy_cursor) != WebInputEventResult::kNotHandled)
event.SetDefaultHandled();
}
void WebPluginContainerImpl::HandleKeyboardEvent(KeyboardEvent& event) {
WebKeyboardEventBuilder web_event(event);
- if (web_event.GetType() == WebInputEvent::kUndefined)
+ if (web_event.GetType() == WebInputEvent::Type::kUndefined)
return;
if (HandleCutCopyPasteKeyboardEvent(web_event)) {
@@ -898,17 +899,17 @@ void WebPluginContainerImpl::HandleKeyboardEvent(KeyboardEvent& event) {
web_frame->Client()->HandleCurrentKeyboardEvent();
ui::Cursor dummy_cursor;
- if (web_plugin_->HandleInputEvent(WebCoalescedInputEvent(web_event),
- &dummy_cursor) !=
- WebInputEventResult::kNotHandled) {
+ if (web_plugin_->HandleInputEvent(
+ WebCoalescedInputEvent(web_event, ui::LatencyInfo()),
+ &dummy_cursor) != WebInputEventResult::kNotHandled) {
event.SetDefaultHandled();
}
}
bool WebPluginContainerImpl::HandleCutCopyPasteKeyboardEvent(
const WebKeyboardEvent& event) {
- if (event.GetType() != WebInputEvent::kRawKeyDown &&
- event.GetType() != WebInputEvent::kKeyDown) {
+ if (event.GetType() != WebInputEvent::Type::kRawKeyDown &&
+ event.GetType() != WebInputEvent::Type::kKeyDown) {
return false;
}
@@ -975,7 +976,8 @@ WebTouchEvent WebPluginContainerImpl::TransformTouchEvent(
WebCoalescedInputEvent WebPluginContainerImpl::TransformCoalescedTouchEvent(
const WebCoalescedInputEvent& coalesced_event) {
WebCoalescedInputEvent transformed_event(
- TransformTouchEvent(coalesced_event.Event()), {}, {});
+ TransformTouchEvent(coalesced_event.Event()).Clone(), {}, {},
+ coalesced_event.latency_info());
for (size_t i = 0; i < coalesced_event.CoalescedEventSize(); ++i) {
transformed_event.AddCoalescedEvent(
TransformTouchEvent(coalesced_event.CoalescedEvent(i)));
@@ -1016,9 +1018,9 @@ void WebPluginContainerImpl::HandleTouchEvent(TouchEvent& event) {
}
void WebPluginContainerImpl::HandleGestureEvent(GestureEvent& event) {
- if (event.NativeEvent().GetType() == WebInputEvent::kUndefined)
+ if (event.NativeEvent().GetType() == WebInputEvent::Type::kUndefined)
return;
- if (event.NativeEvent().GetType() == WebInputEvent::kGestureTapDown)
+ if (event.NativeEvent().GetType() == WebInputEvent::Type::kGestureTapDown)
FocusPlugin();
// Take a copy of the event and translate it into the coordinate
@@ -1033,9 +1035,9 @@ void WebPluginContainerImpl::HandleGestureEvent(GestureEvent& event) {
translated_event.SetPositionInWidget(local_point);
ui::Cursor dummy_cursor;
- if (web_plugin_->HandleInputEvent(WebCoalescedInputEvent(translated_event),
- &dummy_cursor) !=
- WebInputEventResult::kNotHandled) {
+ if (web_plugin_->HandleInputEvent(
+ WebCoalescedInputEvent(translated_event, ui::LatencyInfo()),
+ &dummy_cursor) != WebInputEventResult::kNotHandled) {
event.SetDefaultHandled();
return;
}
@@ -1046,13 +1048,13 @@ void WebPluginContainerImpl::HandleGestureEvent(GestureEvent& event) {
void WebPluginContainerImpl::SynthesizeMouseEventIfPossible(TouchEvent& event) {
WebMouseEventBuilder web_event(ParentFrameView(), element_->GetLayoutObject(),
event);
- if (web_event.GetType() == WebInputEvent::kUndefined)
+ if (web_event.GetType() == WebInputEvent::Type::kUndefined)
return;
ui::Cursor dummy_cursor;
- if (web_plugin_->HandleInputEvent(WebCoalescedInputEvent(web_event),
- &dummy_cursor) !=
- WebInputEventResult::kNotHandled)
+ if (web_plugin_->HandleInputEvent(
+ WebCoalescedInputEvent(web_event, ui::LatencyInfo()),
+ &dummy_cursor) != WebInputEventResult::kNotHandled)
event.SetDefaultHandled();
}
diff --git a/chromium/third_party/blink/renderer/core/exported/web_plugin_container_impl.h b/chromium/third_party/blink/renderer/core/exported/web_plugin_container_impl.h
index 3d8e13cd55f..8ef5dc8600d 100644
--- a/chromium/third_party/blink/renderer/core/exported/web_plugin_container_impl.h
+++ b/chromium/third_party/blink/renderer/core/exported/web_plugin_container_impl.h
@@ -33,9 +33,9 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_EXPORTED_WEB_PLUGIN_CONTAINER_IMPL_H_
#include "base/memory/scoped_refptr.h"
+#include "third_party/blink/public/common/input/web_coalesced_input_event.h"
#include "third_party/blink/public/common/input/web_touch_event.h"
#include "third_party/blink/public/mojom/input/focus_type.mojom-blink-forward.h"
-#include "third_party/blink/public/platform/web_coalesced_input_event.h"
#include "third_party/blink/public/web/web_plugin_container.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.h"
diff --git a/chromium/third_party/blink/renderer/core/exported/web_plugin_container_test.cc b/chromium/third_party/blink/renderer/core/exported/web_plugin_container_test.cc
index 67a0066eef8..9fe809420be 100644
--- a/chromium/third_party/blink/renderer/core/exported/web_plugin_container_test.cc
+++ b/chromium/third_party/blink/renderer/core/exported/web_plugin_container_test.cc
@@ -36,10 +36,10 @@
#include "build/build_config.h"
#include "cc/layers/layer.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/common/frame/frame_owner_element_type.h"
+#include "third_party/blink/public/common/input/web_coalesced_input_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/platform/web_coalesced_input_event.h"
+#include "third_party/blink/public/mojom/frame/frame_owner_element_type.mojom-blink.h"
#include "third_party/blink/public/platform/web_url_loader_mock_factory.h"
#include "third_party/blink/public/web/web_document.h"
#include "third_party/blink/public/web/web_element.h"
@@ -199,13 +199,14 @@ class TestPluginWithEditableText : public FakeWebPlugin {
};
class TestPluginWebFrameClient : public frame_test_helpers::TestWebFrameClient {
- WebLocalFrame* CreateChildFrame(WebLocalFrame* parent,
- WebTreeScopeType scope,
- const WebString& name,
- const WebString& fallback_name,
- const FramePolicy&,
- const WebFrameOwnerProperties&,
- FrameOwnerElementType owner_type) override {
+ WebLocalFrame* CreateChildFrame(
+ WebLocalFrame* parent,
+ mojom::blink::TreeScopeType scope,
+ const WebString& name,
+ const WebString& fallback_name,
+ const FramePolicy&,
+ const WebFrameOwnerProperties&,
+ mojom::blink::FrameOwnerElementType owner_type) override {
return CreateLocalChild(*parent, scope,
std::make_unique<TestPluginWebFrameClient>());
}
@@ -276,7 +277,7 @@ void CreateAndHandleKeyboardEvent(WebElement* plugin_container_one_element,
WebInputEvent::Modifiers modifier_key,
int key_code) {
WebKeyboardEvent web_keyboard_event(
- WebInputEvent::kRawKeyDown, modifier_key,
+ WebInputEvent::Type::kRawKeyDown, modifier_key,
WebInputEvent::GetStaticTimeStampForTests());
web_keyboard_event.windows_key_code = key_code;
KeyboardEvent* key_event = KeyboardEvent::Create(web_keyboard_event, nullptr);
@@ -287,11 +288,12 @@ void CreateAndHandleKeyboardEvent(WebElement* plugin_container_one_element,
void ExecuteContextMenuCommand(WebViewImpl* web_view,
const WebString& command_name) {
auto event = frame_test_helpers::CreateMouseEvent(
- WebMouseEvent::kMouseDown, WebMouseEvent::Button::kRight,
+ WebMouseEvent::Type::kMouseDown, WebMouseEvent::Button::kRight,
IntPoint(30, 30), 0);
event.click_count = 1;
- web_view->MainFrameWidget()->HandleInputEvent(WebCoalescedInputEvent(event));
+ web_view->MainFrameWidget()->HandleInputEvent(
+ WebCoalescedInputEvent(event, ui::LatencyInfo()));
EXPECT_TRUE(
web_view->MainFrame()->ToWebLocalFrame()->ExecuteCommand(command_name));
}
@@ -406,13 +408,14 @@ TEST_F(WebPluginContainerTest, CopyFromContextMenu) {
ClearClipboardBuffer(*local_frame);
auto event = frame_test_helpers::CreateMouseEvent(
- WebMouseEvent::kMouseDown, WebMouseEvent::Button::kRight,
+ WebMouseEvent::Type::kMouseDown, WebMouseEvent::Button::kRight,
IntPoint(30, 30), 0);
event.click_count = 1;
// Now, let's try a more complex scenario:
// 1) open the context menu. This will focus the plugin.
- web_view->MainFrameWidget()->HandleInputEvent(WebCoalescedInputEvent(event));
+ web_view->MainFrameWidget()->HandleInputEvent(
+ WebCoalescedInputEvent(event, ui::LatencyInfo()));
// 2) document blurs the plugin, because it can.
web_view->FocusedElement()->blur();
// 3) Copy should still operate on the context node, even though the focus had
@@ -642,7 +645,7 @@ class EventTestPlugin : public FakeWebPlugin {
public:
explicit EventTestPlugin(const WebPluginParams& params)
: FakeWebPlugin(params),
- last_event_type_(WebInputEvent::kUndefined),
+ last_event_type_(WebInputEvent::Type::kUndefined),
last_event_modifiers_(WebInputEvent::kNoModifiers) {}
WebInputEventResult HandleInputEvent(
@@ -653,7 +656,7 @@ class EventTestPlugin : public FakeWebPlugin {
last_event_type_ = event.GetType();
last_event_modifiers_ = event.GetModifiers();
if (WebInputEvent::IsMouseEventType(event.GetType()) ||
- event.GetType() == WebInputEvent::kMouseWheel) {
+ event.GetType() == WebInputEvent::Type::kMouseWheel) {
const WebMouseEvent& mouse_event =
static_cast<const WebMouseEvent&>(event);
last_event_location_ = IntPoint(mouse_event.PositionInWidget().x(),
@@ -678,7 +681,9 @@ class EventTestPlugin : public FakeWebPlugin {
int GetLastEventModifiers() { return last_event_modifiers_; }
- void ClearLastEventType() { last_event_type_ = WebInputEvent::kUndefined; }
+ void ClearLastEventType() {
+ last_event_type_ = WebInputEvent::Type::kUndefined;
+ }
size_t GetCoalescedEventCount() { return coalesced_event_count_; }
@@ -708,7 +713,7 @@ TEST_F(WebPluginContainerTest, GestureLongPressReachesPlugin) {
->Plugin();
EventTestPlugin* test_plugin = static_cast<EventTestPlugin*>(plugin);
- WebGestureEvent event(WebInputEvent::kGestureLongPress,
+ WebGestureEvent event(WebInputEvent::Type::kGestureLongPress,
WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests(),
WebGestureDevice::kTouchscreen);
@@ -717,10 +722,12 @@ TEST_F(WebPluginContainerTest, GestureLongPressReachesPlugin) {
// plugin doesn't receive it.
event.SetPositionInWidget(gfx::PointF());
- web_view->MainFrameWidget()->HandleInputEvent(WebCoalescedInputEvent(event));
+ web_view->MainFrameWidget()->HandleInputEvent(
+ WebCoalescedInputEvent(event, ui::LatencyInfo()));
RunPendingTasks();
- EXPECT_EQ(WebInputEvent::kUndefined, test_plugin->GetLastInputEventType());
+ EXPECT_EQ(WebInputEvent::Type::kUndefined,
+ test_plugin->GetLastInputEventType());
// Next, send an event that does hit the plugin, and verify it does receive
// it.
@@ -728,10 +735,11 @@ TEST_F(WebPluginContainerTest, GestureLongPressReachesPlugin) {
event.SetPositionInWidget(
gfx::PointF(rect.x + rect.width / 2, rect.y + rect.height / 2));
- web_view->MainFrameWidget()->HandleInputEvent(WebCoalescedInputEvent(event));
+ web_view->MainFrameWidget()->HandleInputEvent(
+ WebCoalescedInputEvent(event, ui::LatencyInfo()));
RunPendingTasks();
- EXPECT_EQ(WebInputEvent::kGestureLongPress,
+ EXPECT_EQ(WebInputEvent::Type::kGestureLongPress,
test_plugin->GetLastInputEventType());
}
@@ -753,17 +761,19 @@ TEST_F(WebPluginContainerTest, MouseEventButtons) {
EventTestPlugin* test_plugin = static_cast<EventTestPlugin*>(plugin);
WebMouseEvent event = frame_test_helpers::CreateMouseEvent(
- WebMouseEvent::kMouseMove, WebMouseEvent::Button::kNoButton,
+ WebMouseEvent::Type::kMouseMove, WebMouseEvent::Button::kNoButton,
IntPoint(30, 30),
WebInputEvent::kMiddleButtonDown | WebInputEvent::kShiftKey);
WebRect rect = plugin_container_one_element.BoundsInViewport();
event.SetPositionInWidget(rect.x + rect.width / 2, rect.y + rect.height / 2);
- web_view->MainFrameWidget()->HandleInputEvent(WebCoalescedInputEvent(event));
+ web_view->MainFrameWidget()->HandleInputEvent(
+ WebCoalescedInputEvent(event, ui::LatencyInfo()));
RunPendingTasks();
- EXPECT_EQ(WebInputEvent::kMouseMove, test_plugin->GetLastInputEventType());
+ EXPECT_EQ(WebInputEvent::Type::kMouseMove,
+ test_plugin->GetLastInputEventType());
EXPECT_EQ(WebInputEvent::kMiddleButtonDown | WebInputEvent::kShiftKey,
test_plugin->GetLastEventModifiers());
}
@@ -785,17 +795,19 @@ TEST_F(WebPluginContainerTest, MouseWheelEventTranslated) {
->Plugin();
EventTestPlugin* test_plugin = static_cast<EventTestPlugin*>(plugin);
- WebMouseWheelEvent event(WebInputEvent::kMouseWheel,
+ WebMouseWheelEvent event(WebInputEvent::Type::kMouseWheel,
WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests());
WebRect rect = plugin_container_one_element.BoundsInViewport();
event.SetPositionInWidget(rect.x + rect.width / 2, rect.y + rect.height / 2);
- web_view->MainFrameWidget()->HandleInputEvent(WebCoalescedInputEvent(event));
+ web_view->MainFrameWidget()->HandleInputEvent(
+ WebCoalescedInputEvent(event, ui::LatencyInfo()));
RunPendingTasks();
- EXPECT_EQ(WebInputEvent::kMouseWheel, test_plugin->GetLastInputEventType());
+ EXPECT_EQ(WebInputEvent::Type::kMouseWheel,
+ test_plugin->GetLastInputEventType());
EXPECT_EQ(rect.width / 2, test_plugin->GetLastEventLocation().X());
EXPECT_EQ(rect.height / 2, test_plugin->GetLastEventLocation().Y());
}
@@ -824,7 +836,7 @@ TEST_F(WebPluginContainerTest, TouchEventScrolled) {
WebRect rect = plugin_container_one_element.BoundsInViewport();
WebPointerEvent event(
- WebInputEvent::kPointerDown,
+ WebInputEvent::Type::kPointerDown,
WebPointerProperties(
1, WebPointerProperties::PointerType::kTouch,
WebPointerProperties::Button::kLeft,
@@ -832,11 +844,13 @@ TEST_F(WebPluginContainerTest, TouchEventScrolled) {
gfx::PointF(rect.x + rect.width / 2, rect.y + rect.height / 2)),
1.0f, 1.0f);
- web_view->MainFrameWidget()->HandleInputEvent(WebCoalescedInputEvent(event));
+ web_view->MainFrameWidget()->HandleInputEvent(
+ WebCoalescedInputEvent(event, ui::LatencyInfo()));
web_view->MainFrameWidget()->DispatchBufferedTouchEvents();
RunPendingTasks();
- EXPECT_EQ(WebInputEvent::kTouchStart, test_plugin->GetLastInputEventType());
+ EXPECT_EQ(WebInputEvent::Type::kTouchStart,
+ test_plugin->GetLastInputEventType());
EXPECT_EQ(rect.width / 2, test_plugin->GetLastEventLocation().X());
EXPECT_EQ(rect.height / 2, test_plugin->GetLastEventLocation().Y());
}
@@ -866,7 +880,7 @@ TEST_F(WebPluginContainerTest, TouchEventScrolledWithCoalescedTouches) {
{
WebRect rect = plugin_container_one_element.BoundsInViewport();
WebPointerEvent event(
- WebInputEvent::kPointerDown,
+ WebInputEvent::Type::kPointerDown,
WebPointerProperties(
1, WebPointerProperties::PointerType::kTouch,
WebPointerProperties::Button::kLeft,
@@ -874,7 +888,7 @@ TEST_F(WebPluginContainerTest, TouchEventScrolledWithCoalescedTouches) {
gfx::PointF(rect.x + rect.width / 2, rect.y + rect.height / 2)),
1.0f, 1.0f);
- WebCoalescedInputEvent coalesced_event(event);
+ WebCoalescedInputEvent coalesced_event(event, ui::LatencyInfo());
web_view->MainFrameWidget()->HandleInputEvent(coalesced_event);
web_view->MainFrameWidget()->DispatchBufferedTouchEvents();
@@ -882,7 +896,8 @@ TEST_F(WebPluginContainerTest, TouchEventScrolledWithCoalescedTouches) {
EXPECT_EQ(static_cast<const size_t>(1),
test_plugin->GetCoalescedEventCount());
- EXPECT_EQ(WebInputEvent::kTouchStart, test_plugin->GetLastInputEventType());
+ EXPECT_EQ(WebInputEvent::Type::kTouchStart,
+ test_plugin->GetLastInputEventType());
EXPECT_EQ(rect.width / 2, test_plugin->GetLastEventLocation().X());
EXPECT_EQ(rect.height / 2, test_plugin->GetLastEventLocation().Y());
}
@@ -890,7 +905,7 @@ TEST_F(WebPluginContainerTest, TouchEventScrolledWithCoalescedTouches) {
{
WebRect rect = plugin_container_one_element.BoundsInViewport();
WebPointerEvent event1(
- WebInputEvent::kPointerMove,
+ WebInputEvent::Type::kPointerMove,
WebPointerProperties(1, WebPointerProperties::PointerType::kTouch,
WebPointerProperties::Button::kLeft,
gfx::PointF(rect.x + rect.width / 2 + 1,
@@ -899,10 +914,10 @@ TEST_F(WebPluginContainerTest, TouchEventScrolledWithCoalescedTouches) {
rect.y + rect.height / 2 + 1)),
1.0f, 1.0f);
- WebCoalescedInputEvent coalesced_event(event1);
+ WebCoalescedInputEvent coalesced_event(event1, ui::LatencyInfo());
WebPointerEvent event2(
- WebInputEvent::kPointerMove,
+ WebInputEvent::Type::kPointerMove,
WebPointerProperties(1, WebPointerProperties::PointerType::kTouch,
WebPointerProperties::Button::kLeft,
gfx::PointF(rect.x + rect.width / 2 + 2,
@@ -911,7 +926,7 @@ TEST_F(WebPluginContainerTest, TouchEventScrolledWithCoalescedTouches) {
rect.y + rect.height / 2 + 2)),
1.0f, 1.0f);
WebPointerEvent event3(
- WebInputEvent::kPointerMove,
+ WebInputEvent::Type::kPointerMove,
WebPointerProperties(1, WebPointerProperties::PointerType::kTouch,
WebPointerProperties::Button::kLeft,
gfx::PointF(rect.x + rect.width / 2 + 3,
@@ -929,7 +944,8 @@ TEST_F(WebPluginContainerTest, TouchEventScrolledWithCoalescedTouches) {
EXPECT_EQ(static_cast<const size_t>(3),
test_plugin->GetCoalescedEventCount());
- EXPECT_EQ(WebInputEvent::kTouchMove, test_plugin->GetLastInputEventType());
+ EXPECT_EQ(WebInputEvent::Type::kTouchMove,
+ test_plugin->GetLastInputEventType());
EXPECT_EQ(rect.width / 2 + 1, test_plugin->GetLastEventLocation().X());
EXPECT_EQ(rect.height / 2 + 1, test_plugin->GetLastEventLocation().Y());
}
@@ -957,17 +973,19 @@ TEST_F(WebPluginContainerTest, MouseWheelEventScrolled) {
->Plugin();
EventTestPlugin* test_plugin = static_cast<EventTestPlugin*>(plugin);
- WebMouseWheelEvent event(WebInputEvent::kMouseWheel,
+ WebMouseWheelEvent event(WebInputEvent::Type::kMouseWheel,
WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests());
WebRect rect = plugin_container_one_element.BoundsInViewport();
event.SetPositionInWidget(rect.x + rect.width / 2, rect.y + rect.height / 2);
- web_view->MainFrameWidget()->HandleInputEvent(WebCoalescedInputEvent(event));
+ web_view->MainFrameWidget()->HandleInputEvent(
+ WebCoalescedInputEvent(event, ui::LatencyInfo()));
RunPendingTasks();
- EXPECT_EQ(WebInputEvent::kMouseWheel, test_plugin->GetLastInputEventType());
+ EXPECT_EQ(WebInputEvent::Type::kMouseWheel,
+ test_plugin->GetLastInputEventType());
EXPECT_EQ(rect.width / 2, test_plugin->GetLastEventLocation().X());
EXPECT_EQ(rect.height / 2, test_plugin->GetLastEventLocation().Y());
}
@@ -994,16 +1012,19 @@ TEST_F(WebPluginContainerTest, MouseEventScrolled) {
->Plugin();
EventTestPlugin* test_plugin = static_cast<EventTestPlugin*>(plugin);
- WebMouseEvent event(WebInputEvent::kMouseMove, WebInputEvent::kNoModifiers,
+ WebMouseEvent event(WebInputEvent::Type::kMouseMove,
+ WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests());
WebRect rect = plugin_container_one_element.BoundsInViewport();
event.SetPositionInWidget(rect.x + rect.width / 2, rect.y + rect.height / 2);
- web_view->MainFrameWidget()->HandleInputEvent(WebCoalescedInputEvent(event));
+ web_view->MainFrameWidget()->HandleInputEvent(
+ WebCoalescedInputEvent(event, ui::LatencyInfo()));
RunPendingTasks();
- EXPECT_EQ(WebInputEvent::kMouseMove, test_plugin->GetLastInputEventType());
+ EXPECT_EQ(WebInputEvent::Type::kMouseMove,
+ test_plugin->GetLastInputEventType());
EXPECT_EQ(rect.width / 2, test_plugin->GetLastEventLocation().X());
EXPECT_EQ(rect.height / 2, test_plugin->GetLastEventLocation().Y());
}
@@ -1033,18 +1054,21 @@ TEST_F(WebPluginContainerTest, MouseEventZoomed) {
->Plugin();
EventTestPlugin* test_plugin = static_cast<EventTestPlugin*>(plugin);
- WebMouseEvent event(WebInputEvent::kMouseMove, WebInputEvent::kNoModifiers,
+ WebMouseEvent event(WebInputEvent::Type::kMouseMove,
+ WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests());
WebRect rect = plugin_container_one_element.BoundsInViewport();
event.SetPositionInWidget(rect.x + rect.width / 2, rect.y + rect.height / 2);
- web_view->MainFrameWidget()->HandleInputEvent(WebCoalescedInputEvent(event));
+ web_view->MainFrameWidget()->HandleInputEvent(
+ WebCoalescedInputEvent(event, ui::LatencyInfo()));
RunPendingTasks();
// rect.width/height divided by 4 because the rect is in viewport bounds and
// there is a scale of 2 set.
- EXPECT_EQ(WebInputEvent::kMouseMove, test_plugin->GetLastInputEventType());
+ EXPECT_EQ(WebInputEvent::Type::kMouseMove,
+ test_plugin->GetLastInputEventType());
EXPECT_EQ(rect.width / 4, test_plugin->GetLastEventLocation().X());
EXPECT_EQ(rect.height / 4, test_plugin->GetLastEventLocation().Y());
}
@@ -1074,19 +1098,21 @@ TEST_F(WebPluginContainerTest, MouseWheelEventZoomed) {
->Plugin();
EventTestPlugin* test_plugin = static_cast<EventTestPlugin*>(plugin);
- WebMouseWheelEvent event(WebInputEvent::kMouseWheel,
+ WebMouseWheelEvent event(WebInputEvent::Type::kMouseWheel,
WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests());
WebRect rect = plugin_container_one_element.BoundsInViewport();
event.SetPositionInWidget(rect.x + rect.width / 2, rect.y + rect.height / 2);
- web_view->MainFrameWidget()->HandleInputEvent(WebCoalescedInputEvent(event));
+ web_view->MainFrameWidget()->HandleInputEvent(
+ WebCoalescedInputEvent(event, ui::LatencyInfo()));
RunPendingTasks();
// rect.width/height divided by 4 because the rect is in viewport bounds and
// there is a scale of 2 set.
- EXPECT_EQ(WebInputEvent::kMouseWheel, test_plugin->GetLastInputEventType());
+ EXPECT_EQ(WebInputEvent::Type::kMouseWheel,
+ test_plugin->GetLastInputEventType());
EXPECT_EQ(rect.width / 4, test_plugin->GetLastEventLocation().X());
EXPECT_EQ(rect.height / 4, test_plugin->GetLastEventLocation().Y());
}
@@ -1118,7 +1144,7 @@ TEST_F(WebPluginContainerTest, TouchEventZoomed) {
WebRect rect = plugin_container_one_element.BoundsInViewport();
WebPointerEvent event(
- WebInputEvent::kPointerDown,
+ WebInputEvent::Type::kPointerDown,
WebPointerProperties(
1, WebPointerProperties::PointerType::kTouch,
WebPointerProperties::Button::kLeft,
@@ -1126,13 +1152,15 @@ TEST_F(WebPluginContainerTest, TouchEventZoomed) {
gfx::PointF(rect.x + rect.width / 2, rect.y + rect.height / 2)),
1.0f, 1.0f);
- web_view->MainFrameWidget()->HandleInputEvent(WebCoalescedInputEvent(event));
+ web_view->MainFrameWidget()->HandleInputEvent(
+ WebCoalescedInputEvent(event, ui::LatencyInfo()));
web_view->MainFrameWidget()->DispatchBufferedTouchEvents();
RunPendingTasks();
// rect.width/height divided by 4 because the rect is in viewport bounds and
// there is a scale of 2 set.
- EXPECT_EQ(WebInputEvent::kTouchStart, test_plugin->GetLastInputEventType());
+ EXPECT_EQ(WebInputEvent::Type::kTouchStart,
+ test_plugin->GetLastInputEventType());
EXPECT_EQ(rect.width / 4, test_plugin->GetLastEventLocation().X());
EXPECT_EQ(rect.height / 4, test_plugin->GetLastEventLocation().Y());
}
diff --git a/chromium/third_party/blink/renderer/core/exported/web_remote_frame_impl.cc b/chromium/third_party/blink/renderer/core/exported/web_remote_frame_impl.cc
index 56ec1b3c20e..733203da2de 100644
--- a/chromium/third_party/blink/renderer/core/exported/web_remote_frame_impl.cc
+++ b/chromium/third_party/blink/renderer/core/exported/web_remote_frame_impl.cc
@@ -7,15 +7,14 @@
#include <utility>
#include "third_party/blink/public/common/feature_policy/feature_policy.h"
+#include "third_party/blink/public/mojom/frame/tree_scope_type.mojom-blink.h"
#include "third_party/blink/public/mojom/security_context/insecure_request_policy.mojom-blink.h"
#include "third_party/blink/public/platform/web_float_rect.h"
-#include "third_party/blink/public/platform/web_intrinsic_sizing_info.h"
#include "third_party/blink/public/platform/web_rect.h"
#include "third_party/blink/public/web/web_document.h"
#include "third_party/blink/public/web/web_frame_owner_properties.h"
#include "third_party/blink/public/web/web_performance.h"
#include "third_party/blink/public/web/web_range.h"
-#include "third_party/blink/public/web/web_tree_scope_type.h"
#include "third_party/blink/renderer/bindings/core/v8/window_proxy.h"
#include "third_party/blink/renderer/core/execution_context/remote_security_context.h"
#include "third_party/blink/renderer/core/execution_context/security_context.h"
@@ -45,12 +44,14 @@
namespace blink {
WebRemoteFrame* WebRemoteFrame::Create(
- WebTreeScopeType scope,
+ mojom::blink::TreeScopeType scope,
WebRemoteFrameClient* client,
InterfaceRegistry* interface_registry,
- AssociatedInterfaceProvider* associated_interface_provider) {
+ AssociatedInterfaceProvider* associated_interface_provider,
+ const base::UnguessableToken& frame_token) {
return MakeGarbageCollected<WebRemoteFrameImpl>(
- scope, client, interface_registry, associated_interface_provider);
+ scope, client, interface_registry, associated_interface_provider,
+ frame_token);
}
WebRemoteFrame* WebRemoteFrame::CreateMainFrame(
@@ -58,21 +59,23 @@ WebRemoteFrame* WebRemoteFrame::CreateMainFrame(
WebRemoteFrameClient* client,
InterfaceRegistry* interface_registry,
AssociatedInterfaceProvider* associated_interface_provider,
+ const base::UnguessableToken& frame_token,
WebFrame* opener) {
return WebRemoteFrameImpl::CreateMainFrame(
web_view, client, interface_registry, associated_interface_provider,
- opener);
+ frame_token, opener);
}
WebRemoteFrame* WebRemoteFrame::CreateForPortal(
- WebTreeScopeType scope,
+ mojom::blink::TreeScopeType scope,
WebRemoteFrameClient* client,
InterfaceRegistry* interface_registry,
AssociatedInterfaceProvider* associated_interface_provider,
+ const base::UnguessableToken& frame_token,
const WebElement& portal_element) {
return WebRemoteFrameImpl::CreateForPortal(scope, client, interface_registry,
associated_interface_provider,
- portal_element);
+ frame_token, portal_element);
}
WebRemoteFrameImpl* WebRemoteFrameImpl::CreateMainFrame(
@@ -80,10 +83,11 @@ WebRemoteFrameImpl* WebRemoteFrameImpl::CreateMainFrame(
WebRemoteFrameClient* client,
InterfaceRegistry* interface_registry,
AssociatedInterfaceProvider* associated_interface_provider,
+ const base::UnguessableToken& frame_token,
WebFrame* opener) {
WebRemoteFrameImpl* frame = MakeGarbageCollected<WebRemoteFrameImpl>(
- WebTreeScopeType::kDocument, client, interface_registry,
- associated_interface_provider);
+ mojom::blink::TreeScopeType::kDocument, client, interface_registry,
+ associated_interface_provider, frame_token);
frame->SetOpener(opener);
Page& page = *static_cast<WebViewImpl*>(web_view)->GetPage();
// It would be nice to DCHECK that the main frame is not set yet here.
@@ -101,13 +105,15 @@ WebRemoteFrameImpl* WebRemoteFrameImpl::CreateMainFrame(
}
WebRemoteFrameImpl* WebRemoteFrameImpl::CreateForPortal(
- WebTreeScopeType scope,
+ mojom::blink::TreeScopeType scope,
WebRemoteFrameClient* client,
InterfaceRegistry* interface_registry,
AssociatedInterfaceProvider* associated_interface_provider,
+ const base::UnguessableToken& frame_token,
const WebElement& portal_element) {
auto* frame = MakeGarbageCollected<WebRemoteFrameImpl>(
- scope, client, interface_registry, associated_interface_provider);
+ scope, client, interface_registry, associated_interface_provider,
+ frame_token);
Element* element = portal_element;
DCHECK(element->HasTagName(html_names::kPortalTag));
@@ -159,23 +165,20 @@ WebView* WebRemoteFrameImpl::View() const {
return GetFrame()->GetPage()->GetChromeClient().GetWebView();
}
-void WebRemoteFrameImpl::StopLoading() {
- // TODO(dcheng,japhet): Calling this method should stop loads
- // in all subframes, both remote and local.
-}
-
WebLocalFrame* WebRemoteFrameImpl::CreateLocalChild(
- WebTreeScopeType scope,
+ mojom::blink::TreeScopeType scope,
const WebString& name,
const FramePolicy& frame_policy,
WebLocalFrameClient* client,
blink::InterfaceRegistry* interface_registry,
WebFrame* previous_sibling,
const WebFrameOwnerProperties& frame_owner_properties,
- FrameOwnerElementType frame_owner_element_type,
+ mojom::blink::FrameOwnerElementType frame_owner_element_type,
+ const base::UnguessableToken& frame_token,
WebFrame* opener) {
auto* child = MakeGarbageCollected<WebLocalFrameImpl>(
- util::PassKey<WebRemoteFrameImpl>(), scope, client, interface_registry);
+ util::PassKey<WebRemoteFrameImpl>(), scope, client, interface_registry,
+ frame_token);
child->SetOpener(opener);
InsertAfter(child, previous_sibling);
auto* owner = MakeGarbageCollected<RemoteFrameOwner>(
@@ -200,23 +203,25 @@ void WebRemoteFrameImpl::InitializeCoreFrame(
const AtomicString& name,
WindowAgentFactory* window_agent_factory) {
SetCoreFrame(MakeGarbageCollected<RemoteFrame>(
- frame_client_.Get(), page, owner, window_agent_factory,
+ frame_client_.Get(), page, owner, GetFrameToken(), window_agent_factory,
interface_registry_, associated_interface_provider_));
GetFrame()->CreateView();
frame_->Tree().SetName(name);
}
WebRemoteFrame* WebRemoteFrameImpl::CreateRemoteChild(
- WebTreeScopeType scope,
+ mojom::blink::TreeScopeType scope,
const WebString& name,
const FramePolicy& frame_policy,
- FrameOwnerElementType frame_owner_element_type,
+ mojom::blink::FrameOwnerElementType frame_owner_element_type,
WebRemoteFrameClient* client,
blink::InterfaceRegistry* interface_registry,
AssociatedInterfaceProvider* associated_interface_provider,
+ const base::UnguessableToken& frame_token,
WebFrame* opener) {
auto* child = MakeGarbageCollected<WebRemoteFrameImpl>(
- scope, client, interface_registry, associated_interface_provider);
+ scope, client, interface_registry, associated_interface_provider,
+ frame_token);
child->SetOpener(opener);
AppendChild(child);
auto* owner = MakeGarbageCollected<RemoteFrameOwner>(
@@ -261,7 +266,7 @@ void WebRemoteFrameImpl::SetReplicatedOrigin(
}
void WebRemoteFrameImpl::SetReplicatedSandboxFlags(
- mojom::blink::WebSandboxFlags flags) {
+ network::mojom::blink::WebSandboxFlags flags) {
DCHECK(GetFrame());
GetFrame()->SetReplicatedSandboxFlags(flags);
}
@@ -346,11 +351,12 @@ WebRect WebRemoteFrameImpl::GetCompositingRect() {
}
WebRemoteFrameImpl::WebRemoteFrameImpl(
- WebTreeScopeType scope,
+ mojom::blink::TreeScopeType scope,
WebRemoteFrameClient* client,
InterfaceRegistry* interface_registry,
- AssociatedInterfaceProvider* associated_interface_provider)
- : WebRemoteFrame(scope),
+ AssociatedInterfaceProvider* associated_interface_provider,
+ const base::UnguessableToken& frame_token)
+ : WebRemoteFrame(scope, frame_token),
client_(client),
frame_client_(MakeGarbageCollected<RemoteFrameClientImpl>(this)),
interface_registry_(interface_registry),
diff --git a/chromium/third_party/blink/renderer/core/exported/web_remote_frame_impl.h b/chromium/third_party/blink/renderer/core/exported/web_remote_frame_impl.h
index defdadc82b4..e4ad3dd92ca 100644
--- a/chromium/third_party/blink/renderer/core/exported/web_remote_frame_impl.h
+++ b/chromium/third_party/blink/renderer/core/exported/web_remote_frame_impl.h
@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_EXPORTED_WEB_REMOTE_FRAME_IMPL_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_EXPORTED_WEB_REMOTE_FRAME_IMPL_H_
+#include "third_party/blink/public/mojom/frame/tree_scope_type.mojom-blink.h"
#include "third_party/blink/public/mojom/frame/user_activation_update_types.mojom-blink-forward.h"
#include "third_party/blink/public/mojom/security_context/insecure_request_policy.mojom-blink-forward.h"
#include "third_party/blink/public/web/web_remote_frame.h"
@@ -32,45 +33,51 @@ class CORE_EXPORT WebRemoteFrameImpl final
: public GarbageCollected<WebRemoteFrameImpl>,
public WebRemoteFrame {
public:
- static WebRemoteFrameImpl* CreateMainFrame(WebView*,
- WebRemoteFrameClient*,
- InterfaceRegistry*,
- AssociatedInterfaceProvider*,
- WebFrame* opener);
- static WebRemoteFrameImpl* CreateForPortal(WebTreeScopeType,
- WebRemoteFrameClient*,
- InterfaceRegistry*,
- AssociatedInterfaceProvider*,
- const WebElement& portal_element);
-
- WebRemoteFrameImpl(WebTreeScopeType,
+ static WebRemoteFrameImpl* CreateMainFrame(
+ WebView*,
+ WebRemoteFrameClient*,
+ InterfaceRegistry*,
+ AssociatedInterfaceProvider*,
+ const base::UnguessableToken& frame_token,
+ WebFrame* opener);
+ static WebRemoteFrameImpl* CreateForPortal(
+ mojom::blink::TreeScopeType,
+ WebRemoteFrameClient*,
+ InterfaceRegistry*,
+ AssociatedInterfaceProvider*,
+ const base::UnguessableToken& frame_token,
+ const WebElement& portal_element);
+
+ WebRemoteFrameImpl(mojom::blink::TreeScopeType,
WebRemoteFrameClient*,
InterfaceRegistry*,
- AssociatedInterfaceProvider*);
+ AssociatedInterfaceProvider*,
+ const base::UnguessableToken& frame_token);
~WebRemoteFrameImpl() override;
// WebFrame methods:
void Close() override;
WebView* View() const override;
- void StopLoading() override;
// WebRemoteFrame methods:
- WebLocalFrame* CreateLocalChild(WebTreeScopeType,
+ WebLocalFrame* CreateLocalChild(mojom::blink::TreeScopeType,
const WebString& name,
const FramePolicy&,
WebLocalFrameClient*,
blink::InterfaceRegistry*,
WebFrame* previous_sibling,
const WebFrameOwnerProperties&,
- FrameOwnerElementType,
+ mojom::FrameOwnerElementType,
+ const base::UnguessableToken& frame_token,
WebFrame* opener) override;
- WebRemoteFrame* CreateRemoteChild(WebTreeScopeType,
+ WebRemoteFrame* CreateRemoteChild(mojom::blink::TreeScopeType,
const WebString& name,
const FramePolicy&,
- FrameOwnerElementType,
+ mojom::FrameOwnerElementType,
WebRemoteFrameClient*,
blink::InterfaceRegistry*,
AssociatedInterfaceProvider*,
+ const base::UnguessableToken& frame_token,
WebFrame* opener) override;
void SetCcLayer(cc::Layer*,
bool prevent_contents_opaque_changes,
@@ -78,7 +85,8 @@ class CORE_EXPORT WebRemoteFrameImpl final
void SetReplicatedOrigin(
const WebSecurityOrigin&,
bool is_potentially_trustworthy_opaque_origin) override;
- void SetReplicatedSandboxFlags(mojom::blink::WebSandboxFlags) override;
+ void SetReplicatedSandboxFlags(
+ network::mojom::blink::WebSandboxFlags) override;
void SetReplicatedName(const WebString&) override;
void SetReplicatedFeaturePolicyHeaderAndOpenerPolicies(
const ParsedFeaturePolicy& parsed_header,
diff --git a/chromium/third_party/blink/renderer/core/exported/web_scoped_window_focus_allowed_indicator.cc b/chromium/third_party/blink/renderer/core/exported/web_scoped_window_focus_allowed_indicator.cc
index 549eef50079..7dd9876c9d1 100644
--- a/chromium/third_party/blink/renderer/core/exported/web_scoped_window_focus_allowed_indicator.cc
+++ b/chromium/third_party/blink/renderer/core/exported/web_scoped_window_focus_allowed_indicator.cc
@@ -41,7 +41,7 @@ WebScopedWindowFocusAllowedIndicator::WebScopedWindowFocusAllowedIndicator(
Document* document = web_document->Unwrap<Document>();
DCHECK(document);
private_.reset(
- new ScopedWindowFocusAllowedIndicator(document->ToExecutionContext()));
+ new ScopedWindowFocusAllowedIndicator(document->GetExecutionContext()));
}
WebScopedWindowFocusAllowedIndicator::~WebScopedWindowFocusAllowedIndicator() =
diff --git a/chromium/third_party/blink/renderer/core/exported/web_scoped_window_focus_allowed_indicator_test.cc b/chromium/third_party/blink/renderer/core/exported/web_scoped_window_focus_allowed_indicator_test.cc
index be2e44fd906..2e1c14b783a 100644
--- a/chromium/third_party/blink/renderer/core/exported/web_scoped_window_focus_allowed_indicator_test.cc
+++ b/chromium/third_party/blink/renderer/core/exported/web_scoped_window_focus_allowed_indicator_test.cc
@@ -32,7 +32,7 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/web/web_document.h"
-#include "third_party/blink/renderer/core/dom/document.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/testing/dummy_page_holder.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
@@ -40,20 +40,20 @@ namespace blink {
TEST(WebScopedWindowFocusAllowedIndicatorTest, Basic) {
auto dummy = std::make_unique<DummyPageHolder>();
- auto* document = &dummy->GetDocument();
- WebDocument web_document(document);
+ auto* window = dummy->GetFrame().DomWindow();
+ WebDocument web_document(&dummy->GetDocument());
- EXPECT_FALSE(document->ToExecutionContext()->IsWindowInteractionAllowed());
+ EXPECT_FALSE(window->IsWindowInteractionAllowed());
{
WebScopedWindowFocusAllowedIndicator indicator1(&web_document);
- EXPECT_TRUE(document->ToExecutionContext()->IsWindowInteractionAllowed());
+ EXPECT_TRUE(window->IsWindowInteractionAllowed());
{
WebScopedWindowFocusAllowedIndicator indicator2(&web_document);
- EXPECT_TRUE(document->ToExecutionContext()->IsWindowInteractionAllowed());
+ EXPECT_TRUE(window->IsWindowInteractionAllowed());
}
- EXPECT_TRUE(document->ToExecutionContext()->IsWindowInteractionAllowed());
+ EXPECT_TRUE(window->IsWindowInteractionAllowed());
}
- EXPECT_FALSE(document->ToExecutionContext()->IsWindowInteractionAllowed());
+ EXPECT_FALSE(window->IsWindowInteractionAllowed());
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/exported/web_searchable_form_data_test.cc b/chromium/third_party/blink/renderer/core/exported/web_searchable_form_data_test.cc
index 98a4a642e52..78a8e8fdcfd 100644
--- a/chromium/third_party/blink/renderer/core/exported/web_searchable_form_data_test.cc
+++ b/chromium/third_party/blink/renderer/core/exported/web_searchable_form_data_test.cc
@@ -74,8 +74,8 @@ TEST_F(WebSearchableFormDataTest, HttpSearchString) {
WebViewImpl* web_view =
web_view_helper_.InitializeAndLoad(base_url + "search_form_http.html");
- WebVector<WebFormElement> forms;
- web_view->MainFrameImpl()->GetDocument().Forms(forms);
+ WebVector<WebFormElement> forms =
+ web_view->MainFrameImpl()->GetDocument().Forms();
EXPECT_EQ(forms.size(), 1U);
@@ -90,8 +90,8 @@ TEST_F(WebSearchableFormDataTest, HttpsSearchString) {
WebViewImpl* web_view =
web_view_helper_.InitializeAndLoad(base_url + "search_form_https.html");
- WebVector<WebFormElement> forms;
- web_view->MainFrameImpl()->GetDocument().Forms(forms);
+ WebVector<WebFormElement> forms =
+ web_view->MainFrameImpl()->GetDocument().Forms();
EXPECT_EQ(forms.size(), 1U);
diff --git a/chromium/third_party/blink/renderer/core/exported/web_settings_impl.cc b/chromium/third_party/blink/renderer/core/exported/web_settings_impl.cc
index 075b02ab8d5..f11e51633f3 100644
--- a/chromium/third_party/blink/renderer/core/exported/web_settings_impl.cc
+++ b/chromium/third_party/blink/renderer/core/exported/web_settings_impl.cc
@@ -152,6 +152,10 @@ void WebSettingsImpl::SetAccessibilityFontScaleFactor(float font_scale_factor) {
settings_->SetAccessibilityFontScaleFactor(font_scale_factor);
}
+void WebSettingsImpl::SetAccessibilityAlwaysShowFocus(bool always_show_focus) {
+ settings_->SetAccessibilityAlwaysShowFocus(always_show_focus);
+}
+
void WebSettingsImpl::SetAccessibilityPasswordValuesEnabled(bool enabled) {
settings_->SetAccessibilityPasswordValuesEnabled(enabled);
}
diff --git a/chromium/third_party/blink/renderer/core/exported/web_settings_impl.h b/chromium/third_party/blink/renderer/core/exported/web_settings_impl.h
index deb6bb33e14..c3f38e93e45 100644
--- a/chromium/third_party/blink/renderer/core/exported/web_settings_impl.h
+++ b/chromium/third_party/blink/renderer/core/exported/web_settings_impl.h
@@ -33,7 +33,7 @@
#include "third_party/blink/public/web/web_settings.h"
#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/platform/heap/handle.h"
+#include "third_party/blink/renderer/platform/heap/persistent.h"
namespace blink {
@@ -165,6 +165,7 @@ class CORE_EXPORT WebSettingsImpl final : public WebSettings {
void SetTextAreasAreResizable(bool) override;
void SetTextAutosizingEnabled(bool) override;
void SetAccessibilityFontScaleFactor(float) override;
+ void SetAccessibilityAlwaysShowFocus(bool) override;
void SetTextTrackKindUserPreference(TextTrackKindUserPreference) override;
void SetTextTrackBackgroundColor(const WebString&) override;
void SetTextTrackFontFamily(const WebString&) override;
@@ -246,7 +247,7 @@ class CORE_EXPORT WebSettingsImpl final : public WebSettings {
private:
Settings* settings_;
- UntracedMember<DevToolsEmulator> dev_tools_emulator_;
+ Persistent<DevToolsEmulator> dev_tools_emulator_;
bool render_v_sync_notification_enabled_;
bool auto_zoom_focused_node_to_legible_scale_;
bool support_deprecated_target_density_dpi_;
diff --git a/chromium/third_party/blink/renderer/core/exported/web_shared_worker_impl.cc b/chromium/third_party/blink/renderer/core/exported/web_shared_worker_impl.cc
index 7582cdbd3a1..9942e60d41f 100644
--- a/chromium/third_party/blink/renderer/core/exported/web_shared_worker_impl.cc
+++ b/chromium/third_party/blink/renderer/core/exported/web_shared_worker_impl.cc
@@ -145,11 +145,8 @@ void WebSharedWorkerImpl::Connect(MessagePortChannel web_channel) {
DCHECK(IsMainThread());
if (asked_to_terminate_)
return;
- // The HTML spec requires to queue a connect event using the DOM manipulation
- // task source.
- // https://html.spec.whatwg.org/C/#shared-workers-and-the-sharedworker-interface
PostCrossThreadTask(
- *GetWorkerThread()->GetTaskRunner(TaskType::kDOMManipulation), FROM_HERE,
+ *task_runner_for_connect_event_, FROM_HERE,
CrossThreadBindOnce(&WebSharedWorkerImpl::ConnectTaskOnWorkerThread,
WTF::CrossThreadUnretained(this),
WTF::Passed(std::move(web_channel))));
@@ -269,6 +266,18 @@ void WebSharedWorkerImpl::StartWorkerContext(
GetWorkerThread()->Start(std::move(creation_params), thread_startup_data,
std::move(devtools_params));
+
+ // Capture the task runner for dispatching connect events. This is necessary
+ // for avoiding race condition with WorkerScheduler termination induced by
+ // close() call on SharedWorkerGlobalScope. See https://crbug.com/1104046 for
+ // details.
+ //
+ // The HTML spec requires to queue a connect event using the DOM manipulation
+ // task source.
+ // https://html.spec.whatwg.org/C/#shared-workers-and-the-sharedworker-interface
+ task_runner_for_connect_event_ =
+ GetWorkerThread()->GetTaskRunner(TaskType::kDOMManipulation);
+
switch (script_type) {
case mojom::ScriptType::kClassic:
GetWorkerThread()->FetchAndRunClassicScript(
diff --git a/chromium/third_party/blink/renderer/core/exported/web_shared_worker_impl.h b/chromium/third_party/blink/renderer/core/exported/web_shared_worker_impl.h
index 13006f67bd3..98374fb9031 100644
--- a/chromium/third_party/blink/renderer/core/exported/web_shared_worker_impl.h
+++ b/chromium/third_party/blink/renderer/core/exported/web_shared_worker_impl.h
@@ -114,6 +114,8 @@ class CORE_EXPORT WebSharedWorkerImpl final : public WebSharedWorker {
// |client_| owns |this|.
WebSharedWorkerClient* client_;
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner_for_connect_event_;
+
bool asked_to_terminate_ = false;
base::WeakPtrFactory<WebSharedWorkerImpl> weak_ptr_factory_{this};
diff --git a/chromium/third_party/blink/renderer/core/exported/web_view_impl.cc b/chromium/third_party/blink/renderer/core/exported/web_view_impl.cc
index 43fc2bb2de6..ebebe2f3b21 100644
--- a/chromium/third_party/blink/renderer/core/exported/web_view_impl.cc
+++ b/chromium/third_party/blink/renderer/core/exported/web_view_impl.cc
@@ -146,7 +146,6 @@
#include "third_party/blink/renderer/core/timing/dom_window_performance.h"
#include "third_party/blink/renderer/core/timing/window_performance.h"
#include "third_party/blink/renderer/platform/fonts/font_cache.h"
-#include "third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.h"
#include "third_party/blink/renderer/platform/graphics/image.h"
#include "third_party/blink/renderer/platform/graphics/paint/cull_rect.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_record_builder.h"
@@ -160,7 +159,6 @@
#include "third_party/blink/renderer/platform/scheduler/public/page_lifecycle_state.h"
#include "third_party/blink/renderer/platform/scheduler/public/page_scheduler.h"
#include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h"
-#include "third_party/blink/renderer/platform/weborigin/scheme_registry.h"
#include "third_party/blink/renderer/platform/widget/widget_base.h"
#include "ui/gfx/skia_util.h"
@@ -231,26 +229,31 @@ class EmptyEventListener final : public NativeEventListener {
// WebView ----------------------------------------------------------------
-WebView* WebView::Create(WebViewClient* client,
- bool is_hidden,
- bool compositing_enabled,
- WebView* opener,
- mojo::ScopedInterfaceEndpointHandle page_handle) {
- return WebViewImpl::Create(client, is_hidden, compositing_enabled,
- static_cast<WebViewImpl*>(opener),
- std::move(page_handle));
+WebView* WebView::Create(
+ WebViewClient* client,
+ bool is_hidden,
+ bool compositing_enabled,
+ WebView* opener,
+ CrossVariantMojoAssociatedReceiver<mojom::PageBroadcastInterfaceBase>
+ page_handle) {
+ return WebViewImpl::Create(
+ client,
+ is_hidden ? mojom::blink::PageVisibilityState::kHidden
+ : mojom::blink::PageVisibilityState::kVisible,
+ compositing_enabled, static_cast<WebViewImpl*>(opener),
+ std::move(page_handle));
}
WebViewImpl* WebViewImpl::Create(
WebViewClient* client,
- bool is_hidden,
+ mojom::blink::PageVisibilityState visibility,
bool compositing_enabled,
WebViewImpl* opener,
- mojo::ScopedInterfaceEndpointHandle page_handle) {
+ mojo::PendingAssociatedReceiver<mojom::blink::PageBroadcast> page_handle) {
// Take a self-reference for WebViewImpl that is released by calling Close(),
// then return a raw pointer to the caller.
auto web_view = base::AdoptRef(new WebViewImpl(
- client, is_hidden, compositing_enabled, opener, std::move(page_handle)));
+ client, visibility, compositing_enabled, opener, std::move(page_handle)));
web_view->AddRef();
return web_view.get();
}
@@ -271,20 +274,20 @@ void WebViewImpl::SetPrerendererClient(
*AsView().page, prerenderer_client));
}
-WebViewImpl::WebViewImpl(WebViewClient* client,
- bool is_hidden,
- bool does_composite,
- WebViewImpl* opener,
- mojo::ScopedInterfaceEndpointHandle page_handle)
+WebViewImpl::WebViewImpl(
+ WebViewClient* client,
+ mojom::blink::PageVisibilityState visibility,
+ bool does_composite,
+ WebViewImpl* opener,
+ mojo::PendingAssociatedReceiver<mojom::blink::PageBroadcast> page_handle)
: as_view_(client),
chrome_client_(MakeGarbageCollected<ChromeClientImpl>(this)),
minimum_zoom_level_(PageZoomFactorToZoomLevel(kMinimumPageZoomFactor)),
maximum_zoom_level_(PageZoomFactorToZoomLevel(kMaximumPageZoomFactor)),
does_composite_(does_composite),
fullscreen_controller_(std::make_unique<FullscreenController>(this)),
- receiver_(this,
- mojo::PendingAssociatedReceiver<mojom::blink::PageBroadcast>(
- std::move(page_handle))) {
+ lifecycle_state_(mojom::blink::PageLifecycleState::New()),
+ receiver_(this, std::move(page_handle)) {
if (!AsView().client) {
DCHECK(!does_composite_);
}
@@ -295,9 +298,9 @@ WebViewImpl::WebViewImpl(WebViewClient* client,
Page::CreateOrdinary(page_clients, opener ? opener->GetPage() : nullptr);
CoreInitializer::GetInstance().ProvideModulesToPage(*AsView().page,
AsView().client);
- SetVisibilityState(
- is_hidden ? PageVisibilityState::kHidden : PageVisibilityState::kVisible,
- /*is_initial_state=*/true);
+
+ SetVisibilityState(visibility, /*is_initial_state=*/true);
+ lifecycle_state_->visibility = visibility;
// When not compositing, keep the Page in the loop so that it will paint all
// content into the root layer, as multiple layers can only be used when
@@ -401,14 +404,6 @@ void WebViewImpl::HandleMouseDown(LocalFrame& main_frame,
}
}
-void WebViewImpl::SetDisplayMode(blink::mojom::DisplayMode mode) {
- display_mode_ = mode;
- if (!MainFrameImpl() || !MainFrameImpl()->GetFrameView())
- return;
-
- MainFrameImpl()->GetFrameView()->SetDisplayMode(mode);
-}
-
void WebViewImpl::MouseContextMenu(const WebMouseEvent& event) {
if (!MainFrameImpl() || !MainFrameImpl()->GetFrameView())
return;
@@ -418,11 +413,10 @@ void WebViewImpl::MouseContextMenu(const WebMouseEvent& event) {
WebMouseEvent transformed_event =
TransformWebMouseEvent(MainFrameImpl()->GetFrameView(), event);
transformed_event.menu_source_type = kMenuSourceMouse;
- PhysicalOffset position_in_root_frame = PhysicalOffset::FromFloatPointRound(
- FloatPoint(transformed_event.PositionInRootFrame()));
// Find the right target frame. See issue 1186900.
- HitTestResult result = HitTestResultForRootFramePos(position_in_root_frame);
+ HitTestResult result = HitTestResultForRootFramePos(
+ FloatPoint(transformed_event.PositionInRootFrame()));
Frame* target_frame;
if (result.InnerNodeOrImageMapImage())
target_frame = result.InnerNodeOrImageMapImage()->GetDocument().GetFrame();
@@ -473,8 +467,8 @@ WebInputEventResult WebViewImpl::HandleGestureEvent(
bool event_cancelled = false; // for disambiguation
// Fling events are not sent to the renderer.
- CHECK(event.GetType() != WebInputEvent::kGestureFlingStart);
- CHECK(event.GetType() != WebInputEvent::kGestureFlingCancel);
+ CHECK(event.GetType() != WebInputEvent::Type::kGestureFlingStart);
+ CHECK(event.GetType() != WebInputEvent::Type::kGestureFlingCancel);
WebGestureEvent scaled_event =
TransformWebGestureEvent(MainFrameImpl()->GetFrameView(), event);
@@ -482,7 +476,7 @@ WebInputEventResult WebViewImpl::HandleGestureEvent(
// Special handling for double tap and scroll events as we don't want to
// hit test for them.
switch (event.GetType()) {
- case WebInputEvent::kGestureDoubleTap:
+ case WebInputEvent::Type::kGestureDoubleTap:
if (web_settings_->DoubleTapToZoomEnabled() &&
MinimumPageScaleFactor() != MaximumPageScaleFactor()) {
if (auto* main_frame = MainFrameImpl()) {
@@ -498,9 +492,9 @@ WebInputEventResult WebViewImpl::HandleGestureEvent(
MainFrameImpl()->FrameWidgetImpl()->Client()->DidHandleGestureEvent(
event, event_cancelled);
return event_result;
- case WebInputEvent::kGestureScrollBegin:
- case WebInputEvent::kGestureScrollEnd:
- case WebInputEvent::kGestureScrollUpdate:
+ case WebInputEvent::Type::kGestureScrollBegin:
+ case WebInputEvent::Type::kGestureScrollEnd:
+ case WebInputEvent::Type::kGestureScrollUpdate:
// Scrolling-related gesture events invoke EventHandler recursively for
// each frame down the chain, doing a single-frame hit-test per frame.
// This matches handleWheelEvent. Perhaps we could simplify things by
@@ -528,13 +522,13 @@ WebInputEventResult WebViewImpl::HandleGestureEvent(
// Handle link highlighting outside the main switch to avoid getting lost in
// the complicated set of cases handled below.
switch (event.GetType()) {
- case WebInputEvent::kGestureShowPress:
+ case WebInputEvent::Type::kGestureShowPress:
// Queue a highlight animation, then hand off to regular handler.
EnableTapHighlightAtPoint(targeted_event);
break;
- case WebInputEvent::kGestureTapCancel:
- case WebInputEvent::kGestureTap:
- case WebInputEvent::kGestureLongPress:
+ case WebInputEvent::Type::kGestureTapCancel:
+ case WebInputEvent::Type::kGestureTap:
+ case WebInputEvent::Type::kGestureLongPress:
GetPage()->GetLinkHighlight().StartHighlightAnimationIfNeeded();
break;
default:
@@ -542,7 +536,7 @@ WebInputEventResult WebViewImpl::HandleGestureEvent(
}
switch (event.GetType()) {
- case WebInputEvent::kGestureTap: {
+ case WebInputEvent::Type::kGestureTap: {
{
ContextMenuAllowedScope scope;
event_result =
@@ -561,13 +555,13 @@ WebInputEventResult WebViewImpl::HandleGestureEvent(
last_hidden_page_popup_ = nullptr;
break;
}
- case WebInputEvent::kGestureTwoFingerTap:
- case WebInputEvent::kGestureLongPress:
- case WebInputEvent::kGestureLongTap: {
+ case WebInputEvent::Type::kGestureTwoFingerTap:
+ case WebInputEvent::Type::kGestureLongPress:
+ case WebInputEvent::Type::kGestureLongTap: {
if (!MainFrameImpl() || !MainFrameImpl()->GetFrameView())
break;
- if (event.GetType() == WebInputEvent::kGestureLongTap &&
+ if (event.GetType() == WebInputEvent::Type::kGestureLongTap &&
!MainFrameImpl()
->GetFrame()
->GetEventHandler()
@@ -584,7 +578,7 @@ WebInputEventResult WebViewImpl::HandleGestureEvent(
break;
}
- case WebInputEvent::kGestureTapDown: {
+ case WebInputEvent::Type::kGestureTapDown: {
// Touch pinch zoom and scroll on the page (outside of a popup) must hide
// the popup. In case of a touch scroll or pinch zoom, this function is
// called with GestureTapDown rather than a GSB/GSU/GSE or GPB/GPU/GPE.
@@ -601,7 +595,7 @@ WebInputEventResult WebViewImpl::HandleGestureEvent(
targeted_event);
break;
}
- case WebInputEvent::kGestureTapCancel: {
+ case WebInputEvent::Type::kGestureTapCancel: {
// Don't have this value persist outside of a single tap gesture.
last_hidden_page_popup_ = nullptr;
event_result =
@@ -609,13 +603,13 @@ WebInputEventResult WebViewImpl::HandleGestureEvent(
targeted_event);
break;
}
- case WebInputEvent::kGestureShowPress: {
+ case WebInputEvent::Type::kGestureShowPress: {
event_result =
MainFrameImpl()->GetFrame()->GetEventHandler().HandleGestureEvent(
targeted_event);
break;
}
- case WebInputEvent::kGestureTapUnconfirmed: {
+ case WebInputEvent::Type::kGestureTapUnconfirmed: {
event_result =
MainFrameImpl()->GetFrame()->GetEventHandler().HandleGestureEvent(
targeted_event);
@@ -688,9 +682,9 @@ void WebViewImpl::AcceptLanguagesChanged() {
}
WebInputEventResult WebViewImpl::HandleKeyEvent(const WebKeyboardEvent& event) {
- DCHECK((event.GetType() == WebInputEvent::kRawKeyDown) ||
- (event.GetType() == WebInputEvent::kKeyDown) ||
- (event.GetType() == WebInputEvent::kKeyUp));
+ DCHECK((event.GetType() == WebInputEvent::Type::kRawKeyDown) ||
+ (event.GetType() == WebInputEvent::Type::kKeyDown) ||
+ (event.GetType() == WebInputEvent::Type::kKeyUp));
TRACE_EVENT2("input", "WebViewImpl::handleKeyEvent", "type",
WebInputEvent::GetName(event.GetType()), "text",
String(event.text).Utf8());
@@ -709,7 +703,7 @@ WebInputEventResult WebViewImpl::HandleKeyEvent(const WebKeyboardEvent& event) {
page_popup_->HandleKeyEvent(event);
// We need to ignore the next Char event after this otherwise pressing
// enter when selecting an item in the popup will go to the page.
- if (WebInputEvent::kRawKeyDown == event.GetType())
+ if (WebInputEvent::Type::kRawKeyDown == event.GetType())
suppress_next_keypress_event_ = true;
return WebInputEventResult::kHandledSystem;
}
@@ -722,7 +716,7 @@ WebInputEventResult WebViewImpl::HandleKeyEvent(const WebKeyboardEvent& event) {
WebInputEventResult result =
focused_local_frame->GetEventHandler().KeyEvent(event);
if (result != WebInputEventResult::kNotHandled) {
- if (WebInputEvent::kRawKeyDown == event.GetType()) {
+ if (WebInputEvent::Type::kRawKeyDown == event.GetType()) {
// Suppress the next keypress event unless the focused node is a plugin
// node. (Flash needs these keypress events to handle non-US keyboards.)
Element* element = FocusedElement();
@@ -747,12 +741,12 @@ WebInputEventResult WebViewImpl::HandleKeyEvent(const WebKeyboardEvent& event) {
#if !defined(OS_MACOSX)
const WebInputEvent::Type kContextMenuKeyTriggeringEventType =
#if defined(OS_WIN)
- WebInputEvent::kKeyUp;
+ WebInputEvent::Type::kKeyUp;
#else
- WebInputEvent::kRawKeyDown;
+ WebInputEvent::Type::kRawKeyDown;
#endif
const WebInputEvent::Type kShiftF10TriggeringEventType =
- WebInputEvent::kRawKeyDown;
+ WebInputEvent::Type::kRawKeyDown;
bool is_unmodified_menu_key =
!(event.GetModifiers() & WebInputEvent::kInputModifiers) &&
@@ -773,7 +767,7 @@ WebInputEventResult WebViewImpl::HandleKeyEvent(const WebKeyboardEvent& event) {
WebInputEventResult WebViewImpl::HandleCharEvent(
const WebKeyboardEvent& event) {
- DCHECK_EQ(event.GetType(), WebInputEvent::kChar);
+ DCHECK_EQ(event.GetType(), WebInputEvent::Type::kChar);
TRACE_EVENT1("input", "WebViewImpl::handleCharEvent", "text",
String(event.text).Utf8());
@@ -1184,6 +1178,11 @@ void WebViewImpl::CleanupPagePopup() {
DisablePopupMouseWheelEventListener();
}
+void WebViewImpl::UpdatePagePopup() {
+ if (page_popup_)
+ page_popup_->Update();
+}
+
void WebViewImpl::EnablePopupMouseWheelEventListener(
WebLocalFrameImpl* local_root) {
DCHECK(!popup_mouse_wheel_event_listener_);
@@ -1521,16 +1520,6 @@ void WebViewImpl::BeginFrame(base::TimeTicks last_frame_time) {
PageWidgetDelegate::Animate(*AsView().page, last_frame_time);
}
-void WebViewImpl::DidBeginFrame() {
- if (!MainFrameImpl() || !MainFrameImpl()->GetFrame())
- return;
- if (Document* document = MainFrameImpl()->GetFrame()->GetDocument()) {
- DocumentLifecycle::AllowThrottlingScope throttling_scope(
- document->Lifecycle());
- PageWidgetDelegate::DidBeginFrame(*MainFrameImpl()->GetFrame());
- }
-}
-
void WebViewImpl::BeginUpdateLayers() {
if (MainFrameImpl())
update_layers_start_time_.emplace(base::TimeTicks::Now());
@@ -1547,25 +1536,6 @@ void WebViewImpl::EndUpdateLayers() {
update_layers_start_time_.reset();
}
-void WebViewImpl::BeginCommitCompositorFrame() {
- if (MainFrameImpl()) {
- commit_compositor_frame_start_time_.emplace(base::TimeTicks::Now());
- }
-}
-
-void WebViewImpl::EndCommitCompositorFrame(base::TimeTicks commit_start_time) {
- // Some tests call this without ever beginning a frame.
- if (MainFrameImpl() && commit_compositor_frame_start_time_) {
- MainFrameImpl()
- ->GetFrame()
- ->View()
- ->EnsureUkmAggregator()
- .RecordImplCompositorSample(commit_compositor_frame_start_time_.value(),
- commit_start_time, base::TimeTicks::Now());
- }
- commit_compositor_frame_start_time_.reset();
-}
-
void WebViewImpl::RecordStartOfFrameMetrics() {
if (!MainFrameImpl())
return;
@@ -1613,6 +1583,8 @@ void WebViewImpl::UpdateLifecycle(WebLifecycleUpdate requested_update,
if (requested_update != WebLifecycleUpdate::kAll)
return;
+ UpdatePagePopup();
+
// There is no background color for non-composited WebViews (eg printing).
if (does_composite_) {
MainFrameImpl()->FrameWidgetImpl()->SetBackgroundColor(BackgroundColor());
@@ -1743,7 +1715,7 @@ WebInputEventResult WebViewImpl::HandleInputEvent(
// If a drag-and-drop operation is in progress, ignore input events except
// PointerCancel.
if (MainFrameImpl()->FrameWidgetImpl()->DoingDragAndDrop() &&
- input_event.GetType() != WebInputEvent::kPointerCancel)
+ input_event.GetType() != WebInputEvent::Type::kPointerCancel)
return WebInputEventResult::kHandledSuppressed;
if (WebDevToolsAgentImpl* devtools = MainFrameDevToolsAgentImpl()) {
@@ -1775,13 +1747,13 @@ WebInputEventResult WebViewImpl::HandleInputEvent(
Document& main_frame_document = *MainFrameImpl()->GetFrame()->GetDocument();
- if (input_event.GetType() != WebInputEvent::kMouseMove) {
+ if (input_event.GetType() != WebInputEvent::Type::kMouseMove) {
FirstMeaningfulPaintDetector::From(main_frame_document).NotifyInputEvent();
}
- if (input_event.GetType() != WebInputEvent::kMouseMove &&
- input_event.GetType() != WebInputEvent::kMouseEnter &&
- input_event.GetType() != WebInputEvent::kMouseLeave) {
+ if (input_event.GetType() != WebInputEvent::Type::kMouseMove &&
+ input_event.GetType() != WebInputEvent::Type::kMouseEnter &&
+ input_event.GetType() != WebInputEvent::Type::kMouseLeave) {
InteractiveDetector* interactive_detector(
InteractiveDetector::From(main_frame_document));
if (interactive_detector) {
@@ -1803,7 +1775,7 @@ WebInputEventResult WebViewImpl::HandleInputEvent(
// Skip the pointerrawupdate for mouse capture case.
if (mouse_capture_element_ &&
- input_event.GetType() == WebInputEvent::kPointerRawUpdate)
+ input_event.GetType() == WebInputEvent::Type::kPointerRawUpdate)
return WebInputEventResult::kHandledSystem;
if (mouse_capture_element_ &&
@@ -1824,29 +1796,29 @@ WebInputEventResult WebViewImpl::HandleCapturedMouseEvent(
HTMLPlugInElement* element = mouse_capture_element_;
// Not all platforms call mouseCaptureLost() directly.
- if (input_event.GetType() == WebInputEvent::kMouseUp)
+ if (input_event.GetType() == WebInputEvent::Type::kMouseUp)
MouseCaptureLost();
AtomicString event_type;
switch (input_event.GetType()) {
- case WebInputEvent::kMouseEnter:
+ case WebInputEvent::Type::kMouseEnter:
event_type = event_type_names::kMouseover;
break;
- case WebInputEvent::kMouseMove:
+ case WebInputEvent::Type::kMouseMove:
event_type = event_type_names::kMousemove;
break;
- case WebInputEvent::kPointerRawUpdate:
+ case WebInputEvent::Type::kPointerRawUpdate:
// There will be no mouse event for rawupdate events.
event_type = event_type_names::kPointerrawupdate;
break;
- case WebInputEvent::kMouseLeave:
+ case WebInputEvent::Type::kMouseLeave:
event_type = event_type_names::kMouseout;
break;
- case WebInputEvent::kMouseDown:
+ case WebInputEvent::Type::kMouseDown:
event_type = event_type_names::kMousedown;
LocalFrame::NotifyUserActivation(element->GetDocument().GetFrame());
break;
- case WebInputEvent::kMouseUp:
+ case WebInputEvent::Type::kMouseUp:
event_type = event_type_names::kMouseup;
break;
default:
@@ -1874,12 +1846,6 @@ void WebViewImpl::SetCursorVisibilityState(bool is_visible) {
AsView().page->SetIsCursorVisible(is_visible);
}
-void WebViewImpl::OnFallbackCursorModeToggled(bool is_on) {
- DCHECK(MainFrameImpl());
- MainFrameImpl()->GetFrame()->GetEventHandler().SetIsFallbackCursorModeOn(
- is_on);
-}
-
void WebViewImpl::MouseCaptureLost() {
TRACE_EVENT_NESTABLE_ASYNC_END0("input", "capturing mouse",
TRACE_ID_LOCAL(this));
@@ -2085,19 +2051,6 @@ void WebViewImpl::SetFocusedFrame(WebFrame* frame) {
core_frame->GetPage()->GetFocusController().SetFocusedFrame(core_frame);
}
-void WebViewImpl::SetInitialFocus(bool reverse) {
- if (!AsView().page)
- return;
- Frame* frame = GetPage()->GetFocusController().FocusedOrMainFrame();
- if (auto* local_frame = DynamicTo<LocalFrame>(frame)) {
- if (Document* document = local_frame->GetDocument())
- document->ClearFocusedElement();
- }
- GetPage()->GetFocusController().SetInitialFocus(
- reverse ? mojom::blink::FocusType::kBackward
- : mojom::blink::FocusType::kForward);
-}
-
// TODO(dglazkov): Remove and replace with Node:hasEditableStyle.
// http://crbug.com/612560
static bool IsElementEditable(const Element* element) {
@@ -2319,15 +2272,6 @@ void WebViewImpl::AdvanceFocus(bool reverse) {
: mojom::blink::FocusType::kForward);
}
-void WebViewImpl::AdvanceFocusAcrossFrames(mojom::blink::FocusType type,
- WebRemoteFrame* from,
- WebLocalFrame* to) {
- // TODO(alexmos): Pass in proper with sourceCapabilities.
- GetPage()->GetFocusController().AdvanceFocusAcrossFrames(
- type, To<WebRemoteFrameImpl>(from)->GetFrame(),
- To<WebLocalFrameImpl>(to)->GetFrame());
-}
-
double WebViewImpl::ZoomLevel() {
return zoom_level_;
}
@@ -2462,8 +2406,15 @@ void WebViewImpl::SetPageLifecycleState(
Page* page = GetPage();
if (!page)
return;
- Scheduler()->SetPageFrozen(state->is_frozen);
+ if (state->visibility != lifecycle_state_->visibility) {
+ SetVisibilityState(state->visibility, /*is_initial_state =*/false);
+ }
+ if (state->is_frozen != lifecycle_state_->is_frozen) {
+ Scheduler()->SetPageFrozen(state->is_frozen);
+ }
+
+ lifecycle_state_ = std::move(state);
// Tell the browser that the freezing or resuming was successful.
std::move(callback).Run();
}
@@ -2784,12 +2735,12 @@ void WebViewImpl::AudioStateChanged(bool is_audio_playing) {
GetPage()->GetPageScheduler()->AudioStateChanged(is_audio_playing);
}
-WebHitTestResult WebViewImpl::HitTestResultAt(const gfx::Point& point) {
+WebHitTestResult WebViewImpl::HitTestResultAt(const gfx::PointF& point) {
return CoreHitTestResultAt(point);
}
HitTestResult WebViewImpl::CoreHitTestResultAt(
- const gfx::Point& point_in_viewport) {
+ const gfx::PointF& point_in_viewport) {
// TODO(crbug.com/843128): When we do async hit-testing, we might try to do
// hit-testing when the local main frame is not valid anymore. Look into if we
// can avoid getting here earlier in the pipeline.
@@ -2799,8 +2750,8 @@ HitTestResult WebViewImpl::CoreHitTestResultAt(
DocumentLifecycle::AllowThrottlingScope throttling_scope(
MainFrameImpl()->GetFrame()->GetDocument()->Lifecycle());
LocalFrameView* view = MainFrameImpl()->GetFrameView();
- PhysicalOffset point_in_root_frame =
- view->ViewportToFrame(PhysicalOffset(IntPoint(point_in_viewport)));
+ FloatPoint point_in_root_frame =
+ view->ViewportToFrame(FloatPoint(point_in_viewport));
return HitTestResultForRootFramePos(point_in_root_frame);
}
@@ -2997,12 +2948,6 @@ bool WebViewImpl::IsActive() const {
return GetPage() ? GetPage()->GetFocusController().IsActive() : false;
}
-void WebViewImpl::SetDomainRelaxationForbidden(bool forbidden,
- const WebString& scheme) {
- SchemeRegistry::SetDomainRelaxationForbiddenForURLScheme(forbidden,
- String(scheme));
-}
-
void WebViewImpl::SetWindowFeatures(const WebWindowFeatures& features) {
AsView().page->SetWindowFeatures(features);
}
@@ -3113,6 +3058,15 @@ void WebViewImpl::MainFrameScrollOffsetChanged() {
}
}
+void WebViewImpl::TextAutosizerPageInfoChanged(
+ const WebTextAutosizerPageInfo& page_info) {
+ DCHECK(MainFrameImpl());
+ local_main_frame_host_remote_->TextAutosizerPageInfoChanged(
+ mojom::blink::TextAutosizerPageInfo::New(
+ page_info.main_frame_width, page_info.main_frame_layout_width,
+ page_info.device_scale_adjustment));
+}
+
void WebViewImpl::SetBackgroundColorOverride(SkColor color) {
DCHECK(does_composite_);
@@ -3137,12 +3091,6 @@ void WebViewImpl::SetZoomFactorOverride(float zoom_factor) {
SetZoomLevel(ZoomLevel());
}
-void WebViewImpl::SetMainFrameOverlayColor(SkColor color) {
- DCHECK(AsView().page->MainFrame());
- if (auto* local_frame = DynamicTo<LocalFrame>(AsView().page->MainFrame()))
- local_frame->SetMainFrameColorOverlay(color);
-}
-
Element* WebViewImpl::FocusedElement() const {
LocalFrame* frame = AsView().page->GetFocusController().FocusedFrame();
if (!frame)
@@ -3156,7 +3104,7 @@ Element* WebViewImpl::FocusedElement() const {
}
HitTestResult WebViewImpl::HitTestResultForRootFramePos(
- const PhysicalOffset& pos_in_root_frame) {
+ const FloatPoint& pos_in_root_frame) {
auto* main_frame = DynamicTo<LocalFrame>(AsView().page->MainFrame());
if (!main_frame)
return HitTestResult();
@@ -3175,7 +3123,7 @@ WebHitTestResult WebViewImpl::HitTestResultForTap(
if (!main_frame)
return HitTestResult();
- WebGestureEvent tap_event(WebInputEvent::kGestureTap,
+ WebGestureEvent tap_event(WebInputEvent::Type::kGestureTap,
WebInputEvent::kNoModifiers, base::TimeTicks::Now(),
WebGestureDevice::kTouchscreen);
// GestureTap is only ever from a touchscreen.
@@ -3355,27 +3303,24 @@ PageScheduler* WebViewImpl::Scheduler() const {
return GetPage()->GetPageScheduler();
}
-void WebViewImpl::SetVisibilityState(PageVisibilityState visibility_state,
- bool is_initial_state) {
+void WebViewImpl::SetVisibilityState(
+ mojom::blink::PageVisibilityState visibility_state,
+ bool is_initial_state) {
DCHECK(GetPage());
+ if (!is_initial_state) {
+ // Preserve the side effects of visibility change.
+ AsView().client->OnPageVisibilityChanged(visibility_state);
+ }
GetPage()->SetVisibilityState(visibility_state, is_initial_state);
- GetPage()->GetPageScheduler()->SetPageVisible(visibility_state ==
- PageVisibilityState::kVisible);
+ GetPage()->GetPageScheduler()->SetPageVisible(
+ visibility_state == mojom::blink::PageVisibilityState::kVisible);
}
-PageVisibilityState WebViewImpl::GetVisibilityState() {
+mojom::blink::PageVisibilityState WebViewImpl::GetVisibilityState() {
DCHECK(GetPage());
return GetPage()->GetVisibilityState();
}
-void WebViewImpl::ForceNextWebGLContextCreationToFail() {
- CoreInitializer::GetInstance().ForceNextWebGLContextCreationToFail();
-}
-
-void WebViewImpl::ForceNextDrawingBufferCreationToFail() {
- DrawingBuffer::ForceNextDrawingBufferCreationToFail();
-}
-
float WebViewImpl::DeviceScaleFactor() const {
// TODO(oshima): Investigate if this should return the ScreenInfo's scale
// factor rather than page's scale factor, which can be 1 in use-zoom-for-dsf
@@ -3405,65 +3350,61 @@ void WebViewImpl::SetPageFrozen(bool frozen) {
}
void WebViewImpl::PutPageIntoBackForwardCache() {
- SetVisibilityState(PageVisibilityState::kHidden, /*is_initial_state=*/false);
-
- Page* page = AsView().page;
- if (page) {
- for (Frame* frame = page->MainFrame(); frame;
- frame = frame->Tree().TraverseNext()) {
- if (frame->DomWindow() && frame->DomWindow()->IsLocalDOMWindow()) {
- frame->DomWindow()->ToLocalDOMWindow()->DispatchPagehideEvent(
- PageTransitionEventPersistence::kPageTransitionEventPersisted);
- }
+ DCHECK(GetPage());
+
+ SetVisibilityState(mojom::blink::PageVisibilityState::kHidden,
+ /*is_initial_state=*/false);
+
+ for (Frame* frame = GetPage()->MainFrame(); frame;
+ frame = frame->Tree().TraverseNext()) {
+ if (frame->DomWindow() && frame->DomWindow()->IsLocalDOMWindow()) {
+ frame->DomWindow()->ToLocalDOMWindow()->DispatchPagehideEvent(
+ PageTransitionEventPersistence::kPageTransitionEventPersisted);
}
}
// Freeze the page.
Scheduler()->SetPageFrozen(/*frozen =*/true);
// Hook eviction.
- if (page) {
- for (Frame* frame = page->MainFrame(); frame;
- frame = frame->Tree().TraverseNext()) {
- auto* local_frame = DynamicTo<LocalFrame>(frame);
- if (!local_frame)
- continue;
- local_frame->HookBackForwardCacheEviction();
- }
+ for (Frame* frame = GetPage()->MainFrame(); frame;
+ frame = frame->Tree().TraverseNext()) {
+ auto* local_frame = DynamicTo<LocalFrame>(frame);
+ if (!local_frame)
+ continue;
+ local_frame->HookBackForwardCacheEviction();
}
}
void WebViewImpl::RestorePageFromBackForwardCache(
base::TimeTicks navigation_start) {
+ DCHECK(GetPage());
+
// Unhook eviction.
- Page* page = AsView().page;
- if (page) {
- for (Frame* frame = page->MainFrame(); frame;
- frame = frame->Tree().TraverseNext()) {
- auto* local_frame = DynamicTo<LocalFrame>(frame);
- if (!local_frame)
- continue;
- local_frame->RemoveBackForwardCacheEviction();
- }
+ for (Frame* frame = GetPage()->MainFrame(); frame;
+ frame = frame->Tree().TraverseNext()) {
+ auto* local_frame = DynamicTo<LocalFrame>(frame);
+ if (!local_frame)
+ continue;
+ local_frame->RemoveBackForwardCacheEviction();
}
// Resume the page.
Scheduler()->SetPageFrozen(/*frozen =*/false);
- if (page) {
- for (Frame* frame = page->MainFrame(); frame;
- frame = frame->Tree().TraverseNext()) {
- if (frame->DomWindow() && frame->DomWindow()->IsLocalDOMWindow()) {
- frame->DomWindow()->ToLocalDOMWindow()->DispatchPersistedPageshowEvent(
- navigation_start);
- if (frame->IsMainFrame()) {
- UMA_HISTOGRAM_BOOLEAN(
- "BackForwardCache.MainFrameHasPageshowListenersOnRestore",
- frame->DomWindow()->ToLocalDOMWindow()->HasEventListeners(
- event_type_names::kPageshow));
- }
+ for (Frame* frame = GetPage()->MainFrame(); frame;
+ frame = frame->Tree().TraverseNext()) {
+ if (frame->DomWindow() && frame->DomWindow()->IsLocalDOMWindow()) {
+ frame->DomWindow()->ToLocalDOMWindow()->DispatchPersistedPageshowEvent(
+ navigation_start);
+ if (frame->IsMainFrame()) {
+ UMA_HISTOGRAM_BOOLEAN(
+ "BackForwardCache.MainFrameHasPageshowListenersOnRestore",
+ frame->DomWindow()->ToLocalDOMWindow()->HasEventListeners(
+ event_type_names::kPageshow));
}
}
}
- SetVisibilityState(PageVisibilityState::kVisible, /*is_initial_state=*/false);
+ SetVisibilityState(mojom::blink::PageVisibilityState::kVisible,
+ /*is_initial_state=*/false);
}
WebFrameWidget* WebViewImpl::MainFrameWidget() {
diff --git a/chromium/third_party/blink/renderer/core/exported/web_view_impl.h b/chromium/third_party/blink/renderer/core/exported/web_view_impl.h
index 60cfa746367..ae5bf526b8a 100644
--- a/chromium/third_party/blink/renderer/core/exported/web_view_impl.h
+++ b/chromium/third_party/blink/renderer/core/exported/web_view_impl.h
@@ -41,8 +41,8 @@
#include "third_party/blink/public/common/input/web_input_event.h"
#include "third_party/blink/public/mojom/frame/frame.mojom-blink.h"
#include "third_party/blink/public/mojom/input/focus_type.mojom-blink-forward.h"
-#include "third_party/blink/public/mojom/manifest/display_mode.mojom-shared.h"
#include "third_party/blink/public/mojom/page/page.mojom-blink.h"
+#include "third_party/blink/public/mojom/page/page_visibility_state.mojom-blink.h"
#include "third_party/blink/public/platform/web_input_event_result.h"
#include "third_party/blink/public/platform/web_rect.h"
#include "third_party/blink/public/platform/web_size.h"
@@ -91,7 +91,6 @@ class WebElement;
class WebInputMethodController;
class WebLocalFrame;
class WebLocalFrameImpl;
-class WebRemoteFrame;
class WebSettingsImpl;
class WebViewClient;
class WebFrameWidgetBase;
@@ -105,11 +104,12 @@ class CORE_EXPORT WebViewImpl final : public WebView,
public PageWidgetEventHandler,
public mojom::blink::PageBroadcast {
public:
- static WebViewImpl* Create(WebViewClient*,
- bool is_hidden,
- bool compositing_enabled,
- WebViewImpl* opener,
- mojo::ScopedInterfaceEndpointHandle page_handle);
+ static WebViewImpl* Create(
+ WebViewClient*,
+ mojom::blink::PageVisibilityState visibility,
+ bool compositing_enabled,
+ WebViewImpl* opener,
+ mojo::PendingAssociatedReceiver<mojom::blink::PageBroadcast> page_handle);
// All calls to Create() should be balanced with a call to Close(). This
// synchronously destroys the WebViewImpl.
@@ -134,7 +134,6 @@ class CORE_EXPORT WebViewImpl final : public WebView,
void SetTabKeyCyclesThroughElements(bool value) override;
bool IsActive() const override;
void SetIsActive(bool value) override;
- void SetDomainRelaxationForbidden(bool, const WebString& scheme) override;
void SetWindowFeatures(const WebWindowFeatures&) override;
void SetOpenedByDOM() override;
void ResizeWithBrowserControls(const WebSize& main_frame_widget_size,
@@ -147,14 +146,10 @@ class CORE_EXPORT WebViewImpl final : public WebView,
WebFrame* MainFrame() override;
WebLocalFrame* FocusedFrame() override;
void SetFocusedFrame(WebFrame*) override;
- void SetInitialFocus(bool reverse) override;
void SmoothScroll(int target_x,
int target_y,
base::TimeDelta duration) override;
void AdvanceFocus(bool reverse) override;
- void AdvanceFocusAcrossFrames(mojom::blink::FocusType,
- WebRemoteFrame* from,
- WebLocalFrame* to) override;
void ZoomAndScrollToFocusedEditableElementRect(
const WebRect& element_bounds_in_document,
const WebRect& caret_bounds_in_document,
@@ -181,7 +176,6 @@ class CORE_EXPORT WebViewImpl final : public WebView,
WebSize ContentsPreferredMinimumSize() override;
void UpdatePreferredSize() override;
void EnablePreferredSizeChangedMode() override;
- void SetDisplayMode(blink::mojom::DisplayMode) override;
void SetDeviceScaleFactor(float) override;
void SetZoomFactorForDeviceScaleFactor(float) override;
float ZoomFactorForDeviceScaleFactor() override {
@@ -191,7 +185,7 @@ class CORE_EXPORT WebViewImpl final : public WebView,
const WebSize& max_size) override;
void DisableAutoResizeMode() override;
void AudioStateChanged(bool is_audio_playing) override;
- WebHitTestResult HitTestResultAt(const gfx::Point&);
+ WebHitTestResult HitTestResultAt(const gfx::PointF&);
WebHitTestResult HitTestResultForTap(const gfx::Point&,
const WebSize&) override;
uint64_t CreateUniqueIdentifierForRequest() override;
@@ -201,7 +195,6 @@ class CORE_EXPORT WebViewImpl final : public WebView,
void DidCloseContextMenu() override;
void CancelPagePopup() override;
WebPagePopupImpl* GetPagePopup() const override { return page_popup_.get(); }
- void SetMainFrameOverlayColor(SkColor) override;
void AcceptLanguagesChanged() override;
void SetPageFrozen(bool frozen) override;
void PutPageIntoBackForwardCache() override;
@@ -235,7 +228,7 @@ class CORE_EXPORT WebViewImpl final : public WebView,
float ClampPageScaleFactorToLimits(float) const;
void ResetScaleStateImmediately();
- HitTestResult CoreHitTestResultAt(const gfx::Point&);
+ HitTestResult CoreHitTestResultAt(const gfx::PointF&);
void InvalidateRect(const IntRect&);
void SetZoomFactorOverride(float);
@@ -309,6 +302,7 @@ class CORE_EXPORT WebViewImpl final : public WebView,
void DidChangeContentsSize();
void PageScaleFactorChanged();
void MainFrameScrollOffsetChanged();
+ void TextAutosizerPageInfoChanged(const WebTextAutosizerPageInfo& page_info);
bool ShouldAutoResize() const { return should_auto_resize_; }
@@ -325,12 +319,15 @@ class CORE_EXPORT WebViewImpl final : public WebView,
// Callback from PagePopup when it is closed, which it can be done directly
// without coming through WebViewImpl.
void CleanupPagePopup();
+ // Ensure popup's size and position is correct based on its owner element's
+ // dimensions.
+ void UpdatePagePopup();
LocalDOMWindow* PagePopupWindow() const;
PageScheduler* Scheduler() const override;
- void SetVisibilityState(PageVisibilityState visibility_state,
+ void SetVisibilityState(mojom::blink::PageVisibilityState visibility_state,
bool is_initial_state) override;
- PageVisibilityState GetVisibilityState() override;
+ mojom::blink::PageVisibilityState GetVisibilityState() override;
// Called by a full frame plugin inside this view to inform it that its
// zoom level has been updated. The plugin should only call this function
@@ -387,9 +384,6 @@ class CORE_EXPORT WebViewImpl final : public WebView,
// changed.
void DidUpdateBrowserControls();
- void ForceNextWebGLContextCreationToFail() override;
- void ForceNextDrawingBufferCreationToFail() override;
-
void AddAutoplayFlags(int32_t) override;
void ClearAutoplayFlags() override;
int32_t AutoplayFlagsForTest() override;
@@ -397,7 +391,6 @@ class CORE_EXPORT WebViewImpl final : public WebView,
WebSize Size();
IntSize MainFrameSize();
- blink::mojom::DisplayMode DisplayMode() const { return display_mode_; }
PageScaleConstraintsSet& GetPageScaleConstraintsSet() const;
@@ -462,11 +455,8 @@ class CORE_EXPORT WebViewImpl final : public WebView,
// WebViewImpl. We expect to eventually move these out.
void SetSuppressFrameRequestsWorkaroundFor704763Only(bool);
void BeginFrame(base::TimeTicks last_frame_time);
- void DidBeginFrame();
void BeginUpdateLayers();
void EndUpdateLayers();
- void BeginCommitCompositorFrame();
- void EndCommitCompositorFrame(base::TimeTicks commit_start_time);
void RecordStartOfFrameMetrics();
void RecordEndOfFrameMetrics(base::TimeTicks frame_begin_time,
cc::ActiveFrameSequenceTrackers trackers);
@@ -477,7 +467,6 @@ class CORE_EXPORT WebViewImpl final : public WebView,
WebInputEventResult HandleInputEvent(const WebCoalescedInputEvent&);
WebInputEventResult DispatchBufferedTouchEvents();
void SetCursorVisibilityState(bool is_visible);
- void OnFallbackCursorModeToggled(bool is_on);
void ApplyViewportChanges(const ApplyViewportChangesArgs& args);
void RecordManipulationTypeCounts(cc::ManipulationInfo info);
void SendOverscrollEventFromImplSide(const gfx::Vector2dF& overscroll_delta,
@@ -508,14 +497,15 @@ class CORE_EXPORT WebViewImpl final : public WebView,
void UpdateBaseBackgroundColor();
- WebViewImpl(WebViewClient*,
- bool is_hidden,
- bool does_composite,
- WebViewImpl* opener,
- mojo::ScopedInterfaceEndpointHandle page_handle);
+ WebViewImpl(
+ WebViewClient*,
+ mojom::blink::PageVisibilityState visibility,
+ bool does_composite,
+ WebViewImpl* opener,
+ mojo::PendingAssociatedReceiver<mojom::blink::PageBroadcast> page_handle);
~WebViewImpl() override;
- HitTestResult HitTestResultForRootFramePos(const PhysicalOffset&);
+ HitTestResult HitTestResultForRootFramePos(const FloatPoint&);
void ConfigureAutoResizeMode();
@@ -689,7 +679,6 @@ class CORE_EXPORT WebViewImpl final : public WebView,
bool should_dispatch_first_visually_non_empty_layout_ = false;
bool should_dispatch_first_layout_after_finished_parsing_ = false;
bool should_dispatch_first_layout_after_finished_loading_ = false;
- blink::mojom::DisplayMode display_mode_ = blink::mojom::DisplayMode::kBrowser;
// TODO(bokan): Temporary debugging added to diagnose
// https://crbug.com/992315. Somehow we're synchronously calling
@@ -733,8 +722,8 @@ class CORE_EXPORT WebViewImpl final : public WebView,
// Set when a measurement begins, reset when the measurement is taken.
base::Optional<base::TimeTicks> update_layers_start_time_;
- base::Optional<base::TimeTicks> commit_compositor_frame_start_time_;
+ mojom::blink::PageLifecycleStatePtr lifecycle_state_;
mojo::AssociatedReceiver<mojom::blink::PageBroadcast> receiver_;
};
diff --git a/chromium/third_party/blink/renderer/core/exported/web_view_test.cc b/chromium/third_party/blink/renderer/core/exported/web_view_test.cc
index 5239942bb0d..cd29a295327 100644
--- a/chromium/third_party/blink/renderer/core/exported/web_view_test.cc
+++ b/chromium/third_party/blink/renderer/core/exported/web_view_test.cc
@@ -39,22 +39,25 @@
#include "base/test/test_mock_time_task_runner.h"
#include "base/time/time.h"
#include "build/build_config.h"
+#include "cc/test/test_ukm_recorder_factory.h"
#include "cc/trees/layer_tree_host.h"
#include "gin/handle.h"
#include "gin/object_template_builder.h"
#include "gin/wrappable.h"
+#include "mojo/public/cpp/bindings/pending_associated_receiver.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
-#include "third_party/blink/public/common/frame/frame_owner_element_type.h"
+#include "third_party/blink/public/common/input/web_coalesced_input_event.h"
#include "third_party/blink/public/common/input/web_input_event.h"
#include "third_party/blink/public/common/input/web_keyboard_event.h"
#include "third_party/blink/public/common/page/page_zoom.h"
+#include "third_party/blink/public/mojom/frame/frame_owner_element_type.mojom-blink.h"
+#include "third_party/blink/public/mojom/frame/tree_scope_type.mojom-blink.h"
#include "third_party/blink/public/mojom/input/focus_type.mojom-blink.h"
#include "third_party/blink/public/mojom/manifest/display_mode.mojom-shared.h"
-#include "third_party/blink/public/platform/web_coalesced_input_event.h"
#include "third_party/blink/public/platform/web_drag_data.h"
#include "third_party/blink/public/platform/web_drag_operation.h"
#include "third_party/blink/public/platform/web_size.h"
@@ -67,7 +70,6 @@
#include "third_party/blink/public/web/web_element.h"
#include "third_party/blink/public/web/web_frame.h"
#include "third_party/blink/public/web/web_frame_content_dumper.h"
-#include "third_party/blink/public/web/web_frame_widget.h"
#include "third_party/blink/public/web/web_hit_test_result.h"
#include "third_party/blink/public/web/web_input_method_controller.h"
#include "third_party/blink/public/web/web_local_frame.h"
@@ -75,11 +77,12 @@
#include "third_party/blink/public/web/web_print_params.h"
#include "third_party/blink/public/web/web_script_source.h"
#include "third_party/blink/public/web/web_settings.h"
-#include "third_party/blink/public/web/web_tree_scope_type.h"
#include "third_party/blink/public/web/web_view_client.h"
#include "third_party/blink/public/web/web_widget.h"
#include "third_party/blink/public/web/web_widget_client.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_document.h"
+#include "third_party/blink/renderer/core/css/media_query_list_listener.h"
+#include "third_party/blink/renderer/core/css/media_query_matcher.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/element.h"
#include "third_party/blink/renderer/core/dom/node_computed_style.h"
@@ -95,6 +98,7 @@
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
#include "third_party/blink/renderer/core/frame/settings.h"
#include "third_party/blink/renderer/core/frame/visual_viewport.h"
+#include "third_party/blink/renderer/core/frame/web_frame_widget_base.h"
#include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
#include "third_party/blink/renderer/core/fullscreen/fullscreen.h"
#include "third_party/blink/renderer/core/html/forms/external_date_time_chooser.h"
@@ -143,7 +147,7 @@
#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "ui/base/cursor/cursor.h"
-#include "ui/base/mojom/cursor_type.mojom-blink.h"
+#include "ui/base/cursor/mojom/cursor_type.mojom-blink.h"
#include "ui/events/keycodes/dom/dom_key.h"
#include "v8/include/v8.h"
@@ -215,10 +219,10 @@ class TapHandlingWebWidgetClient
// WebWidgetClient overrides.
void DidHandleGestureEvent(const WebGestureEvent& event,
bool event_cancelled) override {
- if (event.GetType() == WebInputEvent::kGestureTap) {
+ if (event.GetType() == WebInputEvent::Type::kGestureTap) {
tap_x_ = event.PositionInWidget().x();
tap_y_ = event.PositionInWidget().y();
- } else if (event.GetType() == WebInputEvent::kGestureLongPress) {
+ } else if (event.GetType() == WebInputEvent::Type::kGestureLongPress) {
longpress_x_ = event.PositionInWidget().x();
longpress_y_ = event.PositionInWidget().y();
}
@@ -318,14 +322,14 @@ class WebViewTest : public testing::Test {
};
static bool HitTestIsContentEditable(WebView* view, int x, int y) {
- gfx::Point hit_point(x, y);
+ gfx::PointF hit_point(x, y);
WebHitTestResult hit_test_result =
view->MainFrameWidget()->HitTestResultAt(hit_point);
return hit_test_result.IsContentEditable();
}
static std::string HitTestElementId(WebView* view, int x, int y) {
- gfx::Point hit_point(x, y);
+ gfx::PointF hit_point(x, y);
WebHitTestResult hit_test_result =
view->MainFrameWidget()->HitTestResultAt(hit_point);
return hit_test_result.GetNode().To<WebElement>().GetAttribute("id").Utf8();
@@ -381,14 +385,14 @@ TEST_F(WebViewTest, HitTestContentEditableImageMaps) {
}
static std::string HitTestAbsoluteUrl(WebView* view, int x, int y) {
- gfx::Point hit_point(x, y);
+ gfx::PointF hit_point(x, y);
WebHitTestResult hit_test_result =
view->MainFrameWidget()->HitTestResultAt(hit_point);
return hit_test_result.AbsoluteImageURL().GetString().Utf8();
}
static WebElement HitTestUrlElement(WebView* view, int x, int y) {
- gfx::Point hit_point(x, y);
+ gfx::PointF hit_point(x, y);
WebHitTestResult hit_test_result =
view->MainFrameWidget()->HitTestResultAt(hit_point);
return hit_test_result.UrlElement();
@@ -507,10 +511,9 @@ TEST_F(WebViewTest, SetBaseBackgroundColorBeforeMainFrame) {
// initialization code between WebView and WebLocalFrame creation.
frame_test_helpers::TestWebViewClient web_view_client;
frame_test_helpers::TestWebWidgetClient web_widget_client;
- WebViewImpl* web_view = static_cast<WebViewImpl*>(
- WebView::Create(&web_view_client, false,
- /*compositing_enabled=*/true, nullptr,
- mojo::ScopedInterfaceEndpointHandle()));
+ WebViewImpl* web_view = static_cast<WebViewImpl*>(WebView::Create(
+ &web_view_client, false,
+ /*compositing_enabled=*/true, nullptr, mojo::NullAssociatedReceiver()));
EXPECT_NE(SK_ColorBLUE, web_view->BackgroundColor());
// WebView does not have a frame yet, but we should still be able to set the
@@ -519,8 +522,9 @@ TEST_F(WebViewTest, SetBaseBackgroundColorBeforeMainFrame) {
EXPECT_EQ(SK_ColorBLUE, web_view->BackgroundColor());
frame_test_helpers::TestWebFrameClient web_frame_client;
- WebLocalFrame* frame = WebLocalFrame::CreateMainFrame(
- web_view, &web_frame_client, nullptr, nullptr);
+ WebLocalFrame* frame =
+ WebLocalFrame::CreateMainFrame(web_view, &web_frame_client, nullptr,
+ base::UnguessableToken::Create(), nullptr);
web_frame_client.Bind(frame);
{
@@ -532,8 +536,10 @@ TEST_F(WebViewTest, SetBaseBackgroundColorBeforeMainFrame) {
CrossVariantMojoAssociatedReceiver<mojom::FrameWidgetInterfaceBase>(),
CrossVariantMojoAssociatedRemote<mojom::WidgetHostInterfaceBase>(),
CrossVariantMojoAssociatedReceiver<mojom::WidgetInterfaceBase>());
- widget->SetCompositorHosts(web_widget_client.layer_tree_host(),
- web_widget_client.animation_host());
+ web_widget_client.set_layer_tree_host(widget->InitializeCompositing(
+ web_widget_client.task_graph_runner(),
+ frame_test_helpers::GetSynchronousSingleThreadLayerTreeSettings(),
+ std::make_unique<cc::TestUkmRecorderFactory>()));
widget->SetCompositorVisible(true);
web_view->DidAttachLocalMainFrame();
}
@@ -769,7 +775,7 @@ TEST_F(WebViewTest, HitTestResultAtWithPageScale) {
ToKURL(url), test::CoreTestDataPath("specify_size.html"));
WebView* web_view = web_view_helper_.InitializeAndLoad(url);
web_view->MainFrameWidget()->Resize(WebSize(100, 100));
- gfx::Point hit_point(75, 75);
+ gfx::PointF hit_point(75, 75);
// Image is at top left quandrant, so should not hit it.
WebHitTestResult negative_result =
@@ -793,7 +799,7 @@ TEST_F(WebViewTest, HitTestResultAtWithPageScaleAndPan) {
WebViewImpl* web_view = web_view_helper_.Initialize();
LoadFrame(web_view->MainFrameImpl(), url);
web_view->MainFrameWidget()->Resize(WebSize(100, 100));
- gfx::Point hit_point(75, 75);
+ gfx::PointF hit_point(75, 75);
// Image is at top left quandrant, so should not hit it.
WebHitTestResult negative_result = web_view->HitTestResultAt(hit_point);
@@ -823,7 +829,7 @@ TEST_F(WebViewTest, HitTestResultForTapWithTapArea) {
// Image is at top left quandrant, so should not hit it.
WebHitTestResult negative_result =
- web_view->MainFrameWidget()->HitTestResultAt(hit_point);
+ web_view->MainFrameWidget()->HitTestResultAt(gfx::PointF(hit_point));
EXPECT_FALSE(
negative_result.GetNode().To<WebElement>().HasHTMLTagName("img"));
negative_result.Reset();
@@ -852,7 +858,8 @@ TEST_F(WebViewTest, HitTestResultForTapWithTapAreaPageScaleAndPan) {
gfx::Point hit_point(55, 55);
// Image is at top left quandrant, so should not hit it.
- WebHitTestResult negative_result = web_view->HitTestResultAt(hit_point);
+ WebHitTestResult negative_result =
+ web_view->HitTestResultAt(gfx::PointF(hit_point));
EXPECT_FALSE(
negative_result.GetNode().To<WebElement>().HasHTMLTagName("img"));
negative_result.Reset();
@@ -1003,7 +1010,7 @@ void WebViewTest::TestTextInputType(WebTextInputType expected_type,
web_view->MainFrameImpl()->GetInputMethodController();
EXPECT_EQ(kWebTextInputTypeNone, controller->TextInputType());
EXPECT_EQ(kWebTextInputTypeNone, controller->TextInputInfo().type);
- web_view->SetInitialFocus(false);
+ web_view->MainFrameImpl()->GetFrame()->SetInitialFocus(false);
EXPECT_EQ(expected_type, controller->TextInputType());
EXPECT_EQ(expected_type, controller->TextInputInfo().type);
web_view->FocusedElement()->blur();
@@ -1040,7 +1047,7 @@ TEST_F(WebViewTest, TextInputInfoUpdateStyleAndLayout) {
"</svg>"
"<input>",
base_url);
- web_view_impl->SetInitialFocus(false);
+ web_view_impl->MainFrameImpl()->GetFrame()->SetInitialFocus(false);
// Add id="foo" to <path>, thus triggering the condition described above.
Document* document =
@@ -1061,7 +1068,7 @@ void WebViewTest::TestInputMode(WebTextInputMode expected_input_mode,
RegisterMockedHttpURLLoad(html_file);
WebViewImpl* web_view_impl =
web_view_helper_.InitializeAndLoad(base_url_ + html_file);
- web_view_impl->SetInitialFocus(false);
+ web_view_impl->MainFrameImpl()->GetFrame()->SetInitialFocus(false);
EXPECT_EQ(expected_input_mode, web_view_impl->MainFrameImpl()
->GetInputMethodController()
->TextInputInfo()
@@ -1096,7 +1103,7 @@ void WebViewTest::TestInputAction(ui::TextInputAction expected_input_action,
RegisterMockedHttpURLLoad(html_file);
WebViewImpl* web_view_impl =
web_view_helper_.InitializeAndLoad(base_url_ + html_file);
- web_view_impl->SetInitialFocus(false);
+ web_view_impl->MainFrameImpl()->GetFrame()->SetInitialFocus(false);
EXPECT_EQ(expected_input_action, web_view_impl->MainFrameImpl()
->GetInputMethodController()
->TextInputInfo()
@@ -1124,7 +1131,7 @@ TEST_F(WebViewTest, TextInputInfoWithReplacedElements) {
ToKURL("http://www.test.com/foo.png"),
test::CoreTestDataPath("white-1x1.png"));
WebViewImpl* web_view_impl = web_view_helper_.InitializeAndLoad(url);
- web_view_impl->SetInitialFocus(false);
+ web_view_impl->MainFrameImpl()->GetFrame()->SetInitialFocus(false);
WebTextInputInfo info = web_view_impl->MainFrameImpl()
->GetInputMethodController()
->TextInputInfo();
@@ -1136,7 +1143,7 @@ TEST_F(WebViewTest, SetEditableSelectionOffsetsAndTextInputInfo) {
RegisterMockedHttpURLLoad("input_field_populated.html");
WebViewImpl* web_view = web_view_helper_.InitializeAndLoad(
base_url_ + "input_field_populated.html");
- web_view->SetInitialFocus(false);
+ web_view->MainFrameImpl()->GetFrame()->SetInitialFocus(false);
WebLocalFrameImpl* frame = web_view->MainFrameImpl();
WebInputMethodController* active_input_method_controller =
frame->GetInputMethodController();
@@ -1152,7 +1159,7 @@ TEST_F(WebViewTest, SetEditableSelectionOffsetsAndTextInputInfo) {
RegisterMockedHttpURLLoad("content_editable_populated.html");
web_view = web_view_helper_.InitializeAndLoad(
base_url_ + "content_editable_populated.html");
- web_view->SetInitialFocus(false);
+ web_view->MainFrameImpl()->GetFrame()->SetInitialFocus(false);
frame = web_view->MainFrameImpl();
active_input_method_controller = frame->GetInputMethodController();
frame->SetEditableSelectionOffsets(8, 19);
@@ -1170,7 +1177,7 @@ TEST_F(WebViewTest, FinishComposingTextDoesNotAssert) {
RegisterMockedHttpURLLoad("input_field_default.html");
WebViewImpl* web_view = web_view_helper_.InitializeAndLoad(
base_url_ + "input_field_default.html");
- web_view->SetInitialFocus(false);
+ web_view->MainFrameImpl()->GetFrame()->SetInitialFocus(false);
WebInputMethodController* active_input_method_controller =
web_view->MainFrameImpl()
@@ -1201,7 +1208,7 @@ TEST_F(WebViewTest, LongPressOutsideInputShouldNotSelectPlaceholderText) {
RegisterMockedHttpURLLoad("input_placeholder.html");
WebViewImpl* web_view =
web_view_helper_.InitializeAndLoad(base_url_ + "input_placeholder.html");
- web_view->SetInitialFocus(false);
+ web_view->MainFrameImpl()->GetFrame()->SetInitialFocus(false);
web_view->MainFrameWidget()->Resize(WebSize(500, 300));
UpdateAllLifecyclePhases();
RunPendingTasks();
@@ -1209,17 +1216,17 @@ TEST_F(WebViewTest, LongPressOutsideInputShouldNotSelectPlaceholderText) {
WebString input_id = WebString::FromUTF8("input");
// Focus in input.
- EXPECT_TRUE(TapElementById(WebInputEvent::kGestureTap, input_id));
+ EXPECT_TRUE(TapElementById(WebInputEvent::Type::kGestureTap, input_id));
// Long press below input.
- WebGestureEvent event(WebInputEvent::kGestureLongPress,
+ WebGestureEvent event(WebInputEvent::Type::kGestureLongPress,
WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests(),
WebGestureDevice::kTouchscreen);
event.SetPositionInWidget(gfx::PointF(100, 150));
EXPECT_EQ(WebInputEventResult::kHandledSystem,
web_view->MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(event)));
+ WebCoalescedInputEvent(event, ui::LatencyInfo())));
EXPECT_TRUE(web_view->MainFrameImpl()->SelectionAsText().IsEmpty());
}
@@ -1227,7 +1234,7 @@ TEST_F(WebViewTest, FinishComposingTextCursorPositionChange) {
RegisterMockedHttpURLLoad("input_field_populated.html");
WebViewImpl* web_view = web_view_helper_.InitializeAndLoad(
base_url_ + "input_field_populated.html");
- web_view->SetInitialFocus(false);
+ web_view->MainFrameImpl()->GetFrame()->SetInitialFocus(false);
// Set up a composition that needs to be committed.
std::string composition_text("hello");
@@ -1279,7 +1286,7 @@ TEST_F(WebViewTest, SetCompositionForNewCaretPositions) {
RegisterMockedHttpURLLoad("input_field_populated.html");
WebViewImpl* web_view = web_view_helper_.InitializeAndLoad(
base_url_ + "input_field_populated.html");
- web_view->SetInitialFocus(false);
+ web_view->MainFrameImpl()->GetFrame()->SetInitialFocus(false);
WebInputMethodController* active_input_method_controller =
web_view->MainFrameImpl()
->FrameWidget()
@@ -1395,7 +1402,7 @@ TEST_F(WebViewTest, SetCompositionWithEmptyText) {
RegisterMockedHttpURLLoad("input_field_populated.html");
WebViewImpl* web_view = web_view_helper_.InitializeAndLoad(
base_url_ + "input_field_populated.html");
- web_view->SetInitialFocus(false);
+ web_view->MainFrameImpl()->GetFrame()->SetInitialFocus(false);
WebInputMethodController* active_input_method_controller =
web_view->MainFrameImpl()
->FrameWidget()
@@ -1436,7 +1443,7 @@ TEST_F(WebViewTest, CommitTextForNewCaretPositions) {
RegisterMockedHttpURLLoad("input_field_populated.html");
WebViewImpl* web_view = web_view_helper_.InitializeAndLoad(
base_url_ + "input_field_populated.html");
- web_view->SetInitialFocus(false);
+ web_view->MainFrameImpl()->GetFrame()->SetInitialFocus(false);
WebInputMethodController* active_input_method_controller =
web_view->MainFrameImpl()
->FrameWidget()
@@ -1509,7 +1516,7 @@ TEST_F(WebViewTest, CommitTextWhileComposing) {
RegisterMockedHttpURLLoad("input_field_populated.html");
WebViewImpl* web_view = web_view_helper_.InitializeAndLoad(
base_url_ + "input_field_populated.html");
- web_view->SetInitialFocus(false);
+ web_view->MainFrameImpl()->GetFrame()->SetInitialFocus(false);
WebInputMethodController* active_input_method_controller =
web_view->MainFrameImpl()
->FrameWidget()
@@ -1581,7 +1588,7 @@ TEST_F(WebViewTest, FinishCompositionDoesNotRevealSelection) {
WebViewImpl* web_view =
web_view_helper_.InitializeAndLoad(base_url_ + "form_with_input.html");
web_view->MainFrameWidget()->Resize(WebSize(800, 600));
- web_view->SetInitialFocus(false);
+ web_view->MainFrameImpl()->GetFrame()->SetInitialFocus(false);
EXPECT_EQ(0, web_view->MainFrameImpl()->GetScrollOffset().width);
EXPECT_EQ(0, web_view->MainFrameImpl()->GetScrollOffset().height);
@@ -1614,7 +1621,7 @@ TEST_F(WebViewTest, InsertNewLinePlacementAfterFinishComposingText) {
RegisterMockedHttpURLLoad("text_area_populated.html");
WebViewImpl* web_view = web_view_helper_.InitializeAndLoad(
base_url_ + "text_area_populated.html");
- web_view->SetInitialFocus(false);
+ web_view->MainFrameImpl()->GetFrame()->SetInitialFocus(false);
WebVector<WebImeTextSpan> empty_ime_text_spans;
@@ -1656,7 +1663,7 @@ TEST_F(WebViewTest, ExtendSelectionAndDelete) {
WebViewImpl* web_view = web_view_helper_.InitializeAndLoad(
base_url_ + "input_field_populated.html");
WebLocalFrameImpl* frame = web_view->MainFrameImpl();
- web_view->SetInitialFocus(false);
+ web_view->MainFrameImpl()->GetFrame()->SetInitialFocus(false);
frame->SetEditableSelectionOffsets(10, 10);
frame->ExtendSelectionAndDelete(5, 8);
WebInputMethodController* active_input_method_controller =
@@ -1672,12 +1679,12 @@ TEST_F(WebViewTest, ExtendSelectionAndDelete) {
TEST_F(WebViewTest, DeleteSurroundingText) {
RegisterMockedHttpURLLoad("input_field_populated.html");
- WebView* web_view = web_view_helper_.InitializeAndLoad(
+ WebViewImpl* web_view = web_view_helper_.InitializeAndLoad(
base_url_ + "input_field_populated.html");
auto* frame = To<WebLocalFrameImpl>(web_view->MainFrame());
WebInputMethodController* active_input_method_controller =
frame->GetInputMethodController();
- web_view->SetInitialFocus(false);
+ web_view->MainFrameImpl()->GetFrame()->SetInitialFocus(false);
frame->SetEditableSelectionOffsets(10, 10);
frame->DeleteSurroundingText(5, 8);
@@ -1717,7 +1724,7 @@ TEST_F(WebViewTest, SetCompositionFromExistingText) {
RegisterMockedHttpURLLoad("input_field_populated.html");
WebViewImpl* web_view = web_view_helper_.InitializeAndLoad(
base_url_ + "input_field_populated.html");
- web_view->SetInitialFocus(false);
+ web_view->MainFrameImpl()->GetFrame()->SetInitialFocus(false);
WebVector<WebImeTextSpan> ime_text_spans(static_cast<size_t>(1));
ime_text_spans[0] =
WebImeTextSpan(WebImeTextSpan::Type::kComposition, 0, 4,
@@ -1746,7 +1753,7 @@ TEST_F(WebViewTest, SetCompositionFromExistingTextInTextArea) {
RegisterMockedHttpURLLoad("text_area_populated.html");
WebViewImpl* web_view = web_view_helper_.InitializeAndLoad(
base_url_ + "text_area_populated.html");
- web_view->SetInitialFocus(false);
+ web_view->MainFrameImpl()->GetFrame()->SetInitialFocus(false);
WebVector<WebImeTextSpan> ime_text_spans(static_cast<size_t>(1));
ime_text_spans[0] =
WebImeTextSpan(WebImeTextSpan::Type::kComposition, 0, 4,
@@ -1789,7 +1796,7 @@ TEST_F(WebViewTest, SetCompositionFromExistingTextInRichText) {
RegisterMockedHttpURLLoad("content_editable_rich_text.html");
WebViewImpl* web_view = web_view_helper_.InitializeAndLoad(
base_url_ + "content_editable_rich_text.html");
- web_view->SetInitialFocus(false);
+ web_view->MainFrameImpl()->GetFrame()->SetInitialFocus(false);
WebVector<WebImeTextSpan> ime_text_spans(static_cast<size_t>(1));
ime_text_spans[0] =
WebImeTextSpan(WebImeTextSpan::Type::kComposition, 0, 4,
@@ -1807,7 +1814,7 @@ TEST_F(WebViewTest, SetEditableSelectionOffsetsKeepsComposition) {
RegisterMockedHttpURLLoad("input_field_populated.html");
WebViewImpl* web_view = web_view_helper_.InitializeAndLoad(
base_url_ + "input_field_populated.html");
- web_view->SetInitialFocus(false);
+ web_view->MainFrameImpl()->GetFrame()->SetInitialFocus(false);
std::string composition_text_first("hello ");
std::string composition_text_second("world");
@@ -1879,7 +1886,7 @@ TEST_F(WebViewTest, IsSelectionAnchorFirst) {
base_url_ + "input_field_populated.html");
WebLocalFrame* frame = web_view->MainFrameImpl();
- web_view->SetInitialFocus(false);
+ web_view->MainFrameImpl()->GetFrame()->SetInitialFocus(false);
frame->SetEditableSelectionOffsets(4, 10);
EXPECT_TRUE(frame->IsSelectionAnchorFirst());
WebRect anchor;
@@ -1898,7 +1905,7 @@ TEST_F(
RegisterMockedHttpURLLoad(test_file);
WebViewImpl* web_view =
web_view_helper_.InitializeAndLoad(base_url_ + test_file);
- web_view->SetInitialFocus(false);
+ web_view->MainFrameImpl()->GetFrame()->SetInitialFocus(false);
Document* document = web_view->MainFrameImpl()->GetFrame()->GetDocument();
WebInputMethodController* active_input_method_controller =
web_view->MainFrameImpl()
@@ -2138,7 +2145,7 @@ TEST_F(
RegisterMockedHttpURLLoad(test_file);
WebViewImpl* web_view =
web_view_helper_.InitializeAndLoad(base_url_ + test_file);
- web_view->SetInitialFocus(false);
+ web_view->MainFrameImpl()->GetFrame()->SetInitialFocus(false);
Document* document = web_view->MainFrameImpl()->GetFrame()->GetDocument();
WebInputMethodController* active_input_method_controller =
web_view->MainFrameImpl()
@@ -2241,7 +2248,7 @@ TEST_F(WebViewTest, MoveFocusToNextFocusableElementInFormWithTabIndexElements) {
RegisterMockedHttpURLLoad(test_file);
WebViewImpl* web_view =
web_view_helper_.InitializeAndLoad(base_url_ + test_file);
- web_view->SetInitialFocus(false);
+ web_view->MainFrameImpl()->GetFrame()->SetInitialFocus(false);
Document* document = web_view->MainFrameImpl()->GetFrame()->GetDocument();
WebInputMethodController* active_input_method_controller =
web_view->MainFrameImpl()
@@ -2344,7 +2351,7 @@ TEST_F(WebViewTest,
RegisterMockedHttpURLLoad(test_file);
WebViewImpl* web_view =
web_view_helper_.InitializeAndLoad(base_url_ + test_file);
- web_view->SetInitialFocus(false);
+ web_view->MainFrameImpl()->GetFrame()->SetInitialFocus(false);
Document* document = web_view->MainFrameImpl()->GetFrame()->GetDocument();
WebInputMethodController* active_input_method_controller =
web_view->MainFrameImpl()
@@ -2692,7 +2699,7 @@ bool WebViewTest::TapElement(WebInputEvent::Type type, Element* element) {
event.SetPositionInWidget(center);
web_view_helper_.GetWebView()->MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(event));
+ WebCoalescedInputEvent(event, ui::LatencyInfo()));
RunPendingTasks();
return true;
}
@@ -2726,18 +2733,21 @@ TEST_F(WebViewTest, ClientTapHandling) {
TapHandlingWebWidgetClient client;
WebView* web_view = web_view_helper_.InitializeAndLoad("about:blank", nullptr,
nullptr, &client);
- WebGestureEvent event(WebInputEvent::kGestureTap, WebInputEvent::kNoModifiers,
+ WebGestureEvent event(WebInputEvent::Type::kGestureTap,
+ WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests(),
WebGestureDevice::kTouchscreen);
event.SetPositionInWidget(gfx::PointF(3, 8));
- web_view->MainFrameWidget()->HandleInputEvent(WebCoalescedInputEvent(event));
+ web_view->MainFrameWidget()->HandleInputEvent(
+ WebCoalescedInputEvent(event, ui::LatencyInfo()));
RunPendingTasks();
EXPECT_EQ(3, client.TapX());
EXPECT_EQ(8, client.TapY());
client.Reset();
- event.SetType(WebInputEvent::kGestureLongPress);
+ event.SetType(WebInputEvent::Type::kGestureLongPress);
event.SetPositionInWidget(gfx::PointF(25, 7));
- web_view->MainFrameWidget()->HandleInputEvent(WebCoalescedInputEvent(event));
+ web_view->MainFrameWidget()->HandleInputEvent(
+ WebCoalescedInputEvent(event, ui::LatencyInfo()));
RunPendingTasks();
EXPECT_EQ(25, client.LongpressX());
EXPECT_EQ(7, client.LongpressY());
@@ -2749,14 +2759,14 @@ TEST_F(WebViewTest, ClientTapHandling) {
TEST_F(WebViewTest, ClientTapHandlingNullWebViewClient) {
// Note: this test doesn't use WebViewHelper since WebViewHelper creates an
// internal WebViewClient on demand if the supplied WebViewClient is null.
- WebViewImpl* web_view = static_cast<WebViewImpl*>(
- WebView::Create(nullptr, false,
- /*compositing_enabled=*/false, nullptr,
- mojo::ScopedInterfaceEndpointHandle()));
+ WebViewImpl* web_view = static_cast<WebViewImpl*>(WebView::Create(
+ nullptr, false,
+ /*compositing_enabled=*/false, nullptr, mojo::NullAssociatedReceiver()));
frame_test_helpers::TestWebFrameClient web_frame_client;
frame_test_helpers::TestWebWidgetClient web_widget_client;
- WebLocalFrame* local_frame = WebLocalFrame::CreateMainFrame(
- web_view, &web_frame_client, nullptr, nullptr);
+ WebLocalFrame* local_frame =
+ WebLocalFrame::CreateMainFrame(web_view, &web_frame_client, nullptr,
+ base::UnguessableToken::Create(), nullptr);
web_frame_client.Bind(local_frame);
blink::WebFrameWidget::CreateForMainFrame(
&web_widget_client, local_frame,
@@ -2765,13 +2775,14 @@ TEST_F(WebViewTest, ClientTapHandlingNullWebViewClient) {
CrossVariantMojoAssociatedRemote<mojom::WidgetHostInterfaceBase>(),
CrossVariantMojoAssociatedReceiver<mojom::WidgetInterfaceBase>());
- WebGestureEvent event(WebInputEvent::kGestureTap, WebInputEvent::kNoModifiers,
+ WebGestureEvent event(WebInputEvent::Type::kGestureTap,
+ WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests(),
WebGestureDevice::kTouchscreen);
event.SetPositionInWidget(gfx::PointF(3, 8));
EXPECT_EQ(WebInputEventResult::kNotHandled,
web_view->MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(event)));
+ WebCoalescedInputEvent(event, ui::LatencyInfo())));
web_view->Close();
}
@@ -2785,7 +2796,7 @@ TEST_F(WebViewTest, LongPressEmptyDiv) {
UpdateAllLifecyclePhases();
RunPendingTasks();
- WebGestureEvent event(WebInputEvent::kGestureLongPress,
+ WebGestureEvent event(WebInputEvent::Type::kGestureLongPress,
WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests(),
WebGestureDevice::kTouchscreen);
@@ -2793,7 +2804,7 @@ TEST_F(WebViewTest, LongPressEmptyDiv) {
EXPECT_EQ(WebInputEventResult::kNotHandled,
web_view->MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(event)));
+ WebCoalescedInputEvent(event, ui::LatencyInfo())));
}
TEST_F(WebViewTest, LongPressEmptyDivAlwaysShow) {
@@ -2806,7 +2817,7 @@ TEST_F(WebViewTest, LongPressEmptyDivAlwaysShow) {
UpdateAllLifecyclePhases();
RunPendingTasks();
- WebGestureEvent event(WebInputEvent::kGestureLongPress,
+ WebGestureEvent event(WebInputEvent::Type::kGestureLongPress,
WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests(),
WebGestureDevice::kTouchscreen);
@@ -2814,7 +2825,7 @@ TEST_F(WebViewTest, LongPressEmptyDivAlwaysShow) {
EXPECT_EQ(WebInputEventResult::kHandledSystem,
web_view->MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(event)));
+ WebCoalescedInputEvent(event, ui::LatencyInfo())));
}
TEST_F(WebViewTest, LongPressObject) {
@@ -2827,7 +2838,7 @@ TEST_F(WebViewTest, LongPressObject) {
UpdateAllLifecyclePhases();
RunPendingTasks();
- WebGestureEvent event(WebInputEvent::kGestureLongPress,
+ WebGestureEvent event(WebInputEvent::Type::kGestureLongPress,
WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests(),
WebGestureDevice::kTouchscreen);
@@ -2835,7 +2846,7 @@ TEST_F(WebViewTest, LongPressObject) {
EXPECT_NE(WebInputEventResult::kHandledSystem,
web_view->MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(event)));
+ WebCoalescedInputEvent(event, ui::LatencyInfo())));
auto* element = To<HTMLElement>(static_cast<Node*>(
web_view->MainFrameImpl()->GetDocument().GetElementById("obj")));
@@ -2852,7 +2863,7 @@ TEST_F(WebViewTest, LongPressObjectFallback) {
UpdateAllLifecyclePhases();
RunPendingTasks();
- WebGestureEvent event(WebInputEvent::kGestureLongPress,
+ WebGestureEvent event(WebInputEvent::Type::kGestureLongPress,
WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests(),
WebGestureDevice::kTouchscreen);
@@ -2860,7 +2871,7 @@ TEST_F(WebViewTest, LongPressObjectFallback) {
EXPECT_EQ(WebInputEventResult::kHandledSystem,
web_view->MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(event)));
+ WebCoalescedInputEvent(event, ui::LatencyInfo())));
auto* element = To<HTMLElement>(static_cast<Node*>(
web_view->MainFrameImpl()->GetDocument().GetElementById("obj")));
@@ -2877,7 +2888,7 @@ TEST_F(WebViewTest, LongPressImage) {
UpdateAllLifecyclePhases();
RunPendingTasks();
- WebGestureEvent event(WebInputEvent::kGestureLongPress,
+ WebGestureEvent event(WebInputEvent::Type::kGestureLongPress,
WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests(),
WebGestureDevice::kTouchscreen);
@@ -2885,7 +2896,7 @@ TEST_F(WebViewTest, LongPressImage) {
EXPECT_EQ(WebInputEventResult::kHandledSystem,
web_view->MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(event)));
+ WebCoalescedInputEvent(event, ui::LatencyInfo())));
EXPECT_TRUE(
web_view->AsView()
.page->GetContextMenuController()
@@ -2902,7 +2913,7 @@ TEST_F(WebViewTest, LongPressVideo) {
UpdateAllLifecyclePhases();
RunPendingTasks();
- WebGestureEvent event(WebInputEvent::kGestureLongPress,
+ WebGestureEvent event(WebInputEvent::Type::kGestureLongPress,
WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests(),
WebGestureDevice::kTouchscreen);
@@ -2910,7 +2921,7 @@ TEST_F(WebViewTest, LongPressVideo) {
EXPECT_EQ(WebInputEventResult::kHandledSystem,
web_view->MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(event)));
+ WebCoalescedInputEvent(event, ui::LatencyInfo())));
}
TEST_F(WebViewTest, LongPressLink) {
@@ -2923,7 +2934,7 @@ TEST_F(WebViewTest, LongPressLink) {
UpdateAllLifecyclePhases();
RunPendingTasks();
- WebGestureEvent event(WebInputEvent::kGestureLongPress,
+ WebGestureEvent event(WebInputEvent::Type::kGestureLongPress,
WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests(),
WebGestureDevice::kTouchscreen);
@@ -2931,7 +2942,7 @@ TEST_F(WebViewTest, LongPressLink) {
EXPECT_EQ(WebInputEventResult::kHandledSystem,
web_view->MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(event)));
+ WebCoalescedInputEvent(event, ui::LatencyInfo())));
}
// Tests that we send touchcancel when drag start by long press.
@@ -2950,27 +2961,28 @@ TEST_F(WebViewTest, TouchCancelOnStartDragging) {
RunPendingTasks();
WebPointerEvent pointer_down(
- WebInputEvent::kPointerDown,
+ WebInputEvent::Type::kPointerDown,
WebPointerProperties(1, WebPointerProperties::PointerType::kTouch), 5, 5);
pointer_down.SetPositionInWidget(250, 8);
web_view->MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(pointer_down));
+ WebCoalescedInputEvent(pointer_down, ui::LatencyInfo()));
web_view->MainFrameWidget()->DispatchBufferedTouchEvents();
WebString target_id = WebString::FromUTF8("target");
// Send long press to start dragging
- EXPECT_TRUE(TapElementById(WebInputEvent::kGestureLongPress, target_id));
+ EXPECT_TRUE(
+ TapElementById(WebInputEvent::Type::kGestureLongPress, target_id));
EXPECT_EQ("dragstart", web_view->MainFrameImpl()->GetDocument().Title());
// Check pointer cancel is sent to dom.
WebPointerEvent pointer_cancel(
- WebInputEvent::kPointerCancel,
+ WebInputEvent::Type::kPointerCancel,
WebPointerProperties(1, WebPointerProperties::PointerType::kTouch), 5, 5);
pointer_cancel.SetPositionInWidget(250, 8);
EXPECT_NE(WebInputEventResult::kHandledSuppressed,
web_view->MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(pointer_cancel)));
+ WebCoalescedInputEvent(pointer_cancel, ui::LatencyInfo())));
web_view->MainFrameWidget()->DispatchBufferedTouchEvents();
EXPECT_EQ("touchcancel", web_view->MainFrameImpl()->GetDocument().Title());
}
@@ -2992,11 +3004,13 @@ TEST_F(WebViewTest, showContextMenuOnLongPressingLinks) {
WebString anchor_tag_id = WebString::FromUTF8("anchorTag");
WebString image_tag_id = WebString::FromUTF8("imageTag");
- EXPECT_TRUE(TapElementById(WebInputEvent::kGestureLongPress, anchor_tag_id));
+ EXPECT_TRUE(
+ TapElementById(WebInputEvent::Type::kGestureLongPress, anchor_tag_id));
EXPECT_EQ("anchor contextmenu",
web_view->MainFrameImpl()->GetDocument().Title());
- EXPECT_TRUE(TapElementById(WebInputEvent::kGestureLongPress, image_tag_id));
+ EXPECT_TRUE(
+ TapElementById(WebInputEvent::Type::kGestureLongPress, image_tag_id));
EXPECT_EQ("image contextmenu",
web_view->MainFrameImpl()->GetDocument().Title());
}
@@ -3011,7 +3025,7 @@ TEST_F(WebViewTest, LongPressEmptyEditableSelection) {
UpdateAllLifecyclePhases();
RunPendingTasks();
- WebGestureEvent event(WebInputEvent::kGestureLongPress,
+ WebGestureEvent event(WebInputEvent::Type::kGestureLongPress,
WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests(),
WebGestureDevice::kTouchscreen);
@@ -3019,7 +3033,7 @@ TEST_F(WebViewTest, LongPressEmptyEditableSelection) {
EXPECT_EQ(WebInputEventResult::kHandledSystem,
web_view->MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(event)));
+ WebCoalescedInputEvent(event, ui::LatencyInfo())));
}
TEST_F(WebViewTest, LongPressEmptyNonEditableSelection) {
@@ -3031,7 +3045,7 @@ TEST_F(WebViewTest, LongPressEmptyNonEditableSelection) {
UpdateAllLifecyclePhases();
RunPendingTasks();
- WebGestureEvent event(WebInputEvent::kGestureLongPress,
+ WebGestureEvent event(WebInputEvent::Type::kGestureLongPress,
WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests(),
WebGestureDevice::kTouchscreen);
@@ -3040,7 +3054,7 @@ TEST_F(WebViewTest, LongPressEmptyNonEditableSelection) {
EXPECT_EQ(WebInputEventResult::kHandledSystem,
web_view->MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(event)));
+ WebCoalescedInputEvent(event, ui::LatencyInfo())));
EXPECT_TRUE(frame->SelectionAsText().IsEmpty());
}
@@ -3057,10 +3071,10 @@ TEST_F(WebViewTest, LongPressSelection) {
WebString onselectstartfalse = WebString::FromUTF8("onselectstartfalse");
WebLocalFrameImpl* frame = web_view->MainFrameImpl();
- EXPECT_TRUE(
- TapElementById(WebInputEvent::kGestureLongPress, onselectstartfalse));
+ EXPECT_TRUE(TapElementById(WebInputEvent::Type::kGestureLongPress,
+ onselectstartfalse));
EXPECT_EQ("", frame->SelectionAsText().Utf8());
- EXPECT_TRUE(TapElementById(WebInputEvent::kGestureLongPress, target));
+ EXPECT_TRUE(TapElementById(WebInputEvent::Type::kGestureLongPress, target));
EXPECT_EQ("testword", frame->SelectionAsText().Utf8());
}
@@ -3077,7 +3091,7 @@ TEST_F(WebViewTest, FinishComposingTextDoesNotDismissHandles) {
WebLocalFrameImpl* frame = web_view->MainFrameImpl();
WebInputMethodController* active_input_method_controller =
frame->FrameWidget()->GetActiveWebInputMethodController();
- EXPECT_TRUE(TapElementById(WebInputEvent::kGestureTap, target));
+ EXPECT_TRUE(TapElementById(WebInputEvent::Type::kGestureTap, target));
WebVector<WebImeTextSpan> empty_ime_text_spans;
frame->SetEditableSelectionOffsets(8, 8);
EXPECT_TRUE(active_input_method_controller->SetComposition(
@@ -3087,7 +3101,7 @@ TEST_F(WebViewTest, FinishComposingTextDoesNotDismissHandles) {
EXPECT_FALSE(frame->GetFrame()->Selection().IsHandleVisible());
EXPECT_TRUE(frame->GetFrame()->GetInputMethodController().HasComposition());
- EXPECT_TRUE(TapElementById(WebInputEvent::kGestureLongPress, target));
+ EXPECT_TRUE(TapElementById(WebInputEvent::Type::kGestureLongPress, target));
EXPECT_EQ("testword12345", frame->SelectionAsText().Utf8());
EXPECT_TRUE(frame->GetFrame()->Selection().IsHandleVisible());
EXPECT_TRUE(frame->GetFrame()->GetInputMethodController().HasComposition());
@@ -3112,18 +3126,20 @@ TEST_F(WebViewTest, TouchDoesntSelectEmptyTextarea) {
WebLocalFrameImpl* frame = web_view->MainFrameImpl();
// Long-press on carriage returns.
- EXPECT_TRUE(
- TapElementById(WebInputEvent::kGestureLongPress, blanklinestextbox));
+ EXPECT_TRUE(TapElementById(WebInputEvent::Type::kGestureLongPress,
+ blanklinestextbox));
EXPECT_TRUE(frame->SelectionAsText().IsEmpty());
// Double-tap on carriage returns.
- WebGestureEvent event(WebInputEvent::kGestureTap, WebInputEvent::kNoModifiers,
+ WebGestureEvent event(WebInputEvent::Type::kGestureTap,
+ WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests(),
WebGestureDevice::kTouchscreen);
event.SetPositionInWidget(gfx::PointF(100, 25));
event.data.tap.tap_count = 2;
- web_view->MainFrameWidget()->HandleInputEvent(WebCoalescedInputEvent(event));
+ web_view->MainFrameWidget()->HandleInputEvent(
+ WebCoalescedInputEvent(event, ui::LatencyInfo()));
EXPECT_TRUE(frame->SelectionAsText().IsEmpty());
auto* text_area_element = To<HTMLTextAreaElement>(static_cast<Node*>(
@@ -3132,12 +3148,13 @@ TEST_F(WebViewTest, TouchDoesntSelectEmptyTextarea) {
text_area_element->setValue("hello");
// Long-press past last word of textbox.
- EXPECT_TRUE(
- TapElementById(WebInputEvent::kGestureLongPress, blanklinestextbox));
+ EXPECT_TRUE(TapElementById(WebInputEvent::Type::kGestureLongPress,
+ blanklinestextbox));
EXPECT_TRUE(frame->SelectionAsText().IsEmpty());
// Double-tap past last word of textbox.
- web_view->MainFrameWidget()->HandleInputEvent(WebCoalescedInputEvent(event));
+ web_view->MainFrameWidget()->HandleInputEvent(
+ WebCoalescedInputEvent(event, ui::LatencyInfo()));
EXPECT_TRUE(frame->SelectionAsText().IsEmpty());
}
#endif
@@ -3153,7 +3170,7 @@ TEST_F(WebViewTest, LongPressImageTextarea) {
WebString image = WebString::FromUTF8("purpleimage");
- EXPECT_TRUE(TapElementById(WebInputEvent::kGestureLongPress, image));
+ EXPECT_TRUE(TapElementById(WebInputEvent::Type::kGestureLongPress, image));
WebRange range = web_view->MainFrameImpl()
->GetInputMethodController()
->GetSelectionOffsets();
@@ -3174,7 +3191,7 @@ TEST_F(WebViewTest, BlinkCaretAfterLongPress) {
WebString target = WebString::FromUTF8("target");
WebLocalFrameImpl* main_frame = web_view->MainFrameImpl();
- EXPECT_TRUE(TapElementById(WebInputEvent::kGestureLongPress, target));
+ EXPECT_TRUE(TapElementById(WebInputEvent::Type::kGestureLongPress, target));
EXPECT_FALSE(main_frame->GetFrame()->Selection().IsCaretBlinkingSuspended());
}
@@ -3183,13 +3200,13 @@ TEST_F(WebViewTest, BlinkCaretOnClosingContextMenu) {
WebViewImpl* web_view =
web_view_helper_.InitializeAndLoad(base_url_ + "form.html");
- web_view->SetInitialFocus(false);
+ web_view->MainFrameImpl()->GetFrame()->SetInitialFocus(false);
RunPendingTasks();
// We suspend caret blinking when pressing with mouse right button.
// Note that we do not send MouseUp event here since it will be consumed
// by the context menu once it shows up.
- WebMouseEvent mouse_event(WebInputEvent::kMouseDown,
+ WebMouseEvent mouse_event(WebInputEvent::Type::kMouseDown,
WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests());
@@ -3197,7 +3214,7 @@ TEST_F(WebViewTest, BlinkCaretOnClosingContextMenu) {
mouse_event.SetPositionInWidget(1, 1);
mouse_event.click_count = 1;
web_view->MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(mouse_event));
+ WebCoalescedInputEvent(mouse_event, ui::LatencyInfo()));
RunPendingTasks();
WebLocalFrameImpl* main_frame = web_view->MainFrameImpl();
@@ -3243,7 +3260,7 @@ TEST_F(WebViewTest, KeyDownScrollsHandled) {
UpdateAllLifecyclePhases();
RunPendingTasks();
- WebKeyboardEvent key_event(WebInputEvent::kRawKeyDown,
+ WebKeyboardEvent key_event(WebInputEvent::Type::kRawKeyDown,
WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests());
@@ -3251,73 +3268,73 @@ TEST_F(WebViewTest, KeyDownScrollsHandled) {
key_event.windows_key_code = VKEY_NEXT;
EXPECT_EQ(WebInputEventResult::kHandledSystem,
web_view->MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(key_event)));
- key_event.SetType(WebInputEvent::kKeyUp);
+ WebCoalescedInputEvent(key_event, ui::LatencyInfo())));
+ key_event.SetType(WebInputEvent::Type::kKeyUp);
web_view->MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(key_event));
+ WebCoalescedInputEvent(key_event, ui::LatencyInfo()));
// Coalesced KeyDown arrow-down should be handled.
key_event.windows_key_code = VKEY_DOWN;
- key_event.SetType(WebInputEvent::kKeyDown);
+ key_event.SetType(WebInputEvent::Type::kKeyDown);
EXPECT_EQ(WebInputEventResult::kHandledSystem,
web_view->MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(key_event)));
- key_event.SetType(WebInputEvent::kKeyUp);
+ WebCoalescedInputEvent(key_event, ui::LatencyInfo())));
+ key_event.SetType(WebInputEvent::Type::kKeyUp);
web_view->MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(key_event));
+ WebCoalescedInputEvent(key_event, ui::LatencyInfo()));
// Ctrl-Home should be handled...
key_event.windows_key_code = VKEY_HOME;
key_event.SetModifiers(WebInputEvent::kControlKey);
- key_event.SetType(WebInputEvent::kRawKeyDown);
+ key_event.SetType(WebInputEvent::Type::kRawKeyDown);
EXPECT_EQ(WebInputEventResult::kNotHandled,
web_view->MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(key_event)));
- key_event.SetType(WebInputEvent::kKeyUp);
+ WebCoalescedInputEvent(key_event, ui::LatencyInfo())));
+ key_event.SetType(WebInputEvent::Type::kKeyUp);
web_view->MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(key_event));
+ WebCoalescedInputEvent(key_event, ui::LatencyInfo()));
// But Ctrl-Down should not.
key_event.windows_key_code = VKEY_DOWN;
key_event.SetModifiers(WebInputEvent::kControlKey);
- key_event.SetType(WebInputEvent::kRawKeyDown);
+ key_event.SetType(WebInputEvent::Type::kRawKeyDown);
EXPECT_EQ(WebInputEventResult::kNotHandled,
web_view->MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(key_event)));
- key_event.SetType(WebInputEvent::kKeyUp);
+ WebCoalescedInputEvent(key_event, ui::LatencyInfo())));
+ key_event.SetType(WebInputEvent::Type::kKeyUp);
web_view->MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(key_event));
+ WebCoalescedInputEvent(key_event, ui::LatencyInfo()));
// Shift, meta, and alt should not be handled.
key_event.windows_key_code = VKEY_NEXT;
key_event.SetModifiers(WebInputEvent::kShiftKey);
- key_event.SetType(WebInputEvent::kRawKeyDown);
+ key_event.SetType(WebInputEvent::Type::kRawKeyDown);
EXPECT_EQ(WebInputEventResult::kNotHandled,
web_view->MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(key_event)));
- key_event.SetType(WebInputEvent::kKeyUp);
+ WebCoalescedInputEvent(key_event, ui::LatencyInfo())));
+ key_event.SetType(WebInputEvent::Type::kKeyUp);
web_view->MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(key_event));
+ WebCoalescedInputEvent(key_event, ui::LatencyInfo()));
key_event.windows_key_code = VKEY_NEXT;
key_event.SetModifiers(WebInputEvent::kMetaKey);
- key_event.SetType(WebInputEvent::kRawKeyDown);
+ key_event.SetType(WebInputEvent::Type::kRawKeyDown);
EXPECT_EQ(WebInputEventResult::kNotHandled,
web_view->MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(key_event)));
- key_event.SetType(WebInputEvent::kKeyUp);
+ WebCoalescedInputEvent(key_event, ui::LatencyInfo())));
+ key_event.SetType(WebInputEvent::Type::kKeyUp);
web_view->MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(key_event));
+ WebCoalescedInputEvent(key_event, ui::LatencyInfo()));
key_event.windows_key_code = VKEY_NEXT;
key_event.SetModifiers(WebInputEvent::kAltKey);
- key_event.SetType(WebInputEvent::kRawKeyDown);
+ key_event.SetType(WebInputEvent::Type::kRawKeyDown);
EXPECT_EQ(WebInputEventResult::kNotHandled,
web_view->MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(key_event)));
- key_event.SetType(WebInputEvent::kKeyUp);
+ WebCoalescedInputEvent(key_event, ui::LatencyInfo())));
+ key_event.SetType(WebInputEvent::Type::kKeyUp);
web_view->MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(key_event));
+ WebCoalescedInputEvent(key_event, ui::LatencyInfo()));
// System-key labeled Alt-Down (as in Windows) should do nothing,
// but non-system-key labeled Alt-Down (as in Mac) should be handled
@@ -3325,24 +3342,24 @@ TEST_F(WebViewTest, KeyDownScrollsHandled) {
key_event.windows_key_code = VKEY_DOWN;
key_event.SetModifiers(WebInputEvent::kAltKey);
key_event.is_system_key = true;
- key_event.SetType(WebInputEvent::kRawKeyDown);
+ key_event.SetType(WebInputEvent::Type::kRawKeyDown);
EXPECT_EQ(WebInputEventResult::kNotHandled,
web_view->MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(key_event)));
- key_event.SetType(WebInputEvent::kKeyUp);
+ WebCoalescedInputEvent(key_event, ui::LatencyInfo())));
+ key_event.SetType(WebInputEvent::Type::kKeyUp);
web_view->MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(key_event));
+ WebCoalescedInputEvent(key_event, ui::LatencyInfo()));
key_event.windows_key_code = VKEY_DOWN;
key_event.SetModifiers(WebInputEvent::kAltKey);
key_event.is_system_key = false;
- key_event.SetType(WebInputEvent::kRawKeyDown);
+ key_event.SetType(WebInputEvent::Type::kRawKeyDown);
EXPECT_EQ(WebInputEventResult::kHandledSystem,
web_view->MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(key_event)));
- key_event.SetType(WebInputEvent::kKeyUp);
+ WebCoalescedInputEvent(key_event, ui::LatencyInfo())));
+ key_event.SetType(WebInputEvent::Type::kKeyUp);
web_view->MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(key_event));
+ WebCoalescedInputEvent(key_event, ui::LatencyInfo()));
}
class MiddleClickAutoscrollWebWidgetClient
@@ -3401,7 +3418,7 @@ TEST_F(WebViewTest, MiddleClickAutoscrollCursor) {
PageTestBase::MockClipboardHostProvider mock_clip_host_provider(
local_frame->GetBrowserInterfaceBroker());
- WebMouseEvent mouse_event(WebInputEvent::kMouseDown,
+ WebMouseEvent mouse_event(WebInputEvent::Type::kMouseDown,
WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests());
mouse_event.button = WebMouseEvent::Button::kMiddle;
@@ -3410,10 +3427,10 @@ TEST_F(WebViewTest, MiddleClickAutoscrollCursor) {
// Start middle-click autoscroll.
web_view->MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(mouse_event));
- mouse_event.SetType(WebInputEvent::kMouseUp);
+ WebCoalescedInputEvent(mouse_event, ui::LatencyInfo()));
+ mouse_event.SetType(WebInputEvent::Type::kMouseUp);
web_view->MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(mouse_event));
+ WebCoalescedInputEvent(mouse_event, ui::LatencyInfo()));
EXPECT_EQ(current_test.expected_cursor, client.GetLastCursorType());
@@ -3424,12 +3441,12 @@ TEST_F(WebViewTest, MiddleClickAutoscrollCursor) {
EXPECT_EQ(current_test.expected_cursor, client.GetLastCursorType());
// End middle-click autoscroll.
- mouse_event.SetType(WebInputEvent::kMouseDown);
+ mouse_event.SetType(WebInputEvent::Type::kMouseDown);
web_view->MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(mouse_event));
- mouse_event.SetType(WebInputEvent::kMouseUp);
+ WebCoalescedInputEvent(mouse_event, ui::LatencyInfo()));
+ mouse_event.SetType(WebInputEvent::Type::kMouseUp);
web_view->MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(mouse_event));
+ WebCoalescedInputEvent(mouse_event, ui::LatencyInfo()));
web_view->GetChromeClient().SetCursorForPlugin(IBeamCursor(), local_frame);
EXPECT_EQ(IBeamCursor().type(), client.GetLastCursorType());
@@ -3460,7 +3477,7 @@ TEST_F(WebViewTest, ShowPressOnTransformedLink) {
"highlight</a>",
base_url);
- WebGestureEvent event(WebInputEvent::kGestureShowPress,
+ WebGestureEvent event(WebInputEvent::Type::kGestureShowPress,
WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests(),
WebGestureDevice::kTouchscreen);
@@ -3468,7 +3485,7 @@ TEST_F(WebViewTest, ShowPressOnTransformedLink) {
// Just make sure we don't hit any asserts.
web_view_impl->MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(event));
+ WebCoalescedInputEvent(event, ui::LatencyInfo()));
}
class MockAutofillClient : public WebAutofillClient {
@@ -3510,7 +3527,7 @@ TEST_F(WebViewTest, LosingFocusDoesNotTriggerAutofillTextChange) {
base_url_ + "input_field_populated.html");
WebLocalFrameImpl* frame = web_view->MainFrameImpl();
frame->SetAutofillClient(&client);
- web_view->SetInitialFocus(false);
+ web_view->MainFrameImpl()->GetFrame()->SetInitialFocus(false);
// Set up a composition that needs to be committed.
WebVector<WebImeTextSpan> empty_ime_text_spans;
@@ -3552,7 +3569,7 @@ TEST_F(WebViewTest, CompositionNotCancelledByBackspace) {
base_url_ + "composition_not_cancelled_by_backspace.html");
WebLocalFrameImpl* frame = web_view->MainFrameImpl();
frame->SetAutofillClient(&client);
- web_view->SetInitialFocus(false);
+ web_view->MainFrameImpl()->GetFrame()->SetInitialFocus(false);
// Test both input elements.
for (int i = 0; i < 2; ++i) {
@@ -3568,13 +3585,13 @@ TEST_F(WebViewTest, CompositionNotCancelledByBackspace) {
// Press Backspace and verify composition didn't get cancelled. This is to
// verify the fix for crbug.com/429916.
- WebKeyboardEvent key_event(WebInputEvent::kRawKeyDown,
+ WebKeyboardEvent key_event(WebInputEvent::Type::kRawKeyDown,
WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests());
key_event.dom_key = ui::DomKey::BACKSPACE;
key_event.windows_key_code = VKEY_BACK;
web_view->MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(key_event));
+ WebCoalescedInputEvent(key_event, ui::LatencyInfo()));
frame->SetEditableSelectionOffsets(6, 6);
EXPECT_TRUE(active_input_method_controller->SetComposition(
@@ -3583,9 +3600,9 @@ TEST_F(WebViewTest, CompositionNotCancelledByBackspace) {
VerifySelectionAndComposition(web_view, 10, 10, 6, 10,
"after pressing Backspace");
- key_event.SetType(WebInputEvent::kKeyUp);
+ key_event.SetType(WebInputEvent::Type::kKeyUp);
web_view->MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(key_event));
+ WebCoalescedInputEvent(key_event, ui::LatencyInfo()));
web_view->AdvanceFocus(false);
}
@@ -3600,7 +3617,7 @@ TEST_F(WebViewTest, FinishComposingTextDoesntTriggerAutofillTextChange) {
base_url_ + "input_field_populated.html");
WebLocalFrameImpl* frame = web_view->MainFrameImpl();
frame->SetAutofillClient(&client);
- web_view->SetInitialFocus(false);
+ web_view->MainFrameImpl()->GetFrame()->SetInitialFocus(false);
WebDocument document = web_view->MainFrameImpl()->GetDocument();
auto* form = To<HTMLFormControlElement>(
@@ -3642,7 +3659,7 @@ TEST_F(WebViewTest,
base_url_ + "input_field_populated.html");
WebLocalFrameImpl* frame = web_view->MainFrameImpl();
frame->SetAutofillClient(&client);
- web_view->SetInitialFocus(false);
+ web_view->MainFrameImpl()->GetFrame()->SetInitialFocus(false);
WebVector<WebImeTextSpan> empty_ime_text_spans;
@@ -3673,7 +3690,7 @@ class ViewCreatingWebViewClient : public frame_test_helpers::TestWebViewClient {
const WebWindowFeatures&,
const WebString& name,
WebNavigationPolicy,
- mojom::blink::WebSandboxFlags,
+ network::mojom::blink::WebSandboxFlags,
const FeaturePolicy::FeatureState&,
const SessionStorageNamespaceId&) override {
return web_view_helper_.InitializeWithOpener(opener);
@@ -3757,7 +3774,7 @@ class ViewReusingWebViewClient : public frame_test_helpers::TestWebViewClient {
const WebWindowFeatures&,
const WebString& name,
WebNavigationPolicy,
- mojom::blink::WebSandboxFlags,
+ network::mojom::blink::WebSandboxFlags,
const FeaturePolicy::FeatureState&,
const SessionStorageNamespaceId&) override {
return web_view_;
@@ -3821,17 +3838,17 @@ static void OpenDateTimeChooser(WebView* web_view,
HTMLInputElement* input_element) {
input_element->focus();
- WebKeyboardEvent key_event(WebInputEvent::kRawKeyDown,
+ WebKeyboardEvent key_event(WebInputEvent::Type::kRawKeyDown,
WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests());
key_event.dom_key = ui::DomKey::FromCharacter(' ');
key_event.windows_key_code = VKEY_SPACE;
web_view->MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(key_event));
+ WebCoalescedInputEvent(key_event, ui::LatencyInfo()));
- key_event.SetType(WebInputEvent::kKeyUp);
+ key_event.SetType(WebInputEvent::Type::kKeyUp);
web_view->MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(key_event));
+ WebCoalescedInputEvent(key_event, ui::LatencyInfo()));
}
TEST_F(WebViewTest, ChooseValueFromDateTimeChooser) {
@@ -3919,12 +3936,12 @@ class CreateChildCounterFrameClient
public:
CreateChildCounterFrameClient() : count_(0) {}
WebLocalFrame* CreateChildFrame(WebLocalFrame* parent,
- WebTreeScopeType,
+ mojom::blink::TreeScopeType,
const WebString& name,
const WebString& fallback_name,
const FramePolicy&,
const WebFrameOwnerProperties&,
- FrameOwnerElementType) override;
+ mojom::blink::FrameOwnerElementType) override;
int Count() const { return count_; }
@@ -3934,12 +3951,12 @@ class CreateChildCounterFrameClient
WebLocalFrame* CreateChildCounterFrameClient::CreateChildFrame(
WebLocalFrame* parent,
- WebTreeScopeType scope,
+ mojom::blink::TreeScopeType scope,
const WebString& name,
const WebString& fallback_name,
const FramePolicy& frame_policy,
const WebFrameOwnerProperties& frame_owner_properties,
- FrameOwnerElementType frame_owner_element_type) {
+ mojom::blink::FrameOwnerElementType frame_owner_element_type) {
++count_;
return TestWebFrameClient::CreateChildFrame(
parent, scope, name, fallback_name, frame_policy, frame_owner_properties,
@@ -3948,19 +3965,70 @@ WebLocalFrame* CreateChildCounterFrameClient::CreateChildFrame(
TEST_F(WebViewTest, ChangeDisplayMode) {
RegisterMockedHttpURLLoad("display_mode.html");
- WebView* web_view =
+ WebViewImpl* web_view =
web_view_helper_.InitializeAndLoad(base_url_ + "display_mode.html");
- std::string content =
- WebFrameContentDumper::DumpWebViewAsText(web_view, 21).Utf8();
+ String content = WebFrameContentDumper::DumpWebViewAsText(web_view, 21);
EXPECT_EQ("regular-ui", content);
- web_view->SetDisplayMode(blink::mojom::DisplayMode::kMinimalUi);
- content = WebFrameContentDumper::DumpWebViewAsText(web_view, 21).Utf8();
+ web_view->MainFrameImpl()->LocalRootFrameWidget()->SetDisplayMode(
+ mojom::blink::DisplayMode::kMinimalUi);
+ content = WebFrameContentDumper::DumpWebViewAsText(web_view, 21);
EXPECT_EQ("minimal-ui", content);
web_view_helper_.Reset();
}
+TEST_F(WebViewTest, ChangeDisplayModeChildFrame) {
+ RegisterMockedHttpURLLoad("iframe-display_mode.html");
+ RegisterMockedHttpURLLoad("display_mode.html");
+ WebViewImpl* web_view = web_view_helper_.InitializeAndLoad(
+ base_url_ + "iframe-display_mode.html");
+
+ String content = WebFrameContentDumper::DumpWebViewAsText(web_view, 21);
+ // An iframe inserts whitespace into the content.
+ EXPECT_EQ("regular-ui", content.StripWhiteSpace());
+
+ web_view->MainFrameImpl()->LocalRootFrameWidget()->SetDisplayMode(
+ mojom::blink::DisplayMode::kMinimalUi);
+ content = WebFrameContentDumper::DumpWebViewAsText(web_view, 21);
+ // An iframe inserts whitespace into the content.
+ EXPECT_EQ("minimal-ui", content.StripWhiteSpace());
+ web_view_helper_.Reset();
+}
+
+TEST_F(WebViewTest, ChangeDisplayModeAlertsListener) {
+ RegisterMockedHttpURLLoad("display_mode_listener.html");
+ WebViewImpl* web_view = web_view_helper_.InitializeAndLoad(
+ base_url_ + "display_mode_listener.html");
+
+ String content = WebFrameContentDumper::DumpWebViewAsText(web_view, 21);
+ EXPECT_EQ("regular-ui", content);
+
+ web_view->MainFrameImpl()->LocalRootFrameWidget()->SetDisplayMode(
+ mojom::blink::DisplayMode::kMinimalUi);
+ content = WebFrameContentDumper::DumpWebViewAsText(web_view, 21);
+ EXPECT_EQ("minimal-ui", content);
+ web_view_helper_.Reset();
+}
+
+TEST_F(WebViewTest, ChangeDisplayModeChildFrameAlertsListener) {
+ RegisterMockedHttpURLLoad("iframe-display_mode_listener.html");
+ RegisterMockedHttpURLLoad("display_mode_listener.html");
+ WebViewImpl* web_view = web_view_helper_.InitializeAndLoad(
+ base_url_ + "iframe-display_mode_listener.html");
+
+ String content = WebFrameContentDumper::DumpWebViewAsText(web_view, 21);
+ // An iframe inserts whitespace into the content.
+ EXPECT_EQ("regular-ui", content.StripWhiteSpace());
+
+ web_view->MainFrameImpl()->LocalRootFrameWidget()->SetDisplayMode(
+ mojom::blink::DisplayMode::kMinimalUi);
+ content = WebFrameContentDumper::DumpWebViewAsText(web_view, 21);
+ // An iframe inserts whitespace into the content.
+ EXPECT_EQ("minimal-ui", content.StripWhiteSpace());
+ web_view_helper_.Reset();
+}
+
TEST_F(WebViewTest, AddFrameInCloseUnload) {
CreateChildCounterFrameClient frame_client;
RegisterMockedHttpURLLoad("add_frame_in_unload.html");
@@ -4004,20 +4072,18 @@ TEST_F(WebViewTest, AddFrameInChildInNavigateUnload) {
web_view_helper_.Reset();
}
-class TouchEventHandlerWebWidgetClient
- : public frame_test_helpers::TestWebWidgetClient {
+class FakeFrameWidgetHost : public mojom::blink::FrameWidgetHost {
public:
- // WebWidgetClient methods
- void SetHasTouchEventHandlers(bool state) override {
- // Only count the times the state changes.
- if (state != has_touch_event_handler_)
- has_touch_event_handler_count_[state]++;
- has_touch_event_handler_ = state;
- }
-
- // Local methods
- TouchEventHandlerWebWidgetClient()
+ FakeFrameWidgetHost()
: has_touch_event_handler_count_(), has_touch_event_handler_(false) {}
+ ~FakeFrameWidgetHost() override = default;
+
+ mojo::PendingAssociatedRemote<mojom::blink::FrameWidgetHost>
+ BindNewFrameWidgetInterfaces() {
+ frame_widget_host_receiver_.reset();
+ return frame_widget_host_receiver_
+ .BindNewEndpointAndPassDedicatedRemoteForTesting();
+ }
int GetAndResetHasTouchEventHandlerCallCount(bool state) {
int value = has_touch_event_handler_count_[state];
@@ -4026,19 +4092,75 @@ class TouchEventHandlerWebWidgetClient
}
private:
+ // blink::mojom::FrameWidgetHost overrides.
+ void AnimateDoubleTapZoomInMainFrame(const gfx::Point& tap_point,
+ const gfx::Rect& rect_to_zoom) override {
+ }
+ void ZoomToFindInPageRectInMainFrame(const gfx::Rect& rect_to_zoom) override {
+ }
+ void SetHasTouchEventHandlers(bool state) override {
+ // Only count the times the state changes.
+ if (state != has_touch_event_handler_)
+ has_touch_event_handler_count_[state]++;
+ has_touch_event_handler_ = state;
+ }
+ void IntrinsicSizingInfoChanged(
+ mojom::blink::IntrinsicSizingInfoPtr sizing_info) override {}
+ void AutoscrollStart(const gfx::PointF& position) override {}
+ void AutoscrollFling(const gfx::Vector2dF& position) override {}
+ void AutoscrollEnd() override {}
+
+ private:
+ mojo::AssociatedReceiver<mojom::blink::FrameWidgetHost>
+ frame_widget_host_receiver_{this};
int has_touch_event_handler_count_[2];
bool has_touch_event_handler_;
+
+ DISALLOW_COPY_AND_ASSIGN(FakeFrameWidgetHost);
};
-// This test verifies that WebWidgetClient::SetHasTouchEventHandlers is called
+// This test verifies that FrameWidgetHost::SetHasTouchEventHandlers is called
// accordingly for various calls to EventHandlerRegistry::did{Add|Remove|
// RemoveAll}EventHandler(..., TouchEvent). Verifying that those calls are made
// correctly is the job of web_tests/fast/events/event-handler-count.html.
TEST_F(WebViewTest, SetHasTouchEventHandlers) {
- TouchEventHandlerWebWidgetClient client;
+ // Note: this test doesn't use WebViewHelper since it intentionally runs
+ // initialization code between WebView and WebLocalFrame creation.
+ frame_test_helpers::TestWebViewClient web_view_client;
+ frame_test_helpers::TestWebWidgetClient web_widget_client;
+ WebViewImpl* web_view_impl = static_cast<WebViewImpl*>(WebView::Create(
+ &web_view_client, false,
+ /*compositing_enabled=*/true, nullptr, mojo::NullAssociatedReceiver()));
+
+ frame_test_helpers::TestWebFrameClient web_frame_client;
+ WebLocalFrame* frame =
+ WebLocalFrame::CreateMainFrame(web_view_impl, &web_frame_client, nullptr,
+ base::UnguessableToken::Create(), nullptr);
+ web_frame_client.Bind(frame);
+
+ FakeFrameWidgetHost frame_widget_host;
+ auto blink_frame_widget_host =
+ frame_widget_host.BindNewFrameWidgetInterfaces();
+
+ {
+ // Copy the steps done from WebViewHelper::InitializeWithOpener() to set up
+ // the appropriate pointers!
+ WebFrameWidget* widget = blink::WebFrameWidget::CreateForMainFrame(
+ &web_widget_client, frame, std::move(blink_frame_widget_host),
+ CrossVariantMojoAssociatedReceiver<mojom::FrameWidgetInterfaceBase>(),
+ CrossVariantMojoAssociatedRemote<mojom::WidgetHostInterfaceBase>(),
+ CrossVariantMojoAssociatedReceiver<mojom::WidgetInterfaceBase>());
+ web_widget_client.set_layer_tree_host(widget->InitializeCompositing(
+ web_widget_client.task_graph_runner(),
+ frame_test_helpers::GetSynchronousSingleThreadLayerTreeSettings(),
+ std::make_unique<cc::TestUkmRecorderFactory>()));
+ widget->SetCompositorVisible(true);
+ web_view_impl->DidAttachLocalMainFrame();
+ }
+
std::string url = RegisterMockedHttpURLLoad("has_touch_event_handlers.html");
- WebViewImpl* web_view_impl =
- web_view_helper_.InitializeAndLoad(url, nullptr, nullptr, &client);
+ LoadFrame(web_view_impl->MainFrameImpl(), url);
+
const EventHandlerRegistry::EventHandlerClass kTouchEvent =
EventHandlerRegistry::kTouchStartOrMoveEventBlocking;
@@ -4046,8 +4168,10 @@ TEST_F(WebViewTest, SetHasTouchEventHandlers) {
// In practice we get two such calls because WebViewHelper::initializeAndLoad
// first initializes an empty frame, and then loads a document into it, so
// there are two FrameLoader::commitProvisionalLoad calls.
- EXPECT_EQ(0, client.GetAndResetHasTouchEventHandlerCallCount(false));
- EXPECT_EQ(0, client.GetAndResetHasTouchEventHandlerCallCount(true));
+ EXPECT_EQ(0,
+ frame_widget_host.GetAndResetHasTouchEventHandlerCallCount(false));
+ EXPECT_EQ(0,
+ frame_widget_host.GetAndResetHasTouchEventHandlerCallCount(true));
// Adding the first document handler results in a has-handlers call.
Document* document =
@@ -4055,30 +4179,46 @@ TEST_F(WebViewTest, SetHasTouchEventHandlers) {
EventHandlerRegistry* registry =
&document->GetFrame()->GetEventHandlerRegistry();
registry->DidAddEventHandler(*document, kTouchEvent);
- EXPECT_EQ(0, client.GetAndResetHasTouchEventHandlerCallCount(false));
- EXPECT_EQ(1, client.GetAndResetHasTouchEventHandlerCallCount(true));
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_EQ(0,
+ frame_widget_host.GetAndResetHasTouchEventHandlerCallCount(false));
+ EXPECT_EQ(1,
+ frame_widget_host.GetAndResetHasTouchEventHandlerCallCount(true));
// Adding another handler has no effect.
registry->DidAddEventHandler(*document, kTouchEvent);
- EXPECT_EQ(0, client.GetAndResetHasTouchEventHandlerCallCount(false));
- EXPECT_EQ(0, client.GetAndResetHasTouchEventHandlerCallCount(true));
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(0,
+ frame_widget_host.GetAndResetHasTouchEventHandlerCallCount(false));
+ EXPECT_EQ(0,
+ frame_widget_host.GetAndResetHasTouchEventHandlerCallCount(true));
// Removing the duplicate handler has no effect.
registry->DidRemoveEventHandler(*document, kTouchEvent);
- EXPECT_EQ(0, client.GetAndResetHasTouchEventHandlerCallCount(false));
- EXPECT_EQ(0, client.GetAndResetHasTouchEventHandlerCallCount(true));
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(0,
+ frame_widget_host.GetAndResetHasTouchEventHandlerCallCount(false));
+ EXPECT_EQ(0,
+ frame_widget_host.GetAndResetHasTouchEventHandlerCallCount(true));
// Removing the final handler results in a no-handlers call.
registry->DidRemoveEventHandler(*document, kTouchEvent);
- EXPECT_EQ(1, client.GetAndResetHasTouchEventHandlerCallCount(false));
- EXPECT_EQ(0, client.GetAndResetHasTouchEventHandlerCallCount(true));
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(1,
+ frame_widget_host.GetAndResetHasTouchEventHandlerCallCount(false));
+ EXPECT_EQ(0,
+ frame_widget_host.GetAndResetHasTouchEventHandlerCallCount(true));
// Adding a handler on a div results in a has-handlers call.
Element* parent_div = document->getElementById("parentdiv");
DCHECK(parent_div);
registry->DidAddEventHandler(*parent_div, kTouchEvent);
- EXPECT_EQ(0, client.GetAndResetHasTouchEventHandlerCallCount(false));
- EXPECT_EQ(1, client.GetAndResetHasTouchEventHandlerCallCount(true));
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(0,
+ frame_widget_host.GetAndResetHasTouchEventHandlerCallCount(false));
+ EXPECT_EQ(1,
+ frame_widget_host.GetAndResetHasTouchEventHandlerCallCount(true));
// Adding a duplicate handler on the div, clearing all document handlers
// (of which there are none) and removing the extra handler on the div
@@ -4086,25 +4226,40 @@ TEST_F(WebViewTest, SetHasTouchEventHandlers) {
registry->DidAddEventHandler(*parent_div, kTouchEvent);
registry->DidRemoveAllEventHandlers(*document);
registry->DidRemoveEventHandler(*parent_div, kTouchEvent);
- EXPECT_EQ(0, client.GetAndResetHasTouchEventHandlerCallCount(false));
- EXPECT_EQ(0, client.GetAndResetHasTouchEventHandlerCallCount(true));
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(0,
+ frame_widget_host.GetAndResetHasTouchEventHandlerCallCount(false));
+ EXPECT_EQ(0,
+ frame_widget_host.GetAndResetHasTouchEventHandlerCallCount(true));
// Removing the final handler on the div results in a no-handlers call.
registry->DidRemoveEventHandler(*parent_div, kTouchEvent);
- EXPECT_EQ(1, client.GetAndResetHasTouchEventHandlerCallCount(false));
- EXPECT_EQ(0, client.GetAndResetHasTouchEventHandlerCallCount(true));
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(1,
+ frame_widget_host.GetAndResetHasTouchEventHandlerCallCount(false));
+ EXPECT_EQ(0,
+ frame_widget_host.GetAndResetHasTouchEventHandlerCallCount(true));
// Adding two handlers then clearing them in a single call results in a
// has-handlers then no-handlers call.
registry->DidAddEventHandler(*parent_div, kTouchEvent);
- EXPECT_EQ(0, client.GetAndResetHasTouchEventHandlerCallCount(false));
- EXPECT_EQ(1, client.GetAndResetHasTouchEventHandlerCallCount(true));
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(0,
+ frame_widget_host.GetAndResetHasTouchEventHandlerCallCount(false));
+ EXPECT_EQ(1,
+ frame_widget_host.GetAndResetHasTouchEventHandlerCallCount(true));
registry->DidAddEventHandler(*parent_div, kTouchEvent);
- EXPECT_EQ(0, client.GetAndResetHasTouchEventHandlerCallCount(false));
- EXPECT_EQ(0, client.GetAndResetHasTouchEventHandlerCallCount(true));
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(0,
+ frame_widget_host.GetAndResetHasTouchEventHandlerCallCount(false));
+ EXPECT_EQ(0,
+ frame_widget_host.GetAndResetHasTouchEventHandlerCallCount(true));
registry->DidRemoveAllEventHandlers(*parent_div);
- EXPECT_EQ(1, client.GetAndResetHasTouchEventHandlerCallCount(false));
- EXPECT_EQ(0, client.GetAndResetHasTouchEventHandlerCallCount(true));
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(1,
+ frame_widget_host.GetAndResetHasTouchEventHandlerCallCount(false));
+ EXPECT_EQ(0,
+ frame_widget_host.GetAndResetHasTouchEventHandlerCallCount(true));
// Adding a handler inside of a child iframe results in a has-handlers call.
Element* child_frame = document->getElementById("childframe");
@@ -4114,8 +4269,11 @@ TEST_F(WebViewTest, SetHasTouchEventHandlers) {
Element* child_div = child_document->getElementById("childdiv");
DCHECK(child_div);
registry->DidAddEventHandler(*child_div, kTouchEvent);
- EXPECT_EQ(0, client.GetAndResetHasTouchEventHandlerCallCount(false));
- EXPECT_EQ(1, client.GetAndResetHasTouchEventHandlerCallCount(true));
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(0,
+ frame_widget_host.GetAndResetHasTouchEventHandlerCallCount(false));
+ EXPECT_EQ(1,
+ frame_widget_host.GetAndResetHasTouchEventHandlerCallCount(true));
// Adding and clearing handlers in the parent doc or elsewhere in the child
// doc has no impact.
@@ -4125,19 +4283,28 @@ TEST_F(WebViewTest, SetHasTouchEventHandlers) {
registry->DidRemoveAllEventHandlers(*document);
registry->DidRemoveAllEventHandlers(*child_frame);
registry->DidRemoveAllEventHandlers(*child_document);
- EXPECT_EQ(0, client.GetAndResetHasTouchEventHandlerCallCount(false));
- EXPECT_EQ(0, client.GetAndResetHasTouchEventHandlerCallCount(true));
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(0,
+ frame_widget_host.GetAndResetHasTouchEventHandlerCallCount(false));
+ EXPECT_EQ(0,
+ frame_widget_host.GetAndResetHasTouchEventHandlerCallCount(true));
// Removing the final handler inside the child frame results in a no-handlers
// call.
registry->DidRemoveAllEventHandlers(*child_div);
- EXPECT_EQ(1, client.GetAndResetHasTouchEventHandlerCallCount(false));
- EXPECT_EQ(0, client.GetAndResetHasTouchEventHandlerCallCount(true));
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(1,
+ frame_widget_host.GetAndResetHasTouchEventHandlerCallCount(false));
+ EXPECT_EQ(0,
+ frame_widget_host.GetAndResetHasTouchEventHandlerCallCount(true));
// Adding a handler inside the child frame results in a has-handlers call.
registry->DidAddEventHandler(*child_document, kTouchEvent);
- EXPECT_EQ(0, client.GetAndResetHasTouchEventHandlerCallCount(false));
- EXPECT_EQ(1, client.GetAndResetHasTouchEventHandlerCallCount(true));
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(0,
+ frame_widget_host.GetAndResetHasTouchEventHandlerCallCount(false));
+ EXPECT_EQ(1,
+ frame_widget_host.GetAndResetHasTouchEventHandlerCallCount(true));
// Adding a handler in the parent document and removing the one in the frame
// has no effect.
@@ -4145,14 +4312,20 @@ TEST_F(WebViewTest, SetHasTouchEventHandlers) {
registry->DidRemoveEventHandler(*child_document, kTouchEvent);
registry->DidRemoveAllEventHandlers(*child_document);
registry->DidRemoveAllEventHandlers(*document);
- EXPECT_EQ(0, client.GetAndResetHasTouchEventHandlerCallCount(false));
- EXPECT_EQ(0, client.GetAndResetHasTouchEventHandlerCallCount(true));
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(0,
+ frame_widget_host.GetAndResetHasTouchEventHandlerCallCount(false));
+ EXPECT_EQ(0,
+ frame_widget_host.GetAndResetHasTouchEventHandlerCallCount(true));
// Now removing the handler in the parent document results in a no-handlers
// call.
registry->DidRemoveEventHandler(*child_frame, kTouchEvent);
- EXPECT_EQ(1, client.GetAndResetHasTouchEventHandlerCallCount(false));
- EXPECT_EQ(0, client.GetAndResetHasTouchEventHandlerCallCount(true));
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(1,
+ frame_widget_host.GetAndResetHasTouchEventHandlerCallCount(false));
+ EXPECT_EQ(0,
+ frame_widget_host.GetAndResetHasTouchEventHandlerCallCount(true));
// Free the webView before the TouchEventHandlerWebViewClient gets freed.
web_view_helper_.Reset();
@@ -4191,7 +4364,7 @@ TEST_F(WebViewTest, DeleteElementWithRegisteredHandler) {
TEST_F(WebViewTest, TextInputFlags) {
std::string url = RegisterMockedHttpURLLoad("text_input_flags.html");
WebViewImpl* web_view_impl = web_view_helper_.InitializeAndLoad(url);
- web_view_impl->SetInitialFocus(false);
+ web_view_impl->MainFrameImpl()->GetFrame()->SetInitialFocus(false);
WebLocalFrameImpl* frame = web_view_impl->MainFrameImpl();
WebInputMethodController* active_input_method_controller =
@@ -4253,20 +4426,20 @@ TEST_F(WebViewTest, FirstUserGestureObservedKeyEvent) {
web_view_helper_.InitializeAndLoad(base_url_ + "form.html");
WebLocalFrameImpl* frame = web_view->MainFrameImpl();
frame->SetAutofillClient(&client);
- web_view->SetInitialFocus(false);
+ web_view->MainFrameImpl()->GetFrame()->SetInitialFocus(false);
EXPECT_EQ(0, client.GetUserGestureNotificationsCount());
- WebKeyboardEvent key_event(WebInputEvent::kRawKeyDown,
+ WebKeyboardEvent key_event(WebInputEvent::Type::kRawKeyDown,
WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests());
key_event.dom_key = ui::DomKey::FromCharacter(' ');
key_event.windows_key_code = VKEY_SPACE;
web_view->MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(key_event));
- key_event.SetType(WebInputEvent::kKeyUp);
+ WebCoalescedInputEvent(key_event, ui::LatencyInfo()));
+ key_event.SetType(WebInputEvent::Type::kKeyUp);
web_view->MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(key_event));
+ WebCoalescedInputEvent(key_event, ui::LatencyInfo()));
EXPECT_EQ(1, client.GetUserGestureNotificationsCount());
frame->SetAutofillClient(nullptr);
@@ -4279,21 +4452,21 @@ TEST_F(WebViewTest, FirstUserGestureObservedMouseEvent) {
web_view_helper_.InitializeAndLoad(base_url_ + "form.html");
WebLocalFrameImpl* frame = web_view->MainFrameImpl();
frame->SetAutofillClient(&client);
- web_view->SetInitialFocus(false);
+ web_view->MainFrameImpl()->GetFrame()->SetInitialFocus(false);
EXPECT_EQ(0, client.GetUserGestureNotificationsCount());
- WebMouseEvent mouse_event(WebInputEvent::kMouseDown,
+ WebMouseEvent mouse_event(WebInputEvent::Type::kMouseDown,
WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests());
mouse_event.button = WebMouseEvent::Button::kLeft;
mouse_event.SetPositionInWidget(1, 1);
mouse_event.click_count = 1;
web_view->MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(mouse_event));
- mouse_event.SetType(WebInputEvent::kMouseUp);
+ WebCoalescedInputEvent(mouse_event, ui::LatencyInfo()));
+ mouse_event.SetType(WebInputEvent::Type::kMouseUp);
web_view->MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(mouse_event));
+ WebCoalescedInputEvent(mouse_event, ui::LatencyInfo()));
EXPECT_EQ(1, client.GetUserGestureNotificationsCount());
frame->SetAutofillClient(nullptr);
@@ -4306,7 +4479,7 @@ TEST_F(WebViewTest, CompositionIsUserGesture) {
WebLocalFrameImpl* frame = web_view->MainFrameImpl();
MockAutofillClient client;
frame->SetAutofillClient(&client);
- web_view->SetInitialFocus(false);
+ web_view->MainFrameImpl()->GetFrame()->SetInitialFocus(false);
EXPECT_EQ(0, client.TextChanges());
EXPECT_TRUE(
@@ -4574,7 +4747,7 @@ class ShowUnhandledTapTest : public WebViewTest {
// Tap on the given element by ID.
void Tap(const String& element_id) {
mock_notifier_.Reset();
- EXPECT_TRUE(TapElementById(WebInputEvent::kGestureTap, element_id));
+ EXPECT_TRUE(TapElementById(WebInputEvent::Type::kGestureTap, element_id));
}
// Set up a test script for the given |operation| with the given |handler|.
@@ -4825,7 +4998,7 @@ TEST_F(WebViewTest, ShouldSuppressKeyboardForPasswordField) {
EXPECT_FALSE(frame->ShouldSuppressKeyboardForFocusedElement());
// Focusing a field should result in treating it autofillable.
- web_view->SetInitialFocus(false);
+ web_view->MainFrameImpl()->GetFrame()->SetInitialFocus(false);
EXPECT_TRUE(frame->ShouldSuppressKeyboardForFocusedElement());
// Pretend that |client| no longer has autofill data available.
@@ -4841,7 +5014,7 @@ TEST_F(WebViewTest, PasswordFieldEditingIsUserGesture) {
base_url_ + "input_field_password.html");
WebLocalFrameImpl* frame = web_view->MainFrameImpl();
frame->SetAutofillClient(&client);
- web_view->SetInitialFocus(false);
+ web_view->MainFrameImpl()->GetFrame()->SetInitialFocus(false);
WebVector<WebImeTextSpan> empty_ime_text_spans;
@@ -5356,9 +5529,8 @@ TEST_F(WebViewTest, DetachPluginInLayout) {
To<HTMLObjectElement>(main_frame->GetDocument()->body()->firstChild());
EXPECT_TRUE(plugin_element->OwnedPlugin());
- plugin_element->style()->setCSSText(
- main_frame->GetDocument()->ToExecutionContext(), "display: none",
- ASSERT_NO_EXCEPTION);
+ plugin_element->style()->setCSSText(main_frame->DomWindow(), "display: none",
+ ASSERT_NO_EXCEPTION);
EXPECT_TRUE(plugin_element->OwnedPlugin());
UpdateAllLifecyclePhases();
EXPECT_FALSE(plugin_element->OwnedPlugin());
@@ -5387,7 +5559,7 @@ TEST_F(WebViewTest, FirstInputDelayReported) {
EXPECT_FALSE(interactive_detector->GetFirstInputDelay().has_value());
- WebKeyboardEvent key_event1(WebInputEvent::kRawKeyDown,
+ WebKeyboardEvent key_event1(WebInputEvent::Type::kRawKeyDown,
WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests());
key_event1.dom_key = ui::DomKey::FromCharacter(' ');
@@ -5395,7 +5567,7 @@ TEST_F(WebViewTest, FirstInputDelayReported) {
key_event1.SetTimeStamp(test_task_runner_->NowTicks());
test_task_runner_->FastForwardBy(base::TimeDelta::FromMilliseconds(50));
web_view->MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(key_event1));
+ WebCoalescedInputEvent(key_event1, ui::LatencyInfo()));
EXPECT_TRUE(interactive_detector->GetFirstInputDelay().has_value());
EXPECT_NEAR(50,
@@ -5405,7 +5577,7 @@ TEST_F(WebViewTest, FirstInputDelayReported) {
.InMillisecondsF());
// Sending a second event won't change the FirstInputDelay.
- WebKeyboardEvent key_event2(WebInputEvent::kRawKeyDown,
+ WebKeyboardEvent key_event2(WebInputEvent::Type::kRawKeyDown,
WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests());
key_event2.dom_key = ui::DomKey::FromCharacter(' ');
@@ -5413,7 +5585,7 @@ TEST_F(WebViewTest, FirstInputDelayReported) {
test_task_runner_->FastForwardBy(base::TimeDelta::FromMilliseconds(60));
key_event2.SetTimeStamp(test_task_runner_->NowTicks());
web_view->MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(key_event2));
+ WebCoalescedInputEvent(key_event2, ui::LatencyInfo()));
EXPECT_NEAR(50,
(*interactive_detector->GetFirstInputDelay()).InMillisecondsF(),
@@ -5442,7 +5614,7 @@ TEST_F(WebViewTest, LongestInputDelayReported) {
EXPECT_FALSE(interactive_detector->GetLongestInputDelay().has_value());
- WebKeyboardEvent key_event1(WebInputEvent::kRawKeyDown,
+ WebKeyboardEvent key_event1(WebInputEvent::Type::kRawKeyDown,
WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests());
key_event1.dom_key = ui::DomKey::FromCharacter(' ');
@@ -5450,11 +5622,11 @@ TEST_F(WebViewTest, LongestInputDelayReported) {
key_event1.SetTimeStamp(test_task_runner_->NowTicks());
test_task_runner_->FastForwardBy(base::TimeDelta::FromMilliseconds(50));
web_view->MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(key_event1));
+ WebCoalescedInputEvent(key_event1, ui::LatencyInfo()));
base::TimeTicks longest_input_timestamp = test_task_runner_->NowTicks();
- WebKeyboardEvent key_event2(WebInputEvent::kRawKeyDown,
+ WebKeyboardEvent key_event2(WebInputEvent::Type::kRawKeyDown,
WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests());
key_event2.dom_key = ui::DomKey::FromCharacter(' ');
@@ -5462,9 +5634,9 @@ TEST_F(WebViewTest, LongestInputDelayReported) {
key_event2.SetTimeStamp(longest_input_timestamp);
test_task_runner_->FastForwardBy(base::TimeDelta::FromMilliseconds(100));
web_view->MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(key_event2));
+ WebCoalescedInputEvent(key_event2, ui::LatencyInfo()));
- WebKeyboardEvent key_event3(WebInputEvent::kRawKeyDown,
+ WebKeyboardEvent key_event3(WebInputEvent::Type::kRawKeyDown,
WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests());
key_event3.dom_key = ui::DomKey::FromCharacter(' ');
@@ -5472,7 +5644,7 @@ TEST_F(WebViewTest, LongestInputDelayReported) {
key_event3.SetTimeStamp(test_task_runner_->NowTicks());
test_task_runner_->FastForwardBy(base::TimeDelta::FromMilliseconds(70));
web_view->MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(key_event3));
+ WebCoalescedInputEvent(key_event3, ui::LatencyInfo()));
EXPECT_NEAR(100,
(*interactive_detector->GetLongestInputDelay()).InMillisecondsF(),
@@ -5500,7 +5672,7 @@ TEST_F(WebViewTest, InputDelayReported) {
test_task_runner_->FastForwardBy(base::TimeDelta::FromMilliseconds(70));
HistogramTester histogram_tester;
- WebKeyboardEvent key_event1(WebInputEvent::kRawKeyDown,
+ WebKeyboardEvent key_event1(WebInputEvent::Type::kRawKeyDown,
WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests());
key_event1.dom_key = ui::DomKey::FromCharacter(' ');
@@ -5508,9 +5680,9 @@ TEST_F(WebViewTest, InputDelayReported) {
key_event1.SetTimeStamp(test_task_runner_->NowTicks());
test_task_runner_->FastForwardBy(base::TimeDelta::FromMilliseconds(50));
web_view->MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(key_event1));
+ WebCoalescedInputEvent(key_event1, ui::LatencyInfo()));
- WebKeyboardEvent key_event2(WebInputEvent::kRawKeyDown,
+ WebKeyboardEvent key_event2(WebInputEvent::Type::kRawKeyDown,
WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests());
key_event2.dom_key = ui::DomKey::FromCharacter(' ');
@@ -5518,9 +5690,9 @@ TEST_F(WebViewTest, InputDelayReported) {
key_event2.SetTimeStamp(test_task_runner_->NowTicks());
test_task_runner_->FastForwardBy(base::TimeDelta::FromMilliseconds(50));
web_view->MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(key_event2));
+ WebCoalescedInputEvent(key_event2, ui::LatencyInfo()));
- WebKeyboardEvent key_event3(WebInputEvent::kRawKeyDown,
+ WebKeyboardEvent key_event3(WebInputEvent::Type::kRawKeyDown,
WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests());
key_event3.dom_key = ui::DomKey::FromCharacter(' ');
@@ -5528,7 +5700,7 @@ TEST_F(WebViewTest, InputDelayReported) {
key_event3.SetTimeStamp(test_task_runner_->NowTicks());
test_task_runner_->FastForwardBy(base::TimeDelta::FromMilliseconds(70));
web_view->MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(key_event3));
+ WebCoalescedInputEvent(key_event3, ui::LatencyInfo()));
histogram_tester.ExpectTotalCount("PageLoad.InteractiveTiming.InputDelay3",
3);
@@ -5568,7 +5740,7 @@ TEST_F(WebViewTest, LongestInputDelayPageBackgroundedDuringQueuing) {
EXPECT_FALSE(interactive_detector->GetLongestInputDelay().has_value());
- WebKeyboardEvent key_event1(WebInputEvent::kRawKeyDown,
+ WebKeyboardEvent key_event1(WebInputEvent::Type::kRawKeyDown,
WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests());
key_event1.dom_key = ui::DomKey::FromCharacter(' ');
@@ -5577,24 +5749,24 @@ TEST_F(WebViewTest, LongestInputDelayPageBackgroundedDuringQueuing) {
key_event1.SetTimeStamp(key_event1_time);
test_task_runner_->FastForwardBy(base::TimeDelta::FromMilliseconds(50));
web_view->MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(key_event1));
+ WebCoalescedInputEvent(key_event1, ui::LatencyInfo()));
- WebKeyboardEvent key_event2(WebInputEvent::kRawKeyDown,
+ WebKeyboardEvent key_event2(WebInputEvent::Type::kRawKeyDown,
WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests());
key_event2.dom_key = ui::DomKey::FromCharacter(' ');
key_event2.windows_key_code = VKEY_SPACE;
key_event2.SetTimeStamp(test_task_runner_->NowTicks());
test_task_runner_->FastForwardBy(base::TimeDelta::FromMilliseconds(100));
- web_view->SetVisibilityState(PageVisibilityState::kHidden,
+ web_view->SetVisibilityState(mojom::blink::PageVisibilityState::kHidden,
/*initial_state=*/false);
test_task_runner_->FastForwardBy(base::TimeDelta::FromMilliseconds(100));
- web_view->SetVisibilityState(PageVisibilityState::kVisible,
+ web_view->SetVisibilityState(mojom::blink::PageVisibilityState::kVisible,
/*initial_state=*/false);
test_task_runner_->FastForwardBy(base::TimeDelta::FromMilliseconds(100));
// Total input delay is >300ms.
web_view->MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(key_event2));
+ WebCoalescedInputEvent(key_event2, ui::LatencyInfo()));
EXPECT_NEAR(50,
(*interactive_detector->GetLongestInputDelay()).InMillisecondsF(),
@@ -5607,7 +5779,7 @@ TEST_F(WebViewTest, LongestInputDelayPageBackgroundedDuringQueuing) {
// calculate longest input delay.
TEST_F(WebViewTest, LongestInputDelayPageBackgroundedAtNavStart) {
WebViewImpl* web_view = web_view_helper_.Initialize();
- web_view->SetVisibilityState(PageVisibilityState::kHidden,
+ web_view->SetVisibilityState(mojom::blink::PageVisibilityState::kHidden,
/*initial_state=*/false);
WebURL base_url = url_test_helpers::ToKURL("http://example.com/");
frame_test_helpers::LoadHTMLString(web_view->MainFrameImpl(),
@@ -5624,17 +5796,17 @@ TEST_F(WebViewTest, LongestInputDelayPageBackgroundedAtNavStart) {
InteractiveDetector* interactive_detector =
GetTestInteractiveDetector(*document);
- WebKeyboardEvent key_event(WebInputEvent::kRawKeyDown,
+ WebKeyboardEvent key_event(WebInputEvent::Type::kRawKeyDown,
WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests());
key_event.dom_key = ui::DomKey::FromCharacter(' ');
key_event.windows_key_code = VKEY_SPACE;
key_event.SetTimeStamp(test_task_runner_->NowTicks());
test_task_runner_->FastForwardBy(base::TimeDelta::FromMilliseconds(100));
- web_view->SetVisibilityState(PageVisibilityState::kVisible,
+ web_view->SetVisibilityState(mojom::blink::PageVisibilityState::kVisible,
/*initial_state=*/false);
web_view->MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(key_event));
+ WebCoalescedInputEvent(key_event, ui::LatencyInfo()));
EXPECT_FALSE(interactive_detector->GetLongestInputDelay().has_value());
}
@@ -5660,14 +5832,14 @@ TEST_F(WebViewTest, LongestInputDelayPageBackgroundedNotDuringQueuing) {
EXPECT_FALSE(interactive_detector->GetLongestInputDelay().has_value());
- web_view->SetVisibilityState(PageVisibilityState::kHidden,
+ web_view->SetVisibilityState(mojom::blink::PageVisibilityState::kHidden,
/*initial_state=*/false);
test_task_runner_->FastForwardBy(base::TimeDelta::FromMilliseconds(100));
- web_view->SetVisibilityState(PageVisibilityState::kVisible,
+ web_view->SetVisibilityState(mojom::blink::PageVisibilityState::kVisible,
/*initial_state=*/false);
test_task_runner_->FastForwardBy(base::TimeDelta::FromMilliseconds(1));
- WebKeyboardEvent key_event(WebInputEvent::kRawKeyDown,
+ WebKeyboardEvent key_event(WebInputEvent::Type::kRawKeyDown,
WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests());
key_event.dom_key = ui::DomKey::FromCharacter(' ');
@@ -5676,7 +5848,7 @@ TEST_F(WebViewTest, LongestInputDelayPageBackgroundedNotDuringQueuing) {
key_event.SetTimeStamp(key_event_time);
test_task_runner_->FastForwardBy(base::TimeDelta::FromMilliseconds(50));
web_view->MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(key_event));
+ WebCoalescedInputEvent(key_event, ui::LatencyInfo()));
EXPECT_NEAR(50,
(*interactive_detector->GetLongestInputDelay()).InMillisecondsF(),
@@ -5711,7 +5883,7 @@ TEST_F(WebViewTest, PointerDownUpFirstInputDelay) {
GetTestInteractiveDetector(*document);
WebPointerEvent pointer_down(
- WebInputEvent::kPointerDown,
+ WebInputEvent::Type::kPointerDown,
WebPointerProperties(1, WebPointerProperties::PointerType::kTouch), 5, 5);
pointer_down.SetTimeStamp(test_task_runner_->NowTicks());
// Set this to the left button, needed for testing to behave properly.
@@ -5719,7 +5891,7 @@ TEST_F(WebViewTest, PointerDownUpFirstInputDelay) {
pointer_down.button = WebPointerProperties::Button::kLeft;
test_task_runner_->FastForwardBy(base::TimeDelta::FromMilliseconds(50));
web_view->MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(pointer_down));
+ WebCoalescedInputEvent(pointer_down, ui::LatencyInfo()));
// We don't know if this pointer event will result in a scroll or not, so we
// can't report its delay. We don't consider a scroll to be meaningful input.
@@ -5727,12 +5899,12 @@ TEST_F(WebViewTest, PointerDownUpFirstInputDelay) {
// When we receive a pointer up, we report the delay of the pointer down.
WebPointerEvent pointer_up(
- WebInputEvent::kPointerUp,
+ WebInputEvent::Type::kPointerUp,
WebPointerProperties(1, WebPointerProperties::PointerType::kTouch), 5, 5);
test_task_runner_->FastForwardBy(base::TimeDelta::FromMilliseconds(60));
pointer_up.SetTimeStamp(test_task_runner_->NowTicks());
web_view->MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(pointer_up));
+ WebCoalescedInputEvent(pointer_up, ui::LatencyInfo()));
EXPECT_NEAR(50,
(*interactive_detector->GetFirstInputDelay()).InMillisecondsF(),
@@ -5791,7 +5963,7 @@ TEST_F(WebViewTest, FirstInputDelayExcludesProcessingTime) {
InteractiveDetector* interactive_detector =
GetTestInteractiveDetector(*document);
- WebKeyboardEvent key_event(WebInputEvent::kRawKeyDown,
+ WebKeyboardEvent key_event(WebInputEvent::Type::kRawKeyDown,
WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests());
key_event.dom_key = ui::DomKey::FromCharacter(' ');
@@ -5801,7 +5973,7 @@ TEST_F(WebViewTest, FirstInputDelayExcludesProcessingTime) {
test_task_runner_->FastForwardBy(base::TimeDelta::FromMilliseconds(5000));
web_view->MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(key_event));
+ WebCoalescedInputEvent(key_event, ui::LatencyInfo()));
EXPECT_TRUE(interactive_detector->GetFirstInputDelay().has_value());
base::TimeDelta first_input_delay =
@@ -5837,7 +6009,7 @@ TEST_F(WebViewTest, LongestInputDelayExcludesProcessingTime) {
InteractiveDetector* interactive_detector =
GetTestInteractiveDetector(*document);
- WebKeyboardEvent key_event(WebInputEvent::kRawKeyDown,
+ WebKeyboardEvent key_event(WebInputEvent::Type::kRawKeyDown,
WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests());
key_event.dom_key = ui::DomKey::FromCharacter(' ');
@@ -5847,7 +6019,7 @@ TEST_F(WebViewTest, LongestInputDelayExcludesProcessingTime) {
test_task_runner_->FastForwardBy(base::TimeDelta::FromMilliseconds(5000));
web_view->MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(key_event));
+ WebCoalescedInputEvent(key_event, ui::LatencyInfo()));
base::TimeDelta longest_input_delay =
*interactive_detector->GetLongestInputDelay();
@@ -5878,7 +6050,10 @@ TEST_F(WebViewTest, RootLayerAttachment) {
// Verifies that we emit Blink.UseCounter.FeaturePolicy.PotentialAnimation for
// CSS and JS animations in a document.
-TEST_F(WebViewTest, PotentialViolationReportsForLayoutAnimations) {
+// TODO(crbug.com/1066620): enable this test after metrics for document policy
+// are added. Needs to update histogram name to document policy equivalent
+// when re-enabled.
+TEST_F(WebViewTest, DISABLED_PotentialViolationReportsForLayoutAnimations) {
const char* kHistogramName =
"Blink.UseCounter.FeaturePolicy.PotentialViolation";
WebViewImpl* web_view = web_view_helper_.Initialize();
@@ -5936,7 +6111,7 @@ TEST_F(WebViewTest, LongPressImageAndThenLongTapImage) {
UpdateAllLifecyclePhases();
RunPendingTasks();
- WebGestureEvent event(WebInputEvent::kGestureLongPress,
+ WebGestureEvent event(WebInputEvent::Type::kGestureLongPress,
WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests(),
WebGestureDevice::kTouchscreen);
@@ -5944,13 +6119,13 @@ TEST_F(WebViewTest, LongPressImageAndThenLongTapImage) {
EXPECT_EQ(WebInputEventResult::kHandledSystem,
web_view->MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(event)));
+ WebCoalescedInputEvent(event, ui::LatencyInfo())));
EXPECT_TRUE(
web_view->AsView()
.page->GetContextMenuController()
.ContextMenuNodeForFrame(web_view->MainFrameImpl()->GetFrame()));
- WebGestureEvent tap_event(WebInputEvent::kGestureLongTap,
+ WebGestureEvent tap_event(WebInputEvent::Type::kGestureLongTap,
WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests(),
WebGestureDevice::kTouchscreen);
@@ -5958,7 +6133,7 @@ TEST_F(WebViewTest, LongPressImageAndThenLongTapImage) {
EXPECT_EQ(WebInputEventResult::kNotHandled,
web_view->MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(tap_event)));
+ WebCoalescedInputEvent(tap_event, ui::LatencyInfo())));
EXPECT_TRUE(
web_view->AsView()
.page->GetContextMenuController()
diff --git a/chromium/third_party/blink/renderer/core/feature_policy/BUILD.gn b/chromium/third_party/blink/renderer/core/feature_policy/BUILD.gn
index b5ad4779db6..28b6194dfd6 100644
--- a/chromium/third_party/blink/renderer/core/feature_policy/BUILD.gn
+++ b/chromium/third_party/blink/renderer/core/feature_policy/BUILD.gn
@@ -11,12 +11,12 @@ blink_core_sources("feature_policy") {
"dom_document_policy.h",
"dom_feature_policy.cc",
"dom_feature_policy.h",
- "feature_policy_helper.h",
"feature_policy_parser.cc",
"feature_policy_parser.h",
"feature_policy_parser_delegate.h",
"iframe_policy.h",
"layout_animations_policy.cc",
"layout_animations_policy.h",
+ "policy_helper.h",
]
}
diff --git a/chromium/third_party/blink/renderer/core/feature_policy/document_policy_features.json5 b/chromium/third_party/blink/renderer/core/feature_policy/document_policy_features.json5
index de197f9e3be..eef47dc127f 100644
--- a/chromium/third_party/blink/renderer/core/feature_policy/document_policy_features.json5
+++ b/chromium/third_party/blink/renderer/core/feature_policy/document_policy_features.json5
@@ -89,5 +89,12 @@
default_value: "true",
depends_on: ["UnsizedMediaPolicy"],
},
- ],
+ {
+ name: "LayoutAnimations",
+ document_policy_name: "layout-animations",
+ value_name: "",
+ value_type: "Bool",
+ default_value: "true",
+ depends_on: ["ExperimentalProductivityFeatures"],
+ },],
}
diff --git a/chromium/third_party/blink/renderer/core/feature_policy/document_policy_fuzzer.cc b/chromium/third_party/blink/renderer/core/feature_policy/document_policy_fuzzer.cc
index 1685869a15a..0f31f591cf3 100644
--- a/chromium/third_party/blink/renderer/core/feature_policy/document_policy_fuzzer.cc
+++ b/chromium/third_party/blink/renderer/core/feature_policy/document_policy_fuzzer.cc
@@ -13,6 +13,8 @@
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
static blink::BlinkFuzzerTestSupport test_support =
blink::BlinkFuzzerTestSupport();
- blink::DocumentPolicyParser::Parse(WTF::String(data, size));
+
+ blink::PolicyParserMessageBuffer logger;
+ blink::DocumentPolicyParser::Parse(WTF::String(data, size), logger);
return 0;
}
diff --git a/chromium/third_party/blink/renderer/core/feature_policy/document_policy_parser.cc b/chromium/third_party/blink/renderer/core/feature_policy/document_policy_parser.cc
index 41fa9ea07c1..0ea88d5c958 100644
--- a/chromium/third_party/blink/renderer/core/feature_policy/document_policy_parser.cc
+++ b/chromium/third_party/blink/renderer/core/feature_policy/document_policy_parser.cc
@@ -5,19 +5,58 @@
#include "third_party/blink/renderer/core/feature_policy/document_policy_parser.h"
#include "net/http/structured_headers.h"
-#include "third_party/blink/public/mojom/feature_policy/policy_value.mojom-blink-forward.h"
+#include "third_party/blink/public/mojom/feature_policy/policy_value.mojom-blink.h"
namespace blink {
-
namespace {
-base::Optional<PolicyValue> ItemToPolicyValue(
- const net::structured_headers::Item& item) {
- switch (item.Type()) {
+constexpr const char* kReportTo = "report-to";
+constexpr const char* kNone = "none";
+constexpr const char* kWildCard = "*";
+
+const char* ItemTypeToString(net::structured_headers::Item::ItemType type) {
+ switch (type) {
case net::structured_headers::Item::ItemType::kIntegerType:
- return PolicyValue(static_cast<double>(item.GetInteger()));
+ return "Integer";
case net::structured_headers::Item::ItemType::kDecimalType:
- return PolicyValue(item.GetDecimal());
+ return "Decimal";
+ case net::structured_headers::Item::ItemType::kBooleanType:
+ return "Boolean";
+ case net::structured_headers::Item::ItemType::kByteSequenceType:
+ return "ByteSequence";
+ case net::structured_headers::Item::ItemType::kNullType:
+ return "Null";
+ case net::structured_headers::Item::ItemType::kStringType:
+ return "String";
+ case net::structured_headers::Item::ItemType::kTokenType:
+ return "Token";
+ }
+}
+
+const char* PolicyValueTypeToString(mojom::blink::PolicyValueType type) {
+ switch (type) {
+ case mojom::blink::PolicyValueType::kNull:
+ return "Null";
+ case mojom::blink::PolicyValueType::kBool:
+ return "Boolean";
+ case mojom::blink::PolicyValueType::kDecDouble:
+ return "Double";
+ }
+}
+
+base::Optional<PolicyValue> ItemToPolicyValue(
+ const net::structured_headers::Item& item,
+ mojom::blink::PolicyValueType type) {
+ switch (type) {
+ case mojom::blink::PolicyValueType::kDecDouble:
+ switch (item.Type()) {
+ case net::structured_headers::Item::ItemType::kIntegerType:
+ return PolicyValue(static_cast<double>(item.GetInteger()));
+ case net::structured_headers::Item::ItemType::kDecimalType:
+ return PolicyValue(item.GetDecimal());
+ default:
+ return base::nullopt;
+ }
default:
return base::nullopt;
}
@@ -34,31 +73,59 @@ struct ParsedFeature {
mojom::blink::DocumentPolicyFeature feature;
PolicyValue policy_value;
base::Optional<std::string> endpoint_group;
+ // Wildcard feature('*') is used to specify default endpoint for features.
+ bool is_wildcard = false;
};
+base::Optional<ParsedFeature> ParseWildcardFeature(
+ const net::structured_headers::ParameterizedMember& directive,
+ PolicyParserMessageBuffer& logger) {
+ base::Optional<std::string> endpoint_group;
+
+ for (const auto& param : directive.params) {
+ if (param.first == kReportTo) {
+ endpoint_group = ItemToString(param.second);
+ if (!endpoint_group) {
+ logger.Warn("\"report-to\" parameter should be a token.");
+ return base::nullopt;
+ }
+ } else {
+ // Unrecognized param.
+ logger.Warn(String::Format("Unrecognized parameter name %s for %s.",
+ param.first.c_str(), kWildCard));
+ }
+ }
+
+ return base::make_optional<ParsedFeature>(
+ {mojom::blink::DocumentPolicyFeature::kDefault, PolicyValue(),
+ endpoint_group, true});
+}
+
base::Optional<ParsedFeature> ParseFeature(
const net::structured_headers::ParameterizedMember& directive,
const DocumentPolicyNameFeatureMap& name_feature_map,
- const DocumentPolicyFeatureInfoMap& feature_info_map) {
+ const DocumentPolicyFeatureInfoMap& feature_info_map,
+ PolicyParserMessageBuffer& logger) {
ParsedFeature parsed_feature;
- // Directives must not be inner lists.
- if (directive.member_is_inner_list)
+ if (directive.member_is_inner_list) {
+ logger.Warn("Directives must not be inner lists.");
return base::nullopt;
+ }
const net::structured_headers::Item& feature_token =
directive.member.front().item;
- // The item in directive should be token type.
- if (!feature_token.is_token())
+ if (!feature_token.is_token()) {
+ logger.Warn("The item in directive should be token type.");
return base::nullopt;
+ }
- // No directive can currently have more than two parameters, including
- // 'report-to'.
- if (directive.params.size() > 2)
- return base::nullopt;
+ const std::string& feature_name = feature_token.GetString();
+
+ if (feature_name == kWildCard)
+ return ParseWildcardFeature(directive, logger);
- std::string feature_name = feature_token.GetString();
auto feature_iter = name_feature_map.find(feature_name);
// Parse feature_name string to DocumentPolicyFeature.
@@ -69,77 +136,139 @@ base::Optional<ParsedFeature> ParseFeature(
feature_iter = name_feature_map.find(feature_name.substr(3));
if (feature_iter != name_feature_map.end()) {
parsed_feature.feature = feature_iter->second;
- // "no-" prefix is exclusively for policy with Boolean policy value.
if (feature_info_map.at(parsed_feature.feature).default_value.Type() !=
- mojom::blink::PolicyValueType::kBool)
+ mojom::blink::PolicyValueType::kBool) {
+ logger.Warn(String::Format(
+ "\"no-\" prefix is exclusively for policy with boolean policy "
+ "value. Feature %s does not support boolean policy value.",
+ feature_name.c_str()));
return base::nullopt;
+ }
+
parsed_feature.policy_value = PolicyValue(false);
} else {
- return base::nullopt; // Unrecognized feature name.
+ logger.Warn(
+ String::Format("Unrecognized document policy feature name %s.",
+ feature_name.c_str()));
+ return base::nullopt;
}
} else {
- return base::nullopt; // Unrecognized feature name.
+ logger.Warn(String::Format("Unrecognized document policy feature name %s.",
+ feature_name.c_str()));
+ return base::nullopt;
}
+ auto expected_policy_value_type =
+ feature_info_map.at(parsed_feature.feature).default_value.Type();
// Handle boolean value.
// For document policy that has a boolean policy value, policy value is not
// specified as directive param. Instead, the value is expressed using "no-"
// prefix, e.g. for feature X, "X" itself in header should be parsed as true,
// "no-X" should be parsed as false.
- if (feature_info_map.at(parsed_feature.feature).default_value.Type() ==
- mojom::blink::PolicyValueType::kBool &&
+ if (expected_policy_value_type == mojom::blink::PolicyValueType::kBool &&
parsed_feature.policy_value.Type() ==
mojom::blink::PolicyValueType::kNull)
parsed_feature.policy_value = PolicyValue(true);
+ const std::string& policy_value_param_name =
+ feature_info_map.at(parsed_feature.feature).feature_param_name;
for (const auto& param : directive.params) {
const std::string& param_name = param.first;
// Handle "report-to" param. "report-to" is an optional param for
// Document-Policy header that specifies the endpoint group that the policy
// should send report to. If left unspecified, no report will be send upon
// policy violation.
- if (param_name == "report-to") {
- base::Optional<std::string> endpoint_group = ItemToString(param.second);
- if (!endpoint_group)
+ if (param_name == kReportTo) {
+ parsed_feature.endpoint_group = ItemToString(param.second);
+ if (!parsed_feature.endpoint_group) {
+ logger.Warn(String::Format(
+ "\"report-to\" parameter should be a token in feature %s.",
+ feature_name.c_str()));
return base::nullopt;
- parsed_feature.endpoint_group = *endpoint_group;
- } else {
+ }
+ } else if (param_name == policy_value_param_name) {
// Handle policy value. For all non-boolean policy value types, they
// should be specified as FeatureX;f=xxx, with f representing the
// |feature_param_name| and xxx representing policy value.
- // |param_name| does not match param_name in config.
- if (param_name !=
- feature_info_map.at(parsed_feature.feature).feature_param_name)
- return base::nullopt;
// |parsed_feature.policy_value| should not be assigned yet.
DCHECK(parsed_feature.policy_value.Type() ==
mojom::blink::PolicyValueType::kNull);
base::Optional<PolicyValue> policy_value =
- ItemToPolicyValue(param.second);
- if (!policy_value)
+ ItemToPolicyValue(param.second, expected_policy_value_type);
+ if (!policy_value) {
+ logger.Warn(String::Format(
+ "Parameter %s in feature %s should be %s, but get %s.",
+ policy_value_param_name.c_str(), feature_name.c_str(),
+ PolicyValueTypeToString(expected_policy_value_type),
+ ItemTypeToString(param.second.Type())));
return base::nullopt;
+ }
parsed_feature.policy_value = *policy_value;
+ } else {
+ // Unrecognized param.
+ logger.Warn(
+ String::Format("Unrecognized parameter name %s for feature %s.",
+ param_name.c_str(), feature_name.c_str()));
}
}
// |parsed_feature.policy_value| should be initialized.
if (parsed_feature.policy_value.Type() ==
- mojom::blink::PolicyValueType::kNull)
+ mojom::blink::PolicyValueType::kNull) {
+ logger.Warn(String::Format(
+ "Policy value parameter missing for feature %s. Expected "
+ "something like \"%s;%s=...\".",
+ feature_name.c_str(), feature_name.c_str(),
+ policy_value_param_name.c_str()));
return base::nullopt;
+ }
return parsed_feature;
}
+// Apply |default_endpoint| to given |parsed_policy|.
+void ApplyDefaultEndpoint(DocumentPolicy::ParsedDocumentPolicy& parsed_policy,
+ const std::string& default_endpoint) {
+ DocumentPolicy::FeatureEndpointMap& endpoint_map = parsed_policy.endpoint_map;
+
+ if (!default_endpoint.empty()) {
+ // Fill |default_endpoint| to all feature entry whose |endpoint_group|
+ // is missing.
+ for (const auto& feature_and_value : parsed_policy.feature_state) {
+ mojom::blink::DocumentPolicyFeature feature = feature_and_value.first;
+
+ if (endpoint_map.find(feature) == endpoint_map.end())
+ endpoint_map.emplace(feature, default_endpoint);
+ }
+ }
+
+ // Remove |endpoint_group| for feature entry if its |endpoint_group|
+ // is "none".
+ // Note: if |default_endpoint| is "none", all "none" items are filtered out
+ // here. it would be equivalent to doing nothing.
+ for (auto iter = endpoint_map.begin(); iter != endpoint_map.end();) {
+ if (iter->second == kNone) {
+ iter = endpoint_map.erase(iter);
+ } else {
+ ++iter;
+ }
+ }
+}
+
} // namespace
// static
base::Optional<DocumentPolicy::ParsedDocumentPolicy>
-DocumentPolicyParser::Parse(const String& policy_string) {
+DocumentPolicyParser::Parse(const String& policy_string,
+ PolicyParserMessageBuffer& logger) {
+ if (policy_string.IsEmpty())
+ return base::make_optional<DocumentPolicy::ParsedDocumentPolicy>({});
+
return ParseInternal(policy_string, GetDocumentPolicyNameFeatureMap(),
GetDocumentPolicyFeatureInfoMap(),
- GetAvailableDocumentPolicyFeatures());
+ GetAvailableDocumentPolicyFeatures(), logger);
}
// static
@@ -148,22 +277,33 @@ DocumentPolicyParser::ParseInternal(
const String& policy_string,
const DocumentPolicyNameFeatureMap& name_feature_map,
const DocumentPolicyFeatureInfoMap& feature_info_map,
- const DocumentPolicyFeatureSet& available_features) {
+ const DocumentPolicyFeatureSet& available_features,
+ PolicyParserMessageBuffer& logger) {
auto root = net::structured_headers::ParseList(policy_string.Ascii());
- if (!root)
+ if (!root) {
+ logger.Error(
+ "Parse of document policy failed because of errors reported by "
+ "structured header parser.");
return base::nullopt;
+ }
DocumentPolicy::ParsedDocumentPolicy parse_result;
+ std::string default_endpoint = "";
for (const net::structured_headers::ParameterizedMember& directive :
root.value()) {
base::Optional<ParsedFeature> parsed_feature_option =
- ParseFeature(directive, name_feature_map, feature_info_map);
+ ParseFeature(directive, name_feature_map, feature_info_map, logger);
// If a feature fails parsing, ignore the entry.
if (!parsed_feature_option)
continue;
ParsedFeature parsed_feature = *parsed_feature_option;
+ if (parsed_feature.is_wildcard) {
+ default_endpoint = *parsed_feature.endpoint_group;
+ continue;
+ }
+
// If feature is not available, i.e. not enabled, ignore the entry.
if (available_features.find(parsed_feature.feature) ==
available_features.end())
@@ -176,6 +316,9 @@ DocumentPolicyParser::ParseInternal(
*parsed_feature.endpoint_group);
}
}
+
+ ApplyDefaultEndpoint(parse_result, default_endpoint);
+
return parse_result;
}
diff --git a/chromium/third_party/blink/renderer/core/feature_policy/document_policy_parser.h b/chromium/third_party/blink/renderer/core/feature_policy/document_policy_parser.h
index 660b703081c..924801755e1 100644
--- a/chromium/third_party/blink/renderer/core/feature_policy/document_policy_parser.h
+++ b/chromium/third_party/blink/renderer/core/feature_policy/document_policy_parser.h
@@ -8,10 +8,10 @@
#include "third_party/blink/public/common/feature_policy/document_policy.h"
#include "third_party/blink/public/common/feature_policy/document_policy_features.h"
#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/core/feature_policy/feature_policy_helper.h"
-#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
+#include "third_party/blink/renderer/core/feature_policy/policy_helper.h"
namespace blink {
+
class CORE_EXPORT DocumentPolicyParser {
STATIC_ONLY(DocumentPolicyParser);
@@ -19,14 +19,16 @@ class CORE_EXPORT DocumentPolicyParser {
// Parse document policy header and 'policy' attribute on iframe to
// DocumentPolicy::FeatureState.
static base::Optional<DocumentPolicy::ParsedDocumentPolicy> Parse(
- const String& policy_string);
+ const String& policy_string,
+ PolicyParserMessageBuffer&);
// Internal parsing method for testing.
static base::Optional<DocumentPolicy::ParsedDocumentPolicy> ParseInternal(
const String& policy_string,
const DocumentPolicyNameFeatureMap& name_feature_map,
const DocumentPolicyFeatureInfoMap& feature_info_map,
- const DocumentPolicyFeatureSet& available_features);
+ const DocumentPolicyFeatureSet& available_features,
+ PolicyParserMessageBuffer&);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/feature_policy/document_policy_parser_test.cc b/chromium/third_party/blink/renderer/core/feature_policy/document_policy_parser_test.cc
index 61e6fbc2fa3..2c8efefcef1 100644
--- a/chromium/third_party/blink/renderer/core/feature_policy/document_policy_parser_test.cc
+++ b/chromium/third_party/blink/renderer/core/feature_policy/document_policy_parser_test.cc
@@ -11,149 +11,400 @@
namespace blink {
namespace {
-using DocumentPolicyParserTest = ::testing::Test;
-
-const char* const kValidPolicies[] = {
- "", // An empty policy.
- " ", // An empty policy.
- "font-display-late-swap",
- "no-font-display-late-swap",
- "unoptimized-lossless-images;bpp=1.0",
- "unoptimized-lossless-images;bpp=2",
- "unoptimized-lossless-images;bpp=2.0,no-font-display-late-swap",
- "no-font-display-late-swap,unoptimized-lossless-images;bpp=2.0",
- "no-font-display-late-swap;report-to=default,unoptimized-lossless-images;"
- "bpp=2.0",
- "no-font-display-late-swap;report-to=default,unoptimized-lossless-images;"
- "bpp=2.0;report-to=default",
- "no-font-display-late-swap;report-to=default,unoptimized-lossless-images;"
- "report-to=default;bpp=2.0",
- "no-font-display-late-swap;report-to=default,unoptimized-lossless-images;"
- "report-to=endpoint;bpp=2.0",
-};
+constexpr const mojom::blink::DocumentPolicyFeature kBoolFeature =
+ static_cast<mojom::blink::DocumentPolicyFeature>(1);
+constexpr const mojom::blink::DocumentPolicyFeature kDoubleFeature =
+ static_cast<mojom::blink::DocumentPolicyFeature>(2);
+
+class DocumentPolicyParserTest : public ::testing::Test {
+ protected:
+ DocumentPolicyParserTest()
+ : name_feature_map(DocumentPolicyNameFeatureMap{
+ {"f-bool", kBoolFeature},
+ {"f-double", kDoubleFeature},
+ }),
+ feature_info_map(DocumentPolicyFeatureInfoMap{
+ {kBoolFeature, {"f-bool", "", PolicyValue(true)}},
+ {kDoubleFeature, {"f-double", "value", PolicyValue(1.0)}},
+ }) {
+ available_features.insert(kBoolFeature);
+ available_features.insert(kDoubleFeature);
+ }
+
+ ~DocumentPolicyParserTest() override = default;
+
+ base::Optional<DocumentPolicy::ParsedDocumentPolicy> Parse(
+ const String& policy_string,
+ PolicyParserMessageBuffer& logger) {
+ return DocumentPolicyParser::ParseInternal(policy_string, name_feature_map,
+ feature_info_map,
+ available_features, logger);
+ }
+
+ base::Optional<std::string> Serialize(
+ const DocumentPolicy::FeatureState& policy) {
+ return DocumentPolicy::SerializeInternal(policy, feature_info_map);
+ }
+
+ private:
+ const DocumentPolicyNameFeatureMap name_feature_map;
+ const DocumentPolicyFeatureInfoMap feature_info_map;
+ DocumentPolicyFeatureSet available_features;
+
+ protected:
+ struct ParseTestCase {
+ const char* test_name;
+ const char* input_string;
+ DocumentPolicy::ParsedDocumentPolicy parsed_policy;
+ Vector<PolicyParserMessageBuffer::Message> messages;
+ };
-const char* const kInvalidPolicies[] = {
- "bad-feature-name", "no-bad-feature-name",
- "font-display-late-swap;value=true", // unnecessary param
- "unoptimized-lossless-images;bpp=?0", // wrong type of param
- "unoptimized-lossless-images;ppb=2", // wrong param key
- "\"font-display-late-swap\"", // policy member should be token instead of
- // string
- "();bpp=2", // empty feature token
- "(font-display-late-swap unoptimized-lossless-images);bpp=2", // too many
- // feature
- // tokens
- "unoptimized-lossless-images;report-to=default", // missing param
- "font-display-late-swap;report-to=\"default\"", // report-to member should
- // be token instead of
- // string
+ // |kPolicyParseTestCases| is made as a member of
+ // |DocumentPolicyParserTest| because |PolicyParserMessageBuffer::Message| has
+ // a member of type WTF::String which cannot be statically allocated.
+ const std::vector<ParseTestCase> kPolicyParseTestCases = {
+ //
+ // Parse valid policy strings.
+ //
+ {
+ "Parse an empty policy string.",
+ "",
+ /* parsed_policy */
+ {
+ /* feature_state */ {},
+ /* endpoint_map */ {},
+ },
+ /* messages */ {},
+ },
+ {
+ "Parse an empty policy string.",
+ " ",
+ /* parsed_policy */
+ {
+ /* feature_state */ {},
+ /* endpoint_map */ {},
+ },
+ /* messages */ {},
+ },
+ {
+ "Parse bool feature with value true.",
+ "f-bool",
+ /* parsed_policy */
+ {
+ /* feature_state */ {{kBoolFeature, PolicyValue(true)}},
+ /* endpoint_map */ {},
+ },
+ /* messages */ {},
+ },
+ {
+ "Parse bool feature with value false.",
+ "no-f-bool",
+ /* parsed_policy */
+ {
+ /* feature_state */ {{kBoolFeature, PolicyValue(false)}},
+ /* endpoint_map */ {},
+ },
+ /* messages */ {},
+ },
+ {
+ "Parse double feature with value 1.0.",
+ "f-double;value=1.0",
+ /* parsed_policy */
+ {
+ /* feature_state */ {{kDoubleFeature, PolicyValue(1.0)}},
+ /* endpoint_map */ {},
+ },
+ /* messages */ {},
+ },
+ {
+ "Parse double feature with value literal 2.",
+ "f-double;value=2",
+ /* parsed_policy */
+ {
+ /* feature_state */ {{kDoubleFeature, PolicyValue(2.0)}},
+ /* endpoint_map */ {},
+ },
+ /* messages */ {},
+ },
+ {
+ "Parse double feature and bool feature.",
+ "f-double;value=1,no-f-bool",
+ /* parsed_policy */
+ {
+ /* feature_state */ {{kBoolFeature, PolicyValue(false)},
+ {kDoubleFeature, PolicyValue(1.0)}},
+ /* endpoint_map */ {},
+ },
+ /* messages */ {},
+ },
+ {
+ "Parse bool feature and double feature.",
+ "no-f-bool,f-double;value=1",
+ /* parsed_policy */
+ {
+ /* feature_state */ {{kBoolFeature, PolicyValue(false)},
+ {kDoubleFeature, PolicyValue(1.0)}},
+ /* endpoint_map */ {},
+ },
+ /* messages */ {},
+ },
+ {
+ "White-space is allowed in some positions in structured-header.",
+ "no-f-bool, f-double;value=1",
+ /* parsed_policy */
+ {/* feature_state */ {{kBoolFeature, PolicyValue(false)},
+ {kDoubleFeature, PolicyValue(1.0)}},
+ /* endpoint_map */ {}},
+ /* messages */ {},
+ },
+ {
+ "Unrecognized parameters are ignored, but the feature entry should "
+ "remain valid.",
+ "no-f-bool,f-double;value=1;unknown_param=xxx",
+ /* parsed_policy */
+ {/* feature_state */ {{kBoolFeature, PolicyValue(false)},
+ {kDoubleFeature, PolicyValue(1.0)}},
+ /* endpoint_map */ {}},
+ /* messages */
+ {{mojom::blink::ConsoleMessageLevel::kWarning,
+ "Unrecognized parameter name unknown_param for feature f-double."}},
+ },
+ {
+ "Parse policy with report endpoint specified.",
+ "no-f-bool,f-double;value=1;report-to=default",
+ /* parsed_policy */
+ {/* feature_state */ {{kBoolFeature, PolicyValue(false)},
+ {kDoubleFeature, PolicyValue(1.0)}},
+ /* endpoint_map */ {{kDoubleFeature, "default"}}},
+ /* messages */ {},
+ },
+ {
+ "Parse policy with report endpoint specified.",
+ "no-f-bool;report-to=default,f-double;value=1",
+ /* parsed_policy */
+ {/* feature_state */ {{kBoolFeature, PolicyValue(false)},
+ {kDoubleFeature, PolicyValue(1.0)}},
+ /* endpoint_map */ {{kBoolFeature, "default"}}},
+ /* messages */ {},
+ },
+ {
+ "Parse policy with default report endpoint specified. 'none' "
+ "keyword should overwrite default value assignment.",
+ "no-f-bool;report-to=none, f-double;value=2.0, *;report-to=default",
+ /* parsed_policy */
+ {/* feature_state */ {{kBoolFeature, PolicyValue(false)},
+ {kDoubleFeature, PolicyValue(2.0)}},
+ /* endpoint_map */ {{kDoubleFeature, "default"}}},
+ /* messages */ {},
+ },
+ {
+ "Parse policy with default report endpoint specified.",
+ "no-f-bool;report-to=not_none, f-double;value=2.0, "
+ "*;report-to=default",
+ /* parsed_policy */
+ {/* feature_state */ {{kBoolFeature, PolicyValue(false)},
+ {kDoubleFeature, PolicyValue(2.0)}},
+ /* endpoint_map */ {{kBoolFeature, "not_none"},
+ {kDoubleFeature, "default"}}},
+ /* messages */ {},
+ },
+ {
+ "Parse policy with default report endpoint 'none'.",
+ "no-f-bool;report-to=not_none, f-double;value=2.0, *;report-to=none",
+ /* parsed_policy */
+ {/* feature_state */ {{kBoolFeature, PolicyValue(false)},
+ {kDoubleFeature, PolicyValue(2.0)}},
+ /* endpoint_map */ {{kBoolFeature, "not_none"}}},
+ /* messages */ {},
+ },
+ {
+ "Default endpoint can be specified anywhere in the header, not "
+ "necessary at the end.",
+ "no-f-bool;report-to=not_none, *;report-to=default, "
+ "f-double;value=2.0",
+ /* parsed_policy */
+ {/* feature_state */ {{kBoolFeature, PolicyValue(false)},
+ {kDoubleFeature, PolicyValue(2.0)}},
+ /* endpoint_map */ {{kBoolFeature, "not_none"},
+ {kDoubleFeature, "default"}}},
+ /* messages */ {},
+ },
+ {
+ "Default endpoint can be specified multiple times in the header. "
+ "According to SH rules, last value wins.",
+ "no-f-bool;report-to=not_none, f-double;value=2.0, "
+ "*;report-to=default, *;report-to=none",
+ /* parsed_policy */
+ {/* feature_state */ {{kBoolFeature, PolicyValue(false)},
+ {kDoubleFeature, PolicyValue(2.0)}},
+ /* endpoint_map */ {{kBoolFeature, "not_none"}}},
+ /* messages */ {},
+ },
+ {
+ "Even if default endpoint is not specified, none still should be "
+ "treated as a reserved keyword for endpoint names.",
+ "no-f-bool;report-to=none",
+ /* parsed_policy */
+ {/* feature_state */ {{kBoolFeature, PolicyValue(false)}},
+ /* endpoint_map */ {}},
+ /* messages */ {},
+ },
+
+ //
+ // Parse invalid policies.
+ //
+ {
+ "Parse policy with unrecognized feature name.",
+ "bad-feature-name",
+ /* parsed_policy */
+ {
+ /* feature_state */ {},
+ /* endpoint_map */ {},
+ },
+ /* messages */
+ {{mojom::blink::ConsoleMessageLevel::kWarning,
+ "Unrecognized document policy feature name "
+ "bad-feature-name."}},
+ },
+ {
+ "Parse policy with unrecognized feature name.",
+ "no-bad-feature-name",
+ /* parsed_policy */
+ {
+ /* feature_state */ {},
+ /* endpoint_map */ {},
+ },
+ /* messages */
+ {{mojom::blink::ConsoleMessageLevel::kWarning,
+ "Unrecognized document policy feature name "
+ "no-bad-feature-name."}},
+ },
+ {
+ "Parse policy with wrong type of param. Expected double type but get "
+ "boolean type.",
+ "f-double;value=?0",
+ /* parsed_policy */
+ {
+ /* feature_state */ {},
+ /* endpoint_map */ {},
+ },
+ /* messages */
+ {{mojom::blink::ConsoleMessageLevel::kWarning,
+ "Parameter value in feature f-double should be Double, but get "
+ "Boolean."}},
+ },
+ {
+ "Policy member should be token instead of string.",
+ "\"f-bool\"",
+ /* parsed_policy */
+ {
+ /* feature_state */ {},
+ /* endpoint_map */ {},
+ },
+ /* messages */
+ {{mojom::blink::ConsoleMessageLevel::kWarning,
+ "The item in directive should be token type."}},
+ },
+ {
+ "Feature token should not be empty.",
+ "();value=2",
+ /* parsed_policy */
+ {
+ /* feature_state */ {},
+ /* endpoint_map */ {},
+ },
+ /* messages */
+ {{mojom::blink::ConsoleMessageLevel::kWarning,
+ "Directives must not be inner lists."}},
+ },
+ {
+ "Too many feature tokens.",
+ "(f-bool f-double);value=2",
+ /* parsed_policy */
+ {
+ /* feature_state */ {},
+ /* endpoint_map */ {},
+ },
+ /* messages */
+ {{mojom::blink::ConsoleMessageLevel::kWarning,
+ "Directives must not be inner lists."}},
+ },
+ {
+ "Missing mandatory parameter.",
+ "f-double;report-to=default",
+ /* parsed_policy */
+ {
+ /* feature_state */ {},
+ /* endpoint_map */ {},
+ },
+ /* messages */
+ {{mojom::blink::ConsoleMessageLevel::kWarning,
+ "Policy value parameter missing for feature f-double. Expected "
+ "something like \"f-double;value=...\"."}},
+ },
+ {
+ "\"report-to\" parameter value type should be token instead of "
+ "string.",
+ "f-bool;report-to=\"default\"",
+ /* parsed_policy */
+ {
+ /* feature_state */ {},
+ /* endpoint_map */ {},
+ },
+ /* messages */
+ {{mojom::blink::ConsoleMessageLevel::kWarning,
+ "\"report-to\" parameter should be a token in feature f-bool."}},
+ },
+ };
};
-// TODO(chenleihu): find a DocumentPolicyFeature name start with 'f' < c < 'n'
-// to further strengthen the test on proving "no-" prefix is not counted as part
-// of feature name for ordering.
const std::pair<DocumentPolicy::FeatureState, std::string>
kPolicySerializationTestCases[] = {
- {{{blink::mojom::DocumentPolicyFeature::kFontDisplay,
- PolicyValue(false)},
- {blink::mojom::DocumentPolicyFeature::kUnoptimizedLosslessImages,
- PolicyValue(1.0)}},
- "no-font-display-late-swap, unoptimized-lossless-images;bpp=1.0"},
+ {{{kBoolFeature, PolicyValue(false)},
+ {kDoubleFeature, PolicyValue(1.0)}},
+ "no-f-bool, f-double;value=1.0"},
// Changing ordering of FeatureState element should not affect
// serialization result.
- {{{blink::mojom::DocumentPolicyFeature::kUnoptimizedLosslessImages,
- PolicyValue(1.0)},
- {blink::mojom::DocumentPolicyFeature::kFontDisplay,
- PolicyValue(false)}},
- "no-font-display-late-swap, unoptimized-lossless-images;bpp=1.0"},
+ {{{kDoubleFeature, PolicyValue(1.0)},
+ {kBoolFeature, PolicyValue(false)}},
+ "no-f-bool, f-double;value=1.0"},
// Flipping boolean-valued policy from false to true should not affect
// result ordering of feature.
- {{{blink::mojom::DocumentPolicyFeature::kFontDisplay,
- PolicyValue(true)},
- {blink::mojom::DocumentPolicyFeature::kUnoptimizedLosslessImages,
- PolicyValue(1.0)}},
- "font-display-late-swap, unoptimized-lossless-images;bpp=1.0"}};
-
-const std::pair<const char*, DocumentPolicy::ParsedDocumentPolicy>
- kPolicyParseTestCases[] = {
- {"no-font-display-late-swap,unoptimized-lossless-images;bpp=1",
- {{{blink::mojom::DocumentPolicyFeature::kFontDisplay,
- PolicyValue(false)},
- {blink::mojom::DocumentPolicyFeature::kUnoptimizedLosslessImages,
- PolicyValue(1.0)}},
- {} /* endpoint_map */}},
- // White-space is allowed in some positions in structured-header.
- {"no-font-display-late-swap, unoptimized-lossless-images;bpp=1",
- {{{blink::mojom::DocumentPolicyFeature::kFontDisplay,
- PolicyValue(false)},
- {blink::mojom::DocumentPolicyFeature::kUnoptimizedLosslessImages,
- PolicyValue(1.0)}},
- {} /* endpoint_map */}},
- {"no-font-display-late-swap,unoptimized-lossless-images;bpp=1;report-"
- "to=default",
- {{{blink::mojom::DocumentPolicyFeature::kFontDisplay,
- PolicyValue(false)},
- {blink::mojom::DocumentPolicyFeature::kUnoptimizedLosslessImages,
- PolicyValue(1.0)}},
- {{blink::mojom::DocumentPolicyFeature::kUnoptimizedLosslessImages,
- "default"}}}},
- {"no-font-display-late-swap;report-to=default,unoptimized-lossless-"
- "images;bpp=1",
- {{{blink::mojom::DocumentPolicyFeature::kFontDisplay,
- PolicyValue(false)},
- {blink::mojom::DocumentPolicyFeature::kUnoptimizedLosslessImages,
- PolicyValue(1.0)}},
- {{blink::mojom::DocumentPolicyFeature::kFontDisplay, "default"}}}}};
+ {{{kBoolFeature, PolicyValue(true)},
+ {kDoubleFeature, PolicyValue(1.0)}},
+ "f-bool, f-double;value=1.0"}};
const DocumentPolicy::FeatureState kParsedPolicies[] = {
{}, // An empty policy
- {{mojom::DocumentPolicyFeature::kFontDisplay, PolicyValue(false)}},
- {{mojom::DocumentPolicyFeature::kFontDisplay, PolicyValue(true)}},
- {{mojom::DocumentPolicyFeature::kUnoptimizedLosslessImages,
- PolicyValue(1.0)}},
- {{mojom::DocumentPolicyFeature::kFontDisplay, PolicyValue(true)},
- {mojom::DocumentPolicyFeature::kUnoptimizedLosslessImages,
- PolicyValue(1.0)}}};
+ {{kBoolFeature, PolicyValue(false)}},
+ {{kBoolFeature, PolicyValue(true)}},
+ {{kDoubleFeature, PolicyValue(1.0)}},
+ {{kBoolFeature, PolicyValue(true)}, {kDoubleFeature, PolicyValue(1.0)}}};
// Serialize and then Parse the result of serialization should cancel each
// other out, i.e. d == Parse(Serialize(d)).
// The other way s == Serialize(Parse(s)) is not always true because structured
// header allows some optional white spaces in its parsing targets and floating
-// point numbers will be rounded, e.g. bpp=1 will be parsed to PolicyValue(1.0)
-// and get serialized to bpp=1.0.
+// point numbers will be rounded, e.g. value=1 will be parsed to
+// PolicyValue(1.0) and get serialized to value=1.0.
TEST_F(DocumentPolicyParserTest, SerializeAndParse) {
for (const auto& policy : kParsedPolicies) {
- const base::Optional<std::string> policy_string =
- DocumentPolicy::Serialize(policy);
+ const base::Optional<std::string> policy_string = Serialize(policy);
ASSERT_TRUE(policy_string.has_value());
+ PolicyParserMessageBuffer logger;
const base::Optional<DocumentPolicy::ParsedDocumentPolicy> reparsed_policy =
- DocumentPolicyParser::Parse(policy_string.value().c_str());
+ Parse(policy_string.value().c_str(), logger);
ASSERT_TRUE(reparsed_policy.has_value());
EXPECT_EQ(reparsed_policy.value().feature_state, policy);
}
}
-TEST_F(DocumentPolicyParserTest, ParseValidPolicy) {
- for (const char* policy : kValidPolicies) {
- EXPECT_NE(DocumentPolicyParser::Parse(policy), base::nullopt)
- << "Should parse " << policy;
- }
-}
-
-TEST_F(DocumentPolicyParserTest, ParseInvalidPolicy) {
- for (const char* policy : kInvalidPolicies) {
- EXPECT_EQ(DocumentPolicyParser::Parse(policy),
- base::make_optional(DocumentPolicy::ParsedDocumentPolicy{}))
- << "Should fail to parse " << policy;
- }
-}
-
TEST_F(DocumentPolicyParserTest, SerializeResultShouldMatch) {
for (const auto& test_case : kPolicySerializationTestCases) {
const DocumentPolicy::FeatureState& policy = test_case.first;
const std::string& expected = test_case.second;
- const auto result = DocumentPolicy::Serialize(policy);
+ const auto result = Serialize(policy);
ASSERT_TRUE(result.has_value());
EXPECT_EQ(result.value(), expected);
@@ -162,12 +413,31 @@ TEST_F(DocumentPolicyParserTest, SerializeResultShouldMatch) {
TEST_F(DocumentPolicyParserTest, ParseResultShouldMatch) {
for (const auto& test_case : kPolicyParseTestCases) {
- const char* input = test_case.first;
- const DocumentPolicy::ParsedDocumentPolicy& expected = test_case.second;
- const auto result = DocumentPolicyParser::Parse(input);
+ const String& test_name = test_case.test_name;
+
+ PolicyParserMessageBuffer logger;
+ const auto result = Parse(test_case.input_string, logger);
+ // All tesecases should not return base::nullopt because they all comply to
+ // structured header syntax.
ASSERT_TRUE(result.has_value());
- EXPECT_EQ(result.value(), expected);
+
+ EXPECT_EQ(result->endpoint_map, test_case.parsed_policy.endpoint_map)
+ << test_name << "\n endpoint map should match";
+ EXPECT_EQ(result->feature_state, test_case.parsed_policy.feature_state)
+ << test_name << "\n feature state should match";
+ EXPECT_EQ(logger.GetMessages().size(), test_case.messages.size())
+ << test_name << "\n messages length should match";
+ for (auto *it_actual = logger.GetMessages().begin(),
+ *it_expected = test_case.messages.begin();
+ it_actual != logger.GetMessages().end() &&
+ it_expected != test_case.messages.end();
+ it_actual++, it_expected++) {
+ EXPECT_EQ(it_actual->level, it_expected->level)
+ << test_name << "\n message level should match";
+ EXPECT_EQ(it_actual->content, it_expected->content)
+ << test_name << "\n message content should match";
+ }
}
}
diff --git a/chromium/third_party/blink/renderer/core/feature_policy/dom_feature_policy.cc b/chromium/third_party/blink/renderer/core/feature_policy/dom_feature_policy.cc
index d5ebc9620df..21ed39cb154 100644
--- a/chromium/third_party/blink/renderer/core/feature_policy/dom_feature_policy.cc
+++ b/chromium/third_party/blink/renderer/core/feature_policy/dom_feature_policy.cc
@@ -21,10 +21,7 @@ bool DOMFeaturePolicy::allowsFeature(ScriptState* script_state,
script_state ? ExecutionContext::From(script_state) : nullptr;
if (GetAvailableFeatures(execution_context).Contains(feature)) {
auto feature_name = GetDefaultFeatureNameMap().at(feature);
- mojom::PolicyValueType feature_type =
- GetPolicy()->GetFeatureList().at(feature_name).second;
- PolicyValue value = PolicyValue::CreateMaxPolicyValue(feature_type);
- return GetPolicy()->IsFeatureEnabled(feature_name, value);
+ return GetPolicy()->IsFeatureEnabled(feature_name);
}
AddWarningForUnrecognizedFeature(feature);
@@ -52,11 +49,8 @@ bool DOMFeaturePolicy::allowsFeature(ScriptState* script_state,
}
auto feature_name = GetDefaultFeatureNameMap().at(feature);
- mojom::PolicyValueType feature_type =
- GetPolicy()->GetFeatureList().at(feature_name).second;
- PolicyValue value = PolicyValue::CreateMaxPolicyValue(feature_type);
return GetPolicy()->IsFeatureEnabledForOrigin(feature_name,
- origin->ToUrlOrigin(), value);
+ origin->ToUrlOrigin());
}
Vector<String> DOMFeaturePolicy::features(ScriptState* script_state) const {
@@ -72,10 +66,7 @@ Vector<String> DOMFeaturePolicy::allowedFeatures(
Vector<String> allowed_features;
for (const String& feature : GetAvailableFeatures(execution_context)) {
auto feature_name = GetDefaultFeatureNameMap().at(feature);
- mojom::PolicyValueType feature_type =
- GetPolicy()->GetFeatureList().at(feature_name).second;
- PolicyValue value = PolicyValue::CreateMaxPolicyValue(feature_type);
- if (GetPolicy()->IsFeatureEnabled(feature_name, value))
+ if (GetPolicy()->IsFeatureEnabled(feature_name))
allowed_features.push_back(feature);
}
return allowed_features;
@@ -88,21 +79,17 @@ Vector<String> DOMFeaturePolicy::getAllowlistForFeature(
script_state ? ExecutionContext::From(script_state) : nullptr;
if (GetAvailableFeatures(execution_context).Contains(feature)) {
auto feature_name = GetDefaultFeatureNameMap().at(feature);
- auto feature_type = GetPolicy()->GetFeatureList().at(feature_name).second;
const FeaturePolicy::Allowlist allowlist =
GetPolicy()->GetAllowlistForFeature(feature_name);
- auto values = allowlist.Values();
- PolicyValue max_value = PolicyValue::CreateMaxPolicyValue(feature_type);
- if (values.empty()) {
- if (allowlist.GetFallbackValue().Type() !=
- mojom::PolicyValueType::kNull &&
- allowlist.GetFallbackValue() >= max_value)
+ const auto& allowed_origins = allowlist.AllowedOrigins();
+ if (allowed_origins.empty()) {
+ if (allowlist.GetFallbackValue())
return Vector<String>({"*"});
}
Vector<String> result;
- for (const auto& entry : values) {
- result.push_back(WTF::String::FromUTF8(entry.first.Serialize()));
+ for (const auto& origin : allowed_origins) {
+ result.push_back(WTF::String::FromUTF8(origin.Serialize()));
}
return result;
}
diff --git a/chromium/third_party/blink/renderer/core/feature_policy/feature_policy_features.json5 b/chromium/third_party/blink/renderer/core/feature_policy/feature_policy_features.json5
index 7e0db368b83..39ecf9542e6 100644
--- a/chromium/third_party/blink/renderer/core/feature_policy/feature_policy_features.json5
+++ b/chromium/third_party/blink/renderer/core/feature_policy/feature_policy_features.json5
@@ -104,6 +104,11 @@
depends_on: ["FeaturePolicyForClientHints"],
},
{
+ name: "ClientHintUAPlatformVersion",
+ feature_policy_name: "ch-ua-platform-version",
+ depends_on: ["FeaturePolicyForClientHints"],
+ },
+ {
name: "ClientHintViewportWidth",
feature_policy_name: "ch-viewport-width",
depends_on: ["FeaturePolicyForClientHints"],
@@ -114,6 +119,11 @@
depends_on: ["FeaturePolicyForClientHints"],
},
{
+ name: "ConversionMeasurement",
+ feature_policy_name: "conversion-measurement",
+ depends_on: ["ConversionMeasurement"],
+ },
+ {
name: "DocumentDomain",
feature_policy_name: "document-domain",
},
@@ -179,11 +189,6 @@
depends_on: ["IdleDetection"],
},
{
- name: "LayoutAnimations",
- feature_policy_name: "layout-animations",
- depends_on: ["ExperimentalProductivityFeatures"],
- },
- {
name: "LazyLoad",
feature_policy_name: "lazyload",
depends_on: ["ExperimentalProductivityFeatures"],
@@ -241,9 +246,9 @@
depends_on: ["FeaturePolicyForSandbox"],
},
{
- name: "PublicKeyCredentials",
- feature_policy_name: "publickey-credentials",
- depends_on: ["WebAuthenticationFeaturePolicy"],
+ name: "PublicKeyCredentialsGet",
+ feature_policy_name: "publickey-credentials-get",
+ depends_on: ["WebAuthenticationGetAssertionFeaturePolicy"],
},
{
name: "ScreenWakeLock",
diff --git a/chromium/third_party/blink/renderer/core/feature_policy/feature_policy_parser.cc b/chromium/third_party/blink/renderer/core/feature_policy/feature_policy_parser.cc
index 0c08fe742ce..8bf93369dde 100644
--- a/chromium/third_party/blink/renderer/core/feature_policy/feature_policy_parser.cc
+++ b/chromium/third_party/blink/renderer/core/feature_policy/feature_policy_parser.cc
@@ -4,7 +4,6 @@
#include "third_party/blink/renderer/core/feature_policy/feature_policy_parser.h"
#include <algorithm>
-#include <map>
#include <utility>
#include <bitset>
@@ -25,366 +24,402 @@
#include "url/origin.h"
namespace blink {
+namespace {
+
+class ParsingContext {
+ public:
+ ParsingContext(Vector<String>* messages,
+ scoped_refptr<const SecurityOrigin> self_origin,
+ scoped_refptr<const SecurityOrigin> src_origin,
+ const FeatureNameMap& feature_names,
+ FeaturePolicyParserDelegate* delegate)
+ : messages_(messages),
+ self_origin_(self_origin),
+ src_origin_(src_origin),
+ feature_names_(feature_names),
+ delegate_(delegate) {}
+
+ ~ParsingContext() = default;
+
+ ParsedFeaturePolicy Parse(const String& policy);
+
+ private:
+ // normally 1 char = 1 byte
+ // max length to parse = 2^16 = 64 kB
+ static constexpr wtf_size_t MAX_LENGTH_PARSE = 1 << 16;
+
+ // Parse a single feature entry. e.g. feature_a ORIGIN_A ORIGIN_B.
+ // feature_entry = feature_name ' ' allowlist
+ base::Optional<ParsedFeaturePolicyDeclaration> ParseFeature(
+ const String& input);
+
+ struct ParsedAllowlist {
+ std::vector<url::Origin> allowed_origins;
+ bool fallback_value;
+ bool opaque_value;
+
+ ParsedAllowlist()
+ : allowed_origins({}), fallback_value(false), opaque_value(false) {}
+ };
+
+ base::Optional<mojom::blink::FeaturePolicyFeature> ParseFeatureName(
+ const String& feature_name);
+
+ // Parse allowlist for feature.
+ ParsedAllowlist ParseAllowlist(const Vector<String>& origin_strings);
+
+ inline void Log(const String& message) {
+ if (messages_)
+ messages_->push_back(message);
+ }
-ParsedFeaturePolicy FeaturePolicyParser::ParseHeader(
- const String& policy,
- scoped_refptr<const SecurityOrigin> origin,
- Vector<String>* messages,
- FeaturePolicyParserDelegate* delegate) {
- return Parse(policy, origin, nullptr, messages, GetDefaultFeatureNameMap(),
- delegate);
-}
+ bool FeatureObserved(mojom::blink::FeaturePolicyFeature feature);
-ParsedFeaturePolicy FeaturePolicyParser::ParseAttribute(
- const String& policy,
- scoped_refptr<const SecurityOrigin> self_origin,
- scoped_refptr<const SecurityOrigin> src_origin,
- Vector<String>* messages,
- Document* document) {
- return Parse(policy, self_origin, src_origin, messages,
- GetDefaultFeatureNameMap(), document);
+ void ReportFeaturePolicyWebFeatureUsage(mojom::blink::WebFeature feature);
+
+ void ReportFeatureUsage(mojom::blink::FeaturePolicyFeature feature);
+
+ // This function should be called after Allowlist Histograms related flags
+ // have been captured.
+ void RecordAllowlistTypeUsage(size_t origin_count);
+ // The use of various allowlist types should only be recorded once per page.
+ // For simplicity, this recording assumes that the ParseHeader method is
+ // called once when creating a new document, and similarly the ParseAttribute
+ // method is called once for a frame. It is possible for multiple calls, but
+ // the additional complexity to guarantee only one record isn't warranted as
+ // yet.
+ void ReportAllowlistTypeUsage();
+
+ Vector<String>* messages_;
+ scoped_refptr<const SecurityOrigin> self_origin_;
+ scoped_refptr<const SecurityOrigin> src_origin_;
+ const FeatureNameMap& feature_names_;
+ FeaturePolicyParserDelegate* delegate_;
+
+ // Flags for the types of items which can be used in allowlists.
+ bool allowlist_includes_star_ = false;
+ bool allowlist_includes_self_ = false;
+ bool allowlist_includes_src_ = false;
+ bool allowlist_includes_none_ = false;
+ bool allowlist_includes_origin_ = false;
+
+ HashSet<FeaturePolicyAllowlistType> allowlist_types_used_;
+ std::bitset<
+ static_cast<size_t>(mojom::blink::FeaturePolicyFeature::kMaxValue) + 1>
+ features_specified_;
+};
+
+bool ParsingContext::FeatureObserved(
+ mojom::blink::FeaturePolicyFeature feature) {
+ if (features_specified_[static_cast<size_t>(feature)]) {
+ return true;
+ } else {
+ features_specified_.set(static_cast<size_t>(feature));
+ return false;
+ }
}
-// normally 1 char = 1 byte
-// max length to parse = 2^16 = 64 kB
-constexpr wtf_size_t MAX_LENGTH_PARSE = 1 << 16;
+void ParsingContext::ReportFeaturePolicyWebFeatureUsage(
+ mojom::blink::WebFeature feature) {
+ if (delegate_)
+ delegate_->CountFeaturePolicyUsage(feature);
+}
-ParsedFeaturePolicy FeaturePolicyParser::Parse(
- const String& policy,
- scoped_refptr<const SecurityOrigin> self_origin,
- scoped_refptr<const SecurityOrigin> src_origin,
- Vector<String>* messages,
- const FeatureNameMap& feature_names,
- FeaturePolicyParserDelegate* delegate) {
- ParsedFeaturePolicy allowlists;
+void ParsingContext::ReportFeatureUsage(
+ mojom::blink::FeaturePolicyFeature feature) {
+ if (src_origin_) {
+ if (!delegate_ || !delegate_->FeaturePolicyFeatureObserved(feature)) {
+ UMA_HISTOGRAM_ENUMERATION("Blink.UseCounter.FeaturePolicy.Allow",
+ feature);
+ }
+ } else {
+ UMA_HISTOGRAM_ENUMERATION("Blink.UseCounter.FeaturePolicy.Header", feature);
+ }
+}
- if (policy.length() > MAX_LENGTH_PARSE) {
- if (messages) {
- messages->push_back("Feature policy declaration exceeds size limit(" +
- String::Number(policy.length()) + ">" +
- String::Number(MAX_LENGTH_PARSE) + ")");
+void ParsingContext::RecordAllowlistTypeUsage(size_t origin_count) {
+ // Record the type of allowlist used.
+ if (origin_count == 0) {
+ allowlist_types_used_.insert(FeaturePolicyAllowlistType::kEmpty);
+ } else if (origin_count == 1) {
+ if (allowlist_includes_star_)
+ allowlist_types_used_.insert(FeaturePolicyAllowlistType::kStar);
+ else if (allowlist_includes_self_)
+ allowlist_types_used_.insert(FeaturePolicyAllowlistType::kSelf);
+ else if (allowlist_includes_src_)
+ allowlist_types_used_.insert(FeaturePolicyAllowlistType::kSrc);
+ else if (allowlist_includes_none_)
+ allowlist_types_used_.insert(FeaturePolicyAllowlistType::kNone);
+ else
+ allowlist_types_used_.insert(FeaturePolicyAllowlistType::kOrigins);
+ } else {
+ if (allowlist_includes_origin_) {
+ if (allowlist_includes_star_ || allowlist_includes_none_ ||
+ allowlist_includes_src_ || allowlist_includes_self_)
+ allowlist_types_used_.insert(FeaturePolicyAllowlistType::kMixed);
+ else
+ allowlist_types_used_.insert(FeaturePolicyAllowlistType::kOrigins);
+ } else {
+ allowlist_types_used_.insert(FeaturePolicyAllowlistType::kKeywordsOnly);
}
- return allowlists;
}
+ // Reset all flags.
+ allowlist_includes_star_ = false;
+ allowlist_includes_self_ = false;
+ allowlist_includes_src_ = false;
+ allowlist_includes_none_ = false;
+ allowlist_includes_origin_ = false;
+}
- std::bitset<
- static_cast<size_t>(mojom::blink::FeaturePolicyFeature::kMaxValue) + 1>
- features_specified;
- HashSet<FeaturePolicyAllowlistType> allowlist_types_used;
+void ParsingContext::ReportAllowlistTypeUsage() {
+ for (const FeaturePolicyAllowlistType allowlist_type :
+ allowlist_types_used_) {
+ if (src_origin_) {
+ UMA_HISTOGRAM_ENUMERATION(
+ "Blink.UseCounter.FeaturePolicy.AttributeAllowlistType",
+ allowlist_type);
+ } else {
+ UMA_HISTOGRAM_ENUMERATION(
+ "Blink.UseCounter.FeaturePolicy.HeaderAllowlistType", allowlist_type);
+ }
+ }
+}
- // RFC2616, section 4.2 specifies that headers appearing multiple times can be
- // combined with a comma. Walk the header string, and parse each comma
- // separated chunk as a separate header.
- Vector<String> policy_items;
- // policy_items = [ policy *( "," [ policy ] ) ]
- policy.Split(',', policy_items);
- if (policy_items.size() > 1 && delegate) {
- delegate->CountFeaturePolicyUsage(
- mojom::WebFeature::kFeaturePolicyCommaSeparatedDeclarations);
+base::Optional<mojom::blink::FeaturePolicyFeature>
+ParsingContext::ParseFeatureName(const String& feature_name) {
+ DCHECK(!feature_name.IsEmpty());
+ if (!feature_names_.Contains(feature_name)) {
+ Log("Unrecognized feature: '" + feature_name + "'.");
+ return base::nullopt;
}
- for (const String& item : policy_items) {
- Vector<String> entry_list;
- // entry_list = [ entry *( ";" [ entry ] ) ]
- item.Split(';', entry_list);
- if (entry_list.size() > 1 && delegate) {
- delegate->CountFeaturePolicyUsage(
- mojom::WebFeature::kFeaturePolicySemicolonSeparatedDeclarations);
+ if (DisabledByOriginTrial(feature_name, delegate_)) {
+ Log("Origin trial controlled feature not enabled: '" + feature_name + "'.");
+ return base::nullopt;
+ }
+ mojom::blink::FeaturePolicyFeature feature = feature_names_.at(feature_name);
+
+ return feature;
+}
+
+ParsingContext::ParsedAllowlist ParsingContext::ParseAllowlist(
+ const Vector<String>& origin_strings) {
+ ParsedAllowlist allowlist;
+ if (origin_strings.IsEmpty()) {
+ // If a policy entry has no listed origins (e.g. "feature_name1" in
+ // allow="feature_name1; feature_name2 value"), enable the feature for:
+ // a. |self_origin|, if we are parsing a header policy (i.e.,
+ // |src_origin| is null);
+ // b. |src_origin|, if we are parsing an allow attribute (i.e.,
+ // |src_origin| is not null), |src_origin| is not opaque; or
+ // c. the opaque origin of the frame, if |src_origin| is opaque.
+ if (!src_origin_) {
+ allowlist.allowed_origins.push_back(self_origin_->ToUrlOrigin());
+ } else if (!src_origin_->IsOpaque()) {
+ allowlist.allowed_origins.push_back(src_origin_->ToUrlOrigin());
+ } else {
+ allowlist.opaque_value = true;
}
- for (const String& entry : entry_list) {
- // Split removes extra whitespaces by default
- // "name value1 value2" or "name".
- Vector<String> tokens;
- entry.Split(' ', tokens);
- // Empty policy. Skip.
- if (tokens.IsEmpty())
- continue;
+ } else {
+ for (const String& origin_string : origin_strings) {
+ DCHECK(!origin_string.IsEmpty());
- String feature_name = tokens[0];
- if (!feature_names.Contains(feature_name)) {
- if (messages) {
- messages->push_back("Unrecognized feature: '" + tokens[0] + "'.");
- }
+ if (!origin_string.ContainsOnlyASCIIOrEmpty()) {
+ Log("Non-ASCII characters in origin.");
continue;
}
- if (DisabledByOriginTrial(feature_name, delegate)) {
- if (messages) {
- messages->push_back("Origin trial controlled feature not enabled: '" +
- tokens[0] + "'.");
+ // Determine the target of the declaration. This may be a specific
+ // origin, either explicitly written, or one of the special keywords
+ // 'self' or 'src'. ('src' can only be used in the iframe allow
+ // attribute.)
+ url::Origin target_origin;
+
+ // If the iframe will have an opaque origin (for example, if it is
+ // sandboxed, or has a data: URL), then 'src' needs to refer to the
+ // opaque origin of the frame, which is not known yet. In this case,
+ // the |opaque_value| on the declaration is set, rather than adding
+ // an origin to the allowlist.
+ bool target_is_opaque = false;
+ bool target_is_all = false;
+
+ // 'self' origin is used if the origin is exactly 'self'.
+ if (EqualIgnoringASCIICase(origin_string, "'self'")) {
+ allowlist_includes_self_ = true;
+ target_origin = self_origin_->ToUrlOrigin();
+ }
+ // 'src' origin is used if |src_origin| is available and the
+ // origin is a match for 'src'. |src_origin| is only set
+ // when parsing an iframe allow attribute.
+ else if (src_origin_ && EqualIgnoringASCIICase(origin_string, "'src'")) {
+ allowlist_includes_src_ = true;
+ if (!src_origin_->IsOpaque()) {
+ target_origin = src_origin_->ToUrlOrigin();
+ } else {
+ target_is_opaque = true;
}
+ } else if (EqualIgnoringASCIICase(origin_string, "'none'")) {
+ allowlist_includes_none_ = true;
continue;
+ } else if (origin_string == "*") {
+ allowlist_includes_star_ = true;
+ target_is_all = true;
}
-
- mojom::blink::FeaturePolicyFeature feature =
- feature_names.at(feature_name);
- mojom::PolicyValueType feature_type =
- FeaturePolicy::GetDefaultFeatureList().at(feature).second;
- // If a policy has already been specified for the current feature, drop
- // the new policy.
- if (features_specified[static_cast<size_t>(feature)])
- continue;
-
- // Count the use of this feature policy.
- if (src_origin) {
- if (!delegate || !delegate->FeaturePolicyFeatureObserved(feature)) {
- UMA_HISTOGRAM_ENUMERATION("Blink.UseCounter.FeaturePolicy.Allow",
- feature);
+ // Otherwise, parse the origin string and verify that the result is
+ // valid. Invalid strings will produce an opaque origin, which will
+ // result in an error message.
+ else {
+ scoped_refptr<SecurityOrigin> parsed_origin =
+ SecurityOrigin::CreateFromString(origin_string);
+ if (!parsed_origin->IsOpaque()) {
+ target_origin = parsed_origin->ToUrlOrigin();
+ allowlist_includes_origin_ = true;
+ } else {
+ Log("Unrecognized origin: '" + origin_string + "'.");
+ continue;
}
- } else {
- UMA_HISTOGRAM_ENUMERATION("Blink.UseCounter.FeaturePolicy.Header",
- feature);
}
- // True if we should try to detect what kind of allowlist is being used.
- bool count_allowlist_type = true;
-
- // Flags for the types of items which can be used in allowlists.
- bool allowlist_includes_star = false;
- bool allowlist_includes_self = false;
- bool allowlist_includes_src = false;
- bool allowlist_includes_none = false;
- bool allowlist_includes_origin = false;
-
- ParsedFeaturePolicyDeclaration allowlist(feature, feature_type);
- // TODO(loonybear): fallback value should be parsed from the new syntax.
- allowlist.fallback_value = GetFallbackValueForFeature(feature);
- allowlist.opaque_value = GetFallbackValueForFeature(feature);
- features_specified.set(static_cast<size_t>(feature));
- std::map<url::Origin, PolicyValue> values;
- PolicyValue value = PolicyValue::CreateMaxPolicyValue(feature_type);
- // If a policy entry has no listed origins (e.g. "feature_name1" in
- // allow="feature_name1; feature_name2 value"), enable the feature for:
- // a. |self_origin|, if we are parsing a header policy (i.e.,
- // |src_origin| is null);
- // b. |src_origin|, if we are parsing an allow attribute (i.e.,
- // |src_origin| is not null), |src_origin| is not opaque; or
- // c. the opaque origin of the frame, if |src_origin| is opaque.
- if (tokens.size() == 1) {
- if (!src_origin) {
- values[self_origin->ToUrlOrigin()] = value;
- } else if (!src_origin->IsOpaque()) {
- values[src_origin->ToUrlOrigin()] = value;
- } else {
- allowlist.opaque_value = value;
- }
+ if (target_is_all) {
+ allowlist.fallback_value = true;
+ allowlist.opaque_value = true;
+ } else if (target_is_opaque) {
+ allowlist.opaque_value = true;
+ } else {
+ allowlist.allowed_origins.push_back(target_origin);
}
+ }
+ }
- for (wtf_size_t i = 1; i < tokens.size(); i++) {
- if (!tokens[i].ContainsOnlyASCIIOrEmpty()) {
- messages->push_back("Non-ASCII characters in origin.");
- continue;
- }
+ // Size reduction: remove all items in the allowlist if target is all.
+ if (allowlist.fallback_value)
+ allowlist.allowed_origins.clear();
- // Break the token into an origin and a value. Either one may be
- // omitted.
- PolicyValue value = PolicyValue::CreateMaxPolicyValue(feature_type);
- String origin_string = tokens[i];
- String value_string;
- wtf_size_t param_start = origin_string.find('(');
- if (param_start != kNotFound) {
- // There is a value attached to this origin
- if (!origin_string.EndsWith(')')) {
- // The declaration is malformed if the value is not the last part of
- // the string.
- if (messages)
- messages->push_back("Unable to parse policy value.");
- continue;
- }
- value_string = origin_string.Substring(
- param_start + 1, origin_string.length() - param_start - 2);
- origin_string = origin_string.Substring(0, param_start);
- bool ok = false;
- value = ParseValueForType(feature_type, value_string, &ok);
- if (!ok) {
- if (messages)
- messages->push_back("Unable to parse policy value.");
- continue;
- }
- }
+ // Sort |allowed_origins| in alphabetical order.
+ std::sort(allowlist.allowed_origins.begin(), allowlist.allowed_origins.end());
- // Determine the target of the declaration. This may be a specific
- // origin, either explicitly written, or one of the special keywords
- // 'self' or 'src'. ('src' can only be used in the iframe allow
- // attribute.)
- url::Origin target_origin;
-
- // If the iframe will have an opaque origin (for example, if it is
- // sandboxed, or has a data: URL), then 'src' needs to refer to the
- // opaque origin of the frame, which is not known yet. In this case,
- // the |opaque_value| on the declaration is set, rather than adding
- // an origin to the allowlist.
- bool target_is_opaque = false;
- bool target_is_all = false;
-
- // 'self' origin is used if either the origin is omitted (and there is
- // no 'src' origin available) or the origin is exactly 'self'.
- if ((origin_string.length() == 0 && !src_origin)) {
- target_origin = self_origin->ToUrlOrigin();
- } else if (EqualIgnoringASCIICase(origin_string, "'self'")) {
- target_origin = self_origin->ToUrlOrigin();
- allowlist_includes_self = true;
- }
- // 'src' origin is used if |src_origin| is available and either the
- // origin is omitted or is a match for 'src'. |src_origin| is only set
- // when parsing an iframe allow attribute.
- else if (src_origin &&
- (origin_string.length() == 0 ||
- EqualIgnoringASCIICase(origin_string, "'src'"))) {
- if (origin_string.length() > 0)
- allowlist_includes_src = true;
- if (!src_origin->IsOpaque()) {
- target_origin = src_origin->ToUrlOrigin();
- } else {
- target_is_opaque = true;
- }
- } else if (EqualIgnoringASCIICase(origin_string, "'none'")) {
- allowlist_includes_none = true;
- continue;
- } else if (origin_string == "*") {
- target_is_all = true;
- allowlist_includes_star = true;
- }
- // Otherwise, parse the origin string and verify that the result is
- // valid. Invalid strings will produce an opaque origin, which will
- // result in an error message.
- else {
- scoped_refptr<SecurityOrigin> parsed_origin =
- SecurityOrigin::CreateFromString(origin_string);
- if (!parsed_origin->IsOpaque()) {
- target_origin = parsed_origin->ToUrlOrigin();
- allowlist_includes_origin = true;
- } else if (messages) {
- messages->push_back("Unrecognized origin: '" + origin_string +
- "'.");
- continue;
- }
- }
+ RecordAllowlistTypeUsage(origin_strings.size());
- // Assign the value to the target origin(s).
- if (target_is_all) {
- allowlist.fallback_value = value;
- allowlist.opaque_value = value;
- } else if (target_is_opaque) {
- allowlist.opaque_value = value;
- } else {
- values[target_origin] = value;
- }
- }
+ return allowlist;
+}
- if (count_allowlist_type) {
- // Record the type of allowlist used.
- if (tokens.size() == 1) {
- allowlist_types_used.insert(FeaturePolicyAllowlistType::kEmpty);
- } else if (tokens.size() == 2) {
- if (allowlist_includes_star)
- allowlist_types_used.insert(FeaturePolicyAllowlistType::kStar);
- else if (allowlist_includes_self)
- allowlist_types_used.insert(FeaturePolicyAllowlistType::kSelf);
- else if (allowlist_includes_src)
- allowlist_types_used.insert(FeaturePolicyAllowlistType::kSrc);
- else if (allowlist_includes_none)
- allowlist_types_used.insert(FeaturePolicyAllowlistType::kNone);
- else
- allowlist_types_used.insert(FeaturePolicyAllowlistType::kOrigins);
- } else {
- if (allowlist_includes_origin) {
- if (allowlist_includes_star || allowlist_includes_none ||
- allowlist_includes_src || allowlist_includes_self)
- allowlist_types_used.insert(FeaturePolicyAllowlistType::kMixed);
- else
- allowlist_types_used.insert(FeaturePolicyAllowlistType::kOrigins);
- } else {
- allowlist_types_used.insert(
- FeaturePolicyAllowlistType::kKeywordsOnly);
- }
- }
- }
+base::Optional<ParsedFeaturePolicyDeclaration> ParsingContext::ParseFeature(
+ const String& input) {
+ // Split removes extra whitespaces by default
+ Vector<String> tokens;
+ input.Split(' ', tokens);
- // Size reduction: remove all items in the allowlist whose value is the
- // same as the fallback.
- for (auto it = values.begin(); it != values.end();) {
- if (it->second == allowlist.fallback_value)
- it = values.erase(it);
- else
- it++;
- }
+ // Empty policy. Skip.
+ if (tokens.IsEmpty())
+ return base::nullopt;
- allowlist.values = std::move(values);
- allowlists.push_back(allowlist);
- }
+ // Break tokens into head & tail, where
+ // head = feature_name
+ // tail = origins
+ // After feature_name has been parsed, take tail of tokens vector by
+ // erasing the first element.
+ base::Optional<mojom::blink::FeaturePolicyFeature> feature =
+ ParseFeatureName(/* feature_name */ tokens.front());
+
+ tokens.erase(tokens.begin());
+
+ ParsedAllowlist parsed_allowlist =
+ ParseAllowlist(/* origin_strings */ tokens);
+
+ if (!feature)
+ return base::nullopt;
+
+ // If same feature appeared more than once, only the first one counts.
+ if (FeatureObserved(*feature))
+ return base::nullopt;
+
+ ParsedFeaturePolicyDeclaration parsed_feature(*feature);
+ parsed_feature.allowed_origins = std::move(parsed_allowlist.allowed_origins);
+ parsed_feature.fallback_value = parsed_allowlist.fallback_value;
+ parsed_feature.opaque_value = parsed_allowlist.opaque_value;
+
+ return parsed_feature;
+}
+
+ParsedFeaturePolicy ParsingContext::Parse(const String& policy) {
+ ParsedFeaturePolicy parsed_policy;
+
+ if (policy.length() > MAX_LENGTH_PARSE) {
+ Log("Feature policy declaration exceeds size limit(" +
+ String::Number(policy.length()) + ">" +
+ String::Number(MAX_LENGTH_PARSE) + ")");
+ return parsed_policy;
}
- // The use of various allowlist types should only be recorded once per page.
- // For simplicity, this recording assumes that the ParseHeader method is
- // called once when creating a new document, and similarly the ParseAttribute
- // method is called once for a frame. It is possible for multiple calls, but
- // the additional complexity to guarantee only one record isn't warranted as
- // yet.
- for (const FeaturePolicyAllowlistType allowlist_type : allowlist_types_used) {
- if (src_origin) {
- UMA_HISTOGRAM_ENUMERATION(
- "Blink.UseCounter.FeaturePolicy.AttributeAllowlistType",
- allowlist_type);
- } else {
- UMA_HISTOGRAM_ENUMERATION(
- "Blink.UseCounter.FeaturePolicy.HeaderAllowlistType", allowlist_type);
- }
+ // RFC2616, section 4.2 specifies that headers appearing multiple times can be
+ // combined with a comma. Walk the header string, and parse each comma
+ // separated chunk as a separate header.
+ Vector<String> policy_items;
+ // policy_items = [ policy *( "," [ policy ] ) ]
+ policy.Split(',', policy_items);
+
+ if (policy_items.size() > 1) {
+ ReportFeaturePolicyWebFeatureUsage(
+ mojom::blink::WebFeature::kFeaturePolicyCommaSeparatedDeclarations);
}
- return allowlists;
-}
-// TODO(loonybear): once the new syntax is implemented, use this method to
-// parse the policy value for each parameterized feature, and for non
-// parameterized feature (i.e. boolean-type policy value).
-PolicyValue FeaturePolicyParser::GetFallbackValueForFeature(
- mojom::blink::FeaturePolicyFeature feature) {
- return PolicyValue(false);
-}
+ for (const String& item : policy_items) {
+ Vector<String> feature_entries;
+ // feature_entries = [ feature_entry *( ";" [ feature_entry ] ) ]
+ item.Split(';', feature_entries);
+
+ if (feature_entries.size() > 1) {
+ ReportFeaturePolicyWebFeatureUsage(
+ mojom::blink::WebFeature::
+ kFeaturePolicySemicolonSeparatedDeclarations);
+ }
-PolicyValue FeaturePolicyParser::ParseValueForType(
- mojom::PolicyValueType feature_type,
- const String& value_string,
- bool* ok) {
- *ok = false;
- PolicyValue value;
- switch (feature_type) {
- case mojom::PolicyValueType::kBool:
- // recognize true, false
- if (value_string.LowerASCII() == "true") {
- value = PolicyValue(true);
- *ok = true;
- } else if (value_string.LowerASCII() == "false") {
- value = PolicyValue(false);
- *ok = true;
+ for (const String& feature_entry : feature_entries) {
+ base::Optional<ParsedFeaturePolicyDeclaration> parsed_feature =
+ ParseFeature(feature_entry);
+ if (parsed_feature) {
+ ReportFeatureUsage(parsed_feature->feature);
+ parsed_policy.push_back(*parsed_feature);
}
- break;
- case mojom::PolicyValueType::kDecDouble: {
- if (value_string.LowerASCII() == "inf") {
- value = PolicyValue::CreateMaxPolicyValue(feature_type);
- *ok = true;
- } else {
- double parsed_value = value_string.ToDouble(ok);
- if (*ok && parsed_value >= 0.0f) {
- value = PolicyValue(parsed_value);
- } else {
- *ok = false;
- }
- }
- break;
}
- default:
- NOTREACHED();
}
- if (!*ok)
- return PolicyValue();
- return value;
+
+ ReportAllowlistTypeUsage();
+
+ return parsed_policy;
+}
+
+} // namespace
+
+ParsedFeaturePolicy FeaturePolicyParser::ParseHeader(
+ const String& policy,
+ scoped_refptr<const SecurityOrigin> origin,
+ Vector<String>* messages,
+ FeaturePolicyParserDelegate* delegate) {
+ return Parse(policy, origin, nullptr, messages, GetDefaultFeatureNameMap(),
+ delegate);
}
-void FeaturePolicyParser::ParseValueForFuzzer(
- blink::mojom::PolicyValueType feature_type,
- const WTF::String& value_string) {
- bool ok;
- ParseValueForType(feature_type, value_string, &ok);
+ParsedFeaturePolicy FeaturePolicyParser::ParseAttribute(
+ const String& policy,
+ scoped_refptr<const SecurityOrigin> self_origin,
+ scoped_refptr<const SecurityOrigin> src_origin,
+ Vector<String>* messages,
+ Document* document) {
+ return Parse(policy, self_origin, src_origin, messages,
+ GetDefaultFeatureNameMap(), document);
+}
+
+// static
+ParsedFeaturePolicy FeaturePolicyParser::Parse(
+ const String& policy,
+ scoped_refptr<const SecurityOrigin> self_origin,
+ scoped_refptr<const SecurityOrigin> src_origin,
+ Vector<String>* messages,
+ const FeatureNameMap& feature_names,
+ FeaturePolicyParserDelegate* delegate) {
+ return ParsingContext(messages, self_origin, src_origin, feature_names,
+ delegate)
+ .Parse(policy);
}
bool IsFeatureDeclared(mojom::blink::FeaturePolicyFeature feature,
@@ -411,9 +446,7 @@ bool DisallowFeatureIfNotPresent(mojom::blink::FeaturePolicyFeature feature,
ParsedFeaturePolicy& policy) {
if (IsFeatureDeclared(feature, policy))
return false;
- blink::mojom::PolicyValueType feature_type =
- blink::FeaturePolicy::GetDefaultFeatureList().at(feature).second;
- ParsedFeaturePolicyDeclaration allowlist(feature, feature_type);
+ ParsedFeaturePolicyDeclaration allowlist(feature);
policy.push_back(allowlist);
return true;
}
@@ -423,11 +456,9 @@ bool AllowFeatureEverywhereIfNotPresent(
ParsedFeaturePolicy& policy) {
if (IsFeatureDeclared(feature, policy))
return false;
- blink::mojom::PolicyValueType feature_type =
- blink::FeaturePolicy::GetDefaultFeatureList().at(feature).second;
- ParsedFeaturePolicyDeclaration allowlist(feature, feature_type);
- allowlist.fallback_value.SetToMax();
- allowlist.opaque_value.SetToMax();
+ ParsedFeaturePolicyDeclaration allowlist(feature);
+ allowlist.fallback_value = true;
+ allowlist.opaque_value = true;
policy.push_back(allowlist);
return true;
}
diff --git a/chromium/third_party/blink/renderer/core/feature_policy/feature_policy_parser.h b/chromium/third_party/blink/renderer/core/feature_policy/feature_policy_parser.h
index 371b1fc3e31..18b37104b47 100644
--- a/chromium/third_party/blink/renderer/core/feature_policy/feature_policy_parser.h
+++ b/chromium/third_party/blink/renderer/core/feature_policy/feature_policy_parser.h
@@ -10,7 +10,7 @@
#include "base/memory/scoped_refptr.h"
#include "third_party/blink/public/common/feature_policy/feature_policy.h"
#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/core/feature_policy/feature_policy_helper.h"
+#include "third_party/blink/renderer/core/feature_policy/policy_helper.h"
#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
#include "third_party/blink/renderer/platform/wtf/text/string_hash.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
@@ -92,16 +92,6 @@ class CORE_EXPORT FeaturePolicyParser {
Vector<String>* messages,
const FeatureNameMap& feature_names,
FeaturePolicyParserDelegate* delegate = nullptr);
-
- // Used for LLVM fuzzer test
- static void ParseValueForFuzzer(mojom::PolicyValueType, const String&);
-
- private:
- static PolicyValue GetFallbackValueForFeature(
- mojom::blink::FeaturePolicyFeature feature);
- static PolicyValue ParseValueForType(mojom::PolicyValueType feature_type,
- const String& value_string,
- bool* ok);
};
// Returns true iff any declaration in the policy is for the given feature.
CORE_EXPORT bool IsFeatureDeclared(mojom::blink::FeaturePolicyFeature,
diff --git a/chromium/third_party/blink/renderer/core/feature_policy/feature_policy_test.cc b/chromium/third_party/blink/renderer/core/feature_policy/feature_policy_test.cc
index 1abaea5b1e9..341e364e72b 100644
--- a/chromium/third_party/blink/renderer/core/feature_policy/feature_policy_test.cc
+++ b/chromium/third_party/blink/renderer/core/feature_policy/feature_policy_test.cc
@@ -50,10 +50,6 @@ const char* const kValidPolicies[] = {
"geolocation 'none' 'none' 'none'",
"geolocation " ORIGIN_A " *",
"fullscreen " ORIGIN_A "; payment 'self'",
- "fullscreen " ORIGIN_A "(true)",
- "fullscreen " ORIGIN_A "(false)",
- "fullscreen " ORIGIN_A "(True)",
- "fullscreen " ORIGIN_A "(TRUE)",
"fullscreen " ORIGIN_A "; payment *, geolocation 'self'"};
const char* const kInvalidPolicies[] = {
@@ -66,10 +62,7 @@ const char* const kInvalidPolicies[] = {
"geolocation https://example.com, https://a.com",
"geolocation *, payment data://badorigin",
"geolocation ws://xn--fd\xbcwsw3taaaaaBaa333aBBBBBBJBBJBBBt",
- "fullscreen(true)",
- "fullscreen " ORIGIN_A "(notabool)",
- "fullscreen " ORIGIN_A "(2.0)",
- "fullscreen " ORIGIN_A "()"};
+};
// Names of UMA histograms
const char kAllowlistAttributeHistogram[] =
@@ -100,17 +93,6 @@ class FeaturePolicyParserTest : public testing::Test {
{"fullscreen", blink::mojom::blink::FeaturePolicyFeature::kFullscreen},
{"payment", blink::mojom::blink::FeaturePolicyFeature::kPayment},
{"geolocation", blink::mojom::blink::FeaturePolicyFeature::kGeolocation}};
-
- const PolicyValue min_value = PolicyValue(false);
- const PolicyValue max_value = PolicyValue(true);
- const PolicyValue sample_double_value =
- PolicyValue(1.5, mojom::PolicyValueType::kDecDouble);
- const PolicyValue default_double_value =
- PolicyValue(2.0, mojom::PolicyValueType::kDecDouble);
- const PolicyValue min_double_value =
- PolicyValue::CreateMinPolicyValue(mojom::PolicyValueType::kDecDouble);
- const PolicyValue max_double_value =
- PolicyValue::CreateMaxPolicyValue(mojom::PolicyValueType::kDecDouble);
};
TEST_F(FeaturePolicyParserTest, ParseValidPolicy) {
@@ -158,10 +140,10 @@ TEST_F(FeaturePolicyParserTest, PolicyParsedCorrectly) {
EXPECT_EQ(mojom::blink::FeaturePolicyFeature::kGeolocation,
parsed_policy[0].feature);
- EXPECT_GE(min_value, parsed_policy[0].fallback_value);
- EXPECT_GE(min_value, parsed_policy[0].opaque_value);
- EXPECT_EQ(1UL, parsed_policy[0].values.size());
- EXPECT_TRUE(parsed_policy[0].values.begin()->first.IsSameOriginWith(
+ EXPECT_FALSE(parsed_policy[0].fallback_value);
+ EXPECT_FALSE(parsed_policy[0].opaque_value);
+ EXPECT_EQ(1UL, parsed_policy[0].allowed_origins.size());
+ EXPECT_TRUE(parsed_policy[0].allowed_origins.begin()->IsSameOriginWith(
expected_url_origin_a_));
// Simple policy with *.
@@ -171,9 +153,9 @@ TEST_F(FeaturePolicyParserTest, PolicyParsedCorrectly) {
EXPECT_EQ(1UL, parsed_policy.size());
EXPECT_EQ(mojom::blink::FeaturePolicyFeature::kGeolocation,
parsed_policy[0].feature);
- EXPECT_LE(max_value, parsed_policy[0].fallback_value);
- EXPECT_LE(max_value, parsed_policy[0].opaque_value);
- EXPECT_EQ(0UL, parsed_policy[0].values.size());
+ EXPECT_TRUE(parsed_policy[0].fallback_value);
+ EXPECT_TRUE(parsed_policy[0].opaque_value);
+ EXPECT_EQ(0UL, parsed_policy[0].allowed_origins.size());
// Complicated policy.
parsed_policy = FeaturePolicyParser::Parse(
@@ -184,23 +166,23 @@ TEST_F(FeaturePolicyParserTest, PolicyParsedCorrectly) {
EXPECT_EQ(3UL, parsed_policy.size());
EXPECT_EQ(mojom::blink::FeaturePolicyFeature::kGeolocation,
parsed_policy[0].feature);
- EXPECT_LE(max_value, parsed_policy[0].fallback_value);
- EXPECT_LE(max_value, parsed_policy[0].opaque_value);
- EXPECT_EQ(0UL, parsed_policy[0].values.size());
+ EXPECT_TRUE(parsed_policy[0].fallback_value);
+ EXPECT_TRUE(parsed_policy[0].opaque_value);
+ EXPECT_EQ(0UL, parsed_policy[0].allowed_origins.size());
EXPECT_EQ(mojom::blink::FeaturePolicyFeature::kFullscreen,
parsed_policy[1].feature);
- EXPECT_GE(min_value, parsed_policy[1].fallback_value);
- EXPECT_GE(min_value, parsed_policy[1].opaque_value);
- EXPECT_EQ(2UL, parsed_policy[1].values.size());
- auto it = parsed_policy[1].values.begin();
- EXPECT_TRUE(it->first.IsSameOriginWith(expected_url_origin_b_));
- EXPECT_TRUE((++it)->first.IsSameOriginWith(expected_url_origin_c_));
+ EXPECT_FALSE(parsed_policy[1].fallback_value);
+ EXPECT_FALSE(parsed_policy[1].opaque_value);
+ EXPECT_EQ(2UL, parsed_policy[1].allowed_origins.size());
+ auto it = parsed_policy[1].allowed_origins.begin();
+ EXPECT_TRUE(it->IsSameOriginWith(expected_url_origin_b_));
+ EXPECT_TRUE((++it)->IsSameOriginWith(expected_url_origin_c_));
EXPECT_EQ(mojom::blink::FeaturePolicyFeature::kPayment,
parsed_policy[2].feature);
- EXPECT_GE(min_value, parsed_policy[2].fallback_value);
- EXPECT_GE(min_value, parsed_policy[2].opaque_value);
- EXPECT_EQ(1UL, parsed_policy[2].values.size());
- EXPECT_TRUE(parsed_policy[2].values.begin()->first.IsSameOriginWith(
+ EXPECT_FALSE(parsed_policy[2].fallback_value);
+ EXPECT_FALSE(parsed_policy[2].opaque_value);
+ EXPECT_EQ(1UL, parsed_policy[2].allowed_origins.size());
+ EXPECT_TRUE(parsed_policy[2].allowed_origins.begin()->IsSameOriginWith(
expected_url_origin_a_));
// Multiple policies.
@@ -212,23 +194,23 @@ TEST_F(FeaturePolicyParserTest, PolicyParsedCorrectly) {
EXPECT_EQ(3UL, parsed_policy.size());
EXPECT_EQ(mojom::blink::FeaturePolicyFeature::kGeolocation,
parsed_policy[0].feature);
- EXPECT_LE(max_value, parsed_policy[0].fallback_value);
- EXPECT_LE(max_value, parsed_policy[0].opaque_value);
- EXPECT_EQ(0UL, parsed_policy[0].values.size());
+ EXPECT_TRUE(parsed_policy[0].fallback_value);
+ EXPECT_TRUE(parsed_policy[0].opaque_value);
+ EXPECT_EQ(0UL, parsed_policy[0].allowed_origins.size());
EXPECT_EQ(mojom::blink::FeaturePolicyFeature::kFullscreen,
parsed_policy[1].feature);
- EXPECT_GE(min_value, parsed_policy[1].fallback_value);
- EXPECT_GE(min_value, parsed_policy[1].opaque_value);
- EXPECT_EQ(2UL, parsed_policy[1].values.size());
- it = parsed_policy[1].values.begin();
- EXPECT_TRUE(it->first.IsSameOriginWith(expected_url_origin_b_));
- EXPECT_TRUE((++it)->first.IsSameOriginWith(expected_url_origin_c_));
+ EXPECT_FALSE(parsed_policy[1].fallback_value);
+ EXPECT_FALSE(parsed_policy[1].opaque_value);
+ EXPECT_EQ(2UL, parsed_policy[1].allowed_origins.size());
+ it = parsed_policy[1].allowed_origins.begin();
+ EXPECT_TRUE(it->IsSameOriginWith(expected_url_origin_b_));
+ EXPECT_TRUE((++it)->IsSameOriginWith(expected_url_origin_c_));
EXPECT_EQ(mojom::blink::FeaturePolicyFeature::kPayment,
parsed_policy[2].feature);
- EXPECT_GE(min_value, parsed_policy[2].fallback_value);
- EXPECT_GE(min_value, parsed_policy[2].opaque_value);
- EXPECT_EQ(1UL, parsed_policy[2].values.size());
- EXPECT_TRUE(parsed_policy[2].values.begin()->first.IsSameOriginWith(
+ EXPECT_FALSE(parsed_policy[2].fallback_value);
+ EXPECT_FALSE(parsed_policy[2].opaque_value);
+ EXPECT_EQ(1UL, parsed_policy[2].allowed_origins.size());
+ EXPECT_TRUE(parsed_policy[2].allowed_origins.begin()->IsSameOriginWith(
expected_url_origin_a_));
// Header policies with no optional origin lists.
@@ -238,23 +220,23 @@ TEST_F(FeaturePolicyParserTest, PolicyParsedCorrectly) {
EXPECT_EQ(3UL, parsed_policy.size());
EXPECT_EQ(mojom::blink::FeaturePolicyFeature::kGeolocation,
parsed_policy[0].feature);
- EXPECT_GE(min_value, parsed_policy[0].fallback_value);
- EXPECT_GE(min_value, parsed_policy[0].opaque_value);
- EXPECT_EQ(1UL, parsed_policy[0].values.size());
- EXPECT_TRUE(parsed_policy[0].values.begin()->first.IsSameOriginWith(
+ EXPECT_FALSE(parsed_policy[0].fallback_value);
+ EXPECT_FALSE(parsed_policy[0].opaque_value);
+ EXPECT_EQ(1UL, parsed_policy[0].allowed_origins.size());
+ EXPECT_TRUE(parsed_policy[0].allowed_origins.begin()->IsSameOriginWith(
expected_url_origin_a_));
EXPECT_EQ(mojom::blink::FeaturePolicyFeature::kFullscreen,
parsed_policy[1].feature);
- EXPECT_GE(min_value, parsed_policy[1].fallback_value);
- EXPECT_GE(min_value, parsed_policy[1].opaque_value);
- EXPECT_EQ(1UL, parsed_policy[1].values.size());
- EXPECT_TRUE(parsed_policy[1].values.begin()->first.IsSameOriginWith(
+ EXPECT_FALSE(parsed_policy[1].fallback_value);
+ EXPECT_FALSE(parsed_policy[1].opaque_value);
+ EXPECT_EQ(1UL, parsed_policy[1].allowed_origins.size());
+ EXPECT_TRUE(parsed_policy[1].allowed_origins.begin()->IsSameOriginWith(
expected_url_origin_a_));
EXPECT_EQ(mojom::blink::FeaturePolicyFeature::kPayment,
parsed_policy[2].feature);
- EXPECT_GE(min_value, parsed_policy[2].opaque_value);
- EXPECT_EQ(1UL, parsed_policy[2].values.size());
- EXPECT_TRUE(parsed_policy[2].values.begin()->first.IsSameOriginWith(
+ EXPECT_FALSE(parsed_policy[2].opaque_value);
+ EXPECT_EQ(1UL, parsed_policy[2].allowed_origins.size());
+ EXPECT_TRUE(parsed_policy[2].allowed_origins.begin()->IsSameOriginWith(
expected_url_origin_a_));
}
@@ -278,9 +260,9 @@ TEST_F(FeaturePolicyParserTest, PolicyParsedCorrectlyForOpaqueOrigins) {
EXPECT_EQ(mojom::blink::FeaturePolicyFeature::kGeolocation,
parsed_policy[0].feature);
- EXPECT_GE(min_value, parsed_policy[0].fallback_value);
- EXPECT_LE(max_value, parsed_policy[0].opaque_value);
- EXPECT_EQ(0UL, parsed_policy[0].values.size());
+ EXPECT_FALSE(parsed_policy[0].fallback_value);
+ EXPECT_TRUE(parsed_policy[0].opaque_value);
+ EXPECT_EQ(0UL, parsed_policy[0].allowed_origins.size());
// Simple policy with 'src'.
parsed_policy = FeaturePolicyParser::Parse(
@@ -290,9 +272,9 @@ TEST_F(FeaturePolicyParserTest, PolicyParsedCorrectlyForOpaqueOrigins) {
EXPECT_EQ(mojom::blink::FeaturePolicyFeature::kGeolocation,
parsed_policy[0].feature);
- EXPECT_GE(min_value, parsed_policy[0].fallback_value);
- EXPECT_LE(max_value, parsed_policy[0].opaque_value);
- EXPECT_EQ(0UL, parsed_policy[0].values.size());
+ EXPECT_FALSE(parsed_policy[0].fallback_value);
+ EXPECT_TRUE(parsed_policy[0].opaque_value);
+ EXPECT_EQ(0UL, parsed_policy[0].allowed_origins.size());
// Simple policy with *.
parsed_policy = FeaturePolicyParser::Parse("geolocation *", origin_a_.get(),
@@ -302,9 +284,9 @@ TEST_F(FeaturePolicyParserTest, PolicyParsedCorrectlyForOpaqueOrigins) {
EXPECT_EQ(mojom::blink::FeaturePolicyFeature::kGeolocation,
parsed_policy[0].feature);
- EXPECT_LE(max_value, parsed_policy[0].fallback_value);
- EXPECT_LE(max_value, parsed_policy[0].opaque_value);
- EXPECT_EQ(0UL, parsed_policy[0].values.size());
+ EXPECT_TRUE(parsed_policy[0].fallback_value);
+ EXPECT_TRUE(parsed_policy[0].opaque_value);
+ EXPECT_EQ(0UL, parsed_policy[0].allowed_origins.size());
// Policy with explicit origins
parsed_policy = FeaturePolicyParser::Parse(
@@ -314,12 +296,12 @@ TEST_F(FeaturePolicyParserTest, PolicyParsedCorrectlyForOpaqueOrigins) {
EXPECT_EQ(mojom::blink::FeaturePolicyFeature::kGeolocation,
parsed_policy[0].feature);
- EXPECT_GE(min_value, parsed_policy[0].fallback_value);
- EXPECT_GE(min_value, parsed_policy[0].opaque_value);
- EXPECT_EQ(2UL, parsed_policy[0].values.size());
- auto it = parsed_policy[0].values.begin();
- EXPECT_TRUE(it->first.IsSameOriginWith(expected_url_origin_b_));
- EXPECT_TRUE((++it)->first.IsSameOriginWith(expected_url_origin_c_));
+ EXPECT_FALSE(parsed_policy[0].fallback_value);
+ EXPECT_FALSE(parsed_policy[0].opaque_value);
+ EXPECT_EQ(2UL, parsed_policy[0].allowed_origins.size());
+ auto it = parsed_policy[0].allowed_origins.begin();
+ EXPECT_TRUE(it->IsSameOriginWith(expected_url_origin_b_));
+ EXPECT_TRUE((++it)->IsSameOriginWith(expected_url_origin_c_));
// Policy with multiple origins, including 'src'.
parsed_policy = FeaturePolicyParser::Parse(
@@ -329,141 +311,13 @@ TEST_F(FeaturePolicyParserTest, PolicyParsedCorrectlyForOpaqueOrigins) {
EXPECT_EQ(mojom::blink::FeaturePolicyFeature::kGeolocation,
parsed_policy[0].feature);
- EXPECT_GE(min_value, parsed_policy[0].fallback_value);
- EXPECT_LE(max_value, parsed_policy[0].opaque_value);
- EXPECT_EQ(1UL, parsed_policy[0].values.size());
- EXPECT_TRUE(parsed_policy[0].values.begin()->first.IsSameOriginWith(
+ EXPECT_FALSE(parsed_policy[0].fallback_value);
+ EXPECT_TRUE(parsed_policy[0].opaque_value);
+ EXPECT_EQ(1UL, parsed_policy[0].allowed_origins.size());
+ EXPECT_TRUE(parsed_policy[0].allowed_origins.begin()->IsSameOriginWith(
expected_url_origin_b_));
}
-TEST_F(FeaturePolicyParserTest, BooleanPolicyParametersParsedCorrectly) {
- Vector<String> messages;
- ParsedFeaturePolicy parsed_policy;
-
- // Test no origin specified, in a container policy context.
- // (true)
- parsed_policy = FeaturePolicyParser::Parse("fullscreen (true)",
- origin_a_.get(), origin_b_.get(),
- &messages, test_feature_name_map);
- EXPECT_EQ(1UL, parsed_policy.size());
- EXPECT_EQ(mojom::blink::FeaturePolicyFeature::kFullscreen,
- parsed_policy[0].feature);
- EXPECT_EQ(min_value, parsed_policy[0].fallback_value);
- EXPECT_EQ(min_value, parsed_policy[0].opaque_value);
- EXPECT_EQ(1UL, parsed_policy[0].values.size());
- EXPECT_TRUE(parsed_policy[0].values.begin()->first.IsSameOriginWith(
- expected_url_origin_b_));
- EXPECT_EQ(max_value, parsed_policy[0].values.begin()->second);
-
- // Test no origin specified, in a header context.
- // (true)
- parsed_policy =
- FeaturePolicyParser::Parse("fullscreen (true)", origin_a_.get(), nullptr,
- &messages, test_feature_name_map);
- EXPECT_EQ(1UL, parsed_policy.size());
- EXPECT_EQ(mojom::blink::FeaturePolicyFeature::kFullscreen,
- parsed_policy[0].feature);
- EXPECT_EQ(min_value, parsed_policy[0].fallback_value);
- EXPECT_EQ(min_value, parsed_policy[0].opaque_value);
- EXPECT_EQ(1UL, parsed_policy[0].values.size());
- EXPECT_TRUE(parsed_policy[0].values.begin()->first.IsSameOriginWith(
- expected_url_origin_a_));
- EXPECT_EQ(max_value, parsed_policy[0].values.begin()->second);
-
- // Test no origin specified, in a sandboxed container policy context.
- // (true)
- scoped_refptr<SecurityOrigin> opaque_origin =
- SecurityOrigin::CreateUniqueOpaque();
- parsed_policy = FeaturePolicyParser::Parse("fullscreen (true)",
- origin_a_.get(), opaque_origin,
- &messages, test_feature_name_map);
- EXPECT_EQ(1UL, parsed_policy.size());
- EXPECT_EQ(mojom::blink::FeaturePolicyFeature::kFullscreen,
- parsed_policy[0].feature);
- EXPECT_EQ(min_value, parsed_policy[0].fallback_value);
- EXPECT_EQ(max_value, parsed_policy[0].opaque_value);
- EXPECT_EQ(0UL, parsed_policy[0].values.size());
-
- // 'self'(true)
- parsed_policy = FeaturePolicyParser::Parse("fullscreen 'self'(true)",
- origin_a_.get(), origin_b_.get(),
- &messages, test_feature_name_map);
- EXPECT_EQ(1UL, parsed_policy.size());
-
- EXPECT_EQ(mojom::blink::FeaturePolicyFeature::kFullscreen,
- parsed_policy[0].feature);
- EXPECT_EQ(min_value, parsed_policy[0].fallback_value);
- EXPECT_EQ(min_value, parsed_policy[0].opaque_value);
- EXPECT_EQ(1UL, parsed_policy[0].values.size());
- EXPECT_TRUE(parsed_policy[0].values.begin()->first.IsSameOriginWith(
- expected_url_origin_a_));
- EXPECT_EQ(max_value, parsed_policy[0].values.begin()->second);
-
- // *(false)
- parsed_policy = FeaturePolicyParser::Parse("fullscreen *(false)",
- origin_a_.get(), origin_b_.get(),
- &messages, test_feature_name_map);
- EXPECT_EQ(1UL, parsed_policy.size());
-
- EXPECT_EQ(mojom::blink::FeaturePolicyFeature::kFullscreen,
- parsed_policy[0].feature);
- EXPECT_EQ(min_value, parsed_policy[0].fallback_value);
- EXPECT_EQ(min_value, parsed_policy[0].opaque_value);
- EXPECT_EQ(0UL, parsed_policy[0].values.size());
-
- // *(true)
- parsed_policy = FeaturePolicyParser::Parse("fullscreen *(true)",
- origin_a_.get(), origin_b_.get(),
- &messages, test_feature_name_map);
- EXPECT_EQ(1UL, parsed_policy.size());
-
- EXPECT_EQ(mojom::blink::FeaturePolicyFeature::kFullscreen,
- parsed_policy[0].feature);
- EXPECT_EQ(max_value, parsed_policy[0].fallback_value);
- EXPECT_EQ(max_value, parsed_policy[0].opaque_value);
- EXPECT_EQ(0UL, parsed_policy[0].values.size());
-}
-
-TEST_F(FeaturePolicyParserTest, RedundantBooleanItemsRemoved) {
- Vector<String> messages;
- ParsedFeaturePolicy parsed_policy;
-
- // 'self'(true) *(true)
- parsed_policy = FeaturePolicyParser::Parse("fullscreen 'self'(true) *(true)",
- origin_a_.get(), origin_b_.get(),
- &messages, test_feature_name_map);
- EXPECT_EQ(1UL, parsed_policy.size());
-
- EXPECT_EQ(mojom::blink::FeaturePolicyFeature::kFullscreen,
- parsed_policy[0].feature);
- EXPECT_EQ(max_value, parsed_policy[0].fallback_value);
- EXPECT_EQ(max_value, parsed_policy[0].opaque_value);
- EXPECT_EQ(0UL, parsed_policy[0].values.size());
-
- // 'self'(false)
- parsed_policy = FeaturePolicyParser::Parse("fullscreen 'self'(false)",
- origin_a_.get(), origin_b_.get(),
- &messages, test_feature_name_map);
- EXPECT_EQ(1UL, parsed_policy.size());
-
- EXPECT_EQ(mojom::blink::FeaturePolicyFeature::kFullscreen,
- parsed_policy[0].feature);
- EXPECT_EQ(min_value, parsed_policy[0].fallback_value);
- EXPECT_EQ(min_value, parsed_policy[0].opaque_value);
- EXPECT_EQ(0UL, parsed_policy[0].values.size());
-
- // (true)
- parsed_policy = FeaturePolicyParser::Parse("fullscreen (false)",
- origin_a_.get(), origin_b_.get(),
- &messages, test_feature_name_map);
- EXPECT_EQ(1UL, parsed_policy.size());
- EXPECT_EQ(mojom::blink::FeaturePolicyFeature::kFullscreen,
- parsed_policy[0].feature);
- EXPECT_EQ(min_value, parsed_policy[0].fallback_value);
- EXPECT_EQ(min_value, parsed_policy[0].opaque_value);
- EXPECT_EQ(0UL, parsed_policy[0].values.size());
-}
-
// Test histogram counting the use of feature policies in header.
TEST_F(FeaturePolicyParserTest, HeaderHistogram) {
const char* histogram_name = "Blink.UseCounter.FeaturePolicy.Header";
@@ -822,8 +676,8 @@ class FeaturePolicyMutationTest : public testing::Test {
if (result == policy.end())
return false;
- return result->feature == feature && result->fallback_value >= max_value &&
- result->opaque_value >= max_value && result->values.empty();
+ return result->feature == feature && result->fallback_value &&
+ result->opaque_value && result->allowed_origins.empty();
}
// Returns true if the policy contains a declaration for the feature which
@@ -837,25 +691,15 @@ class FeaturePolicyMutationTest : public testing::Test {
if (result == policy.end())
return false;
- return result->feature == feature && result->fallback_value <= min_value &&
- result->opaque_value <= min_value && result->values.empty();
+ return result->feature == feature && !result->fallback_value &&
+ !result->opaque_value && result->allowed_origins.empty();
}
- const PolicyValue min_value = PolicyValue(false);
- const PolicyValue max_value = PolicyValue(true);
- const PolicyValue min_double_value =
- PolicyValue(2.0, mojom::PolicyValueType::kDecDouble);
- const PolicyValue max_double_value =
- PolicyValue::CreateMaxPolicyValue(mojom::PolicyValueType::kDecDouble);
-
ParsedFeaturePolicy test_policy = {
{mojom::blink::FeaturePolicyFeature::kFullscreen,
- std::map<url::Origin, PolicyValue>{{url_origin_a_, PolicyValue(true)},
- {url_origin_b_, PolicyValue(true)}},
- PolicyValue(false), PolicyValue(false)},
+ /* allowed_origins */ {url_origin_a_, url_origin_b_}, false, false},
{mojom::blink::FeaturePolicyFeature::kGeolocation,
- std::map<url::Origin, PolicyValue>{{url_origin_a_, PolicyValue(true)}},
- PolicyValue(false), PolicyValue(false)}};
+ /* allowed_origins */ {url_origin_a_}, false, false}};
ParsedFeaturePolicy empty_policy = {};
};
diff --git a/chromium/third_party/blink/renderer/core/feature_policy/feature_policy_value.dict b/chromium/third_party/blink/renderer/core/feature_policy/feature_policy_value.dict
deleted file mode 100644
index 569ac1c5bbb..00000000000
--- a/chromium/third_party/blink/renderer/core/feature_policy/feature_policy_value.dict
+++ /dev/null
@@ -1,10 +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.
-
-"true"
-"false"
-"inf"
-"0"
-"1"
-".0"
diff --git a/chromium/third_party/blink/renderer/core/feature_policy/feature_policy_value_corpus/1 b/chromium/third_party/blink/renderer/core/feature_policy/feature_policy_value_corpus/1
deleted file mode 100644
index d3827e75a5c..00000000000
--- a/chromium/third_party/blink/renderer/core/feature_policy/feature_policy_value_corpus/1
+++ /dev/null
@@ -1 +0,0 @@
-1.0
diff --git a/chromium/third_party/blink/renderer/core/feature_policy/feature_policy_value_corpus/2 b/chromium/third_party/blink/renderer/core/feature_policy/feature_policy_value_corpus/2
deleted file mode 100644
index 27ba77ddaf6..00000000000
--- a/chromium/third_party/blink/renderer/core/feature_policy/feature_policy_value_corpus/2
+++ /dev/null
@@ -1 +0,0 @@
-true
diff --git a/chromium/third_party/blink/renderer/core/feature_policy/feature_policy_value_corpus/3 b/chromium/third_party/blink/renderer/core/feature_policy/feature_policy_value_corpus/3
deleted file mode 100644
index c508d5366f7..00000000000
--- a/chromium/third_party/blink/renderer/core/feature_policy/feature_policy_value_corpus/3
+++ /dev/null
@@ -1 +0,0 @@
-false
diff --git a/chromium/third_party/blink/renderer/core/feature_policy/feature_policy_value_corpus/4 b/chromium/third_party/blink/renderer/core/feature_policy/feature_policy_value_corpus/4
deleted file mode 100644
index 730c31b9d9b..00000000000
--- a/chromium/third_party/blink/renderer/core/feature_policy/feature_policy_value_corpus/4
+++ /dev/null
@@ -1 +0,0 @@
-0.000001
diff --git a/chromium/third_party/blink/renderer/core/feature_policy/feature_policy_value_corpus/5 b/chromium/third_party/blink/renderer/core/feature_policy/feature_policy_value_corpus/5
deleted file mode 100644
index 8484d062f57..00000000000
--- a/chromium/third_party/blink/renderer/core/feature_policy/feature_policy_value_corpus/5
+++ /dev/null
@@ -1 +0,0 @@
-inf
diff --git a/chromium/third_party/blink/renderer/core/feature_policy/feature_policy_value_corpus/6 b/chromium/third_party/blink/renderer/core/feature_policy/feature_policy_value_corpus/6
deleted file mode 100644
index b8626c4cff2..00000000000
--- a/chromium/third_party/blink/renderer/core/feature_policy/feature_policy_value_corpus/6
+++ /dev/null
@@ -1 +0,0 @@
-4
diff --git a/chromium/third_party/blink/renderer/core/feature_policy/feature_policy_value_fuzzer.cc b/chromium/third_party/blink/renderer/core/feature_policy/feature_policy_value_fuzzer.cc
deleted file mode 100644
index dbb180443b5..00000000000
--- a/chromium/third_party/blink/renderer/core/feature_policy/feature_policy_value_fuzzer.cc
+++ /dev/null
@@ -1,25 +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/core/feature_policy/feature_policy_parser.h"
-
-#include <stddef.h>
-#include <stdint.h>
-#include <memory>
-#include "third_party/blink/public/mojom/feature_policy/feature_policy.mojom-blink.h"
-#include "third_party/blink/renderer/platform/heap/handle.h"
-#include "third_party/blink/renderer/platform/testing/blink_fuzzer_test_support.h"
-#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
-#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
-#include "third_party/blink/renderer/platform/wtf/vector.h"
-
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
- static blink::BlinkFuzzerTestSupport test_support =
- blink::BlinkFuzzerTestSupport();
- blink::FeaturePolicyParser::ParseValueForFuzzer(
- blink::mojom::PolicyValueType::kBool, WTF::String(data, size));
- blink::FeaturePolicyParser::ParseValueForFuzzer(
- blink::mojom::PolicyValueType::kDecDouble, WTF::String(data, size));
- return 0;
-}
diff --git a/chromium/third_party/blink/renderer/core/feature_policy/layout_animations_policy.cc b/chromium/third_party/blink/renderer/core/feature_policy/layout_animations_policy.cc
index 3f2fc6a7cc0..72252d6d64e 100644
--- a/chromium/third_party/blink/renderer/core/feature_policy/layout_animations_policy.cc
+++ b/chromium/third_party/blink/renderer/core/feature_policy/layout_animations_policy.cc
@@ -4,22 +4,21 @@
#include "third_party/blink/renderer/core/feature_policy/layout_animations_policy.h"
-#include "third_party/blink/public/mojom/feature_policy/feature_policy.mojom-blink.h"
+#include "third_party/blink/public/common/feature_policy/document_policy_features.h"
#include "third_party/blink/renderer/core/css/properties/css_property.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
-#include "third_party/blink/renderer/core/feature_policy/feature_policy_parser.h"
#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
namespace blink {
namespace {
String GetViolationMessage(const CSSProperty& property) {
return String::Format(
- "Feature policy violation: CSS property '%s' violates feature policy "
+ "Document policy violation: CSS property '%s' violates document policy "
"'%s' which is disabled in this document",
property.GetPropertyNameString().Utf8().c_str(),
- GetNameForFeature(mojom::blink::FeaturePolicyFeature::kLayoutAnimations)
- .Utf8()
- .c_str());
+ GetDocumentPolicyFeatureInfoMap()
+ .at(mojom::blink::DocumentPolicyFeature::kLayoutAnimations)
+ .feature_name.c_str());
}
} // namespace
@@ -41,7 +40,7 @@ void LayoutAnimationsPolicy::ReportViolation(
const ExecutionContext& context) {
DCHECK(AffectedCSSProperties().Contains(&animated_property));
context.IsFeatureEnabled(
- mojom::blink::FeaturePolicyFeature::kLayoutAnimations,
+ mojom::blink::DocumentPolicyFeature::kLayoutAnimations,
ReportOptions::kReportOnFailure, GetViolationMessage(animated_property));
}
diff --git a/chromium/third_party/blink/renderer/core/feature_policy/feature_policy_helper.h b/chromium/third_party/blink/renderer/core/feature_policy/policy_helper.h
index 74dde545b59..c7041b1238a 100644
--- a/chromium/third_party/blink/renderer/core/feature_policy/feature_policy_helper.h
+++ b/chromium/third_party/blink/renderer/core/feature_policy/policy_helper.h
@@ -2,23 +2,69 @@
// 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_CORE_FEATURE_POLICY_FEATURE_POLICY_HELPER_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_FEATURE_POLICY_FEATURE_POLICY_HELPER_H_
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_FEATURE_POLICY_POLICY_HELPER_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_FEATURE_POLICY_POLICY_HELPER_H_
#include "third_party/blink/public/common/feature_policy/feature_policy.h"
+#include "third_party/blink/public/mojom/devtools/console_message.mojom-blink.h"
#include "third_party/blink/public/mojom/feature_policy/document_policy_feature.mojom-blink-forward.h"
#include "third_party/blink/public/mojom/feature_policy/feature_policy.mojom-blink-forward.h"
#include "third_party/blink/public/mojom/feature_policy/feature_policy_feature.mojom-blink-forward.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/linked_hash_set.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+#include "third_party/blink/renderer/platform/wtf/vector.h"
namespace blink {
+class PolicyParserMessageBuffer {
+ public:
+ struct Message {
+ mojom::blink::ConsoleMessageLevel level;
+ String content;
+
+ Message(mojom::blink::ConsoleMessageLevel level, const String& content)
+ : level(level), content(content) {}
+ };
+
+ PolicyParserMessageBuffer() = default;
+ explicit PolicyParserMessageBuffer(const String& prefix,
+ bool discard_message = false)
+ : prefix_(prefix), discard_message_(discard_message) {}
+
+ ~PolicyParserMessageBuffer() = default;
+
+ void Warn(const String& message) {
+ if (!discard_message_) {
+ message_buffer_.emplace_back(mojom::blink::ConsoleMessageLevel::kWarning,
+ prefix_ + message);
+ }
+ }
+
+ void Error(const String& message) {
+ if (!discard_message_) {
+ message_buffer_.emplace_back(mojom::blink::ConsoleMessageLevel::kError,
+ prefix_ + message);
+ }
+ }
+
+ const Vector<Message>& GetMessages() { return message_buffer_; }
+
+ private:
+ String prefix_;
+ Vector<Message> message_buffer_;
+ // If a dummy message buffer is desired, i.e. messages are not needed for
+ // the caller, this flag can be set to true and the message buffer will
+ // discard any incoming messages.
+ bool discard_message_ = false;
+};
using FeatureNameMap = HashMap<String, mojom::blink::FeaturePolicyFeature>;
+
+// TODO(crbug.com/1069021): Use WTF::HashSet as DocumentPolicyFeatureSet
+// container will cause unknown timeout in release build only.
using DocumentPolicyFeatureSet =
- HashSet<mojom::blink::DocumentPolicyFeature,
- IntHash<mojom::blink::DocumentPolicyFeature>>;
+ LinkedHashSet<mojom::blink::DocumentPolicyFeature,
+ IntHash<mojom::blink::DocumentPolicyFeature>>;
class FeatureContext;
@@ -45,4 +91,4 @@ bool DisabledByOriginTrial(mojom::blink::DocumentPolicyFeature,
FeatureContext*);
} // namespace blink
-#endif // THIRD_PARTY_BLINK_RENDERER_CORE_FEATURE_POLICY_FEATURE_POLICY_HELPER_H_
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_FEATURE_POLICY_POLICY_HELPER_H_
diff --git a/chromium/third_party/blink/renderer/core/fetch/BUILD.gn b/chromium/third_party/blink/renderer/core/fetch/BUILD.gn
index c48584c91e3..596433ac5ea 100644
--- a/chromium/third_party/blink/renderer/core/fetch/BUILD.gn
+++ b/chromium/third_party/blink/renderer/core/fetch/BUILD.gn
@@ -40,6 +40,8 @@ blink_core_sources("fetch") {
"request.h",
"response.cc",
"response.h",
+ "trust_token_issuance_authorization.cc",
+ "trust_token_issuance_authorization.h",
"trust_token_to_mojom.cc",
"trust_token_to_mojom.h",
]
diff --git a/chromium/third_party/blink/renderer/core/fetch/DEPS b/chromium/third_party/blink/renderer/core/fetch/DEPS
index 628e2fdb106..82e8abc9aab 100644
--- a/chromium/third_party/blink/renderer/core/fetch/DEPS
+++ b/chromium/third_party/blink/renderer/core/fetch/DEPS
@@ -4,6 +4,7 @@ include_rules = [
"+mojo/public/cpp/system/data_pipe_utils.h",
"+mojo/public/cpp/system/simple_watcher.h",
"+net/base/request_priority.h",
- "+services/network/public/cpp/content_security_policy/content_security_policy.h",
+ "+services/network/public/cpp",
+ "+services/network/public/mojom",
"+url/gurl.h",
]
diff --git a/chromium/third_party/blink/renderer/core/fetch/body.h b/chromium/third_party/blink/renderer/core/fetch/body.h
index f238092dfbf..fa3449c1273 100644
--- a/chromium/third_party/blink/renderer/core/fetch/body.h
+++ b/chromium/third_party/blink/renderer/core/fetch/body.h
@@ -29,12 +29,7 @@ class ScriptState;
// spec only Response has it and Request has a byte stream defined in the
// Encoding spec. The spec should be fixed shortly to be aligned with this
// implementation.
-class CORE_EXPORT Body : public ScriptWrappable,
- public ActiveScriptWrappable<Body>,
- public ExecutionContextClient {
- DEFINE_WRAPPERTYPEINFO();
- USING_GARBAGE_COLLECTED_MIXIN(Body);
-
+class CORE_EXPORT Body : public ExecutionContextClient {
public:
enum class BodyUsed { kUsed, kUnused, kBroken };
enum class BodyLocked { kLocked, kUnlocked, kBroken };
@@ -64,13 +59,7 @@ class CORE_EXPORT Body : public ScriptWrappable,
// exception pending and the caller should return to JavaScript immediately.
BodyLocked IsBodyLocked(ExceptionState&);
- // ScriptWrappable override.
- bool HasPendingActivity() const override;
-
- void Trace(Visitor* visitor) override {
- ScriptWrappable::Trace(visitor);
- ExecutionContextClient::Trace(visitor);
- }
+ bool HasPendingActivity() const;
protected:
// A version of IsBodyUsed() which catches exceptions and returns
diff --git a/chromium/third_party/blink/renderer/core/fetch/fetch_header_list.cc b/chromium/third_party/blink/renderer/core/fetch/fetch_header_list.cc
index 99658116a8f..fff5f517832 100644
--- a/chromium/third_party/blink/renderer/core/fetch/fetch_header_list.cc
+++ b/chromium/third_party/blink/renderer/core/fetch/fetch_header_list.cc
@@ -104,6 +104,23 @@ bool FetchHeaderList::Get(const String& name, String& result) const {
return found;
}
+String FetchHeaderList::GetAsRawString(int status_code,
+ String status_message) const {
+ StringBuilder builder;
+ builder.Append("HTTP/1.1 ");
+ builder.AppendNumber(status_code);
+ builder.Append(" ");
+ builder.Append(status_message);
+ builder.Append("\r\n");
+ for (auto& it : header_list_) {
+ builder.Append(it.first);
+ builder.Append(":");
+ builder.Append(it.second);
+ builder.Append("\r\n");
+ }
+ return builder.ToString();
+}
+
bool FetchHeaderList::Has(const String& name) const {
// https://fetch.spec.whatwg.org/#header-list-contains
// "A header list (|list|) contains a name (|name|) if |list| contains a
diff --git a/chromium/third_party/blink/renderer/core/fetch/fetch_header_list.h b/chromium/third_party/blink/renderer/core/fetch/fetch_header_list.h
index b7bb616e2e8..d1a561786f6 100644
--- a/chromium/third_party/blink/renderer/core/fetch/fetch_header_list.h
+++ b/chromium/third_party/blink/renderer/core/fetch/fetch_header_list.h
@@ -37,6 +37,7 @@ class CORE_EXPORT FetchHeaderList final
size_t size() const;
void Remove(const String&);
bool Get(const String&, String&) const;
+ String GetAsRawString(int status_code, String status_message) const;
bool Has(const String&) const;
void ClearList();
diff --git a/chromium/third_party/blink/renderer/core/fetch/fetch_manager.cc b/chromium/third_party/blink/renderer/core/fetch/fetch_manager.cc
index 5c62a59abe1..7bae19a506f 100644
--- a/chromium/third_party/blink/renderer/core/fetch/fetch_manager.cc
+++ b/chromium/third_party/blink/renderer/core/fetch/fetch_manager.cc
@@ -12,10 +12,12 @@
#include "services/network/public/cpp/features.h"
#include "services/network/public/cpp/request_mode.h"
#include "services/network/public/mojom/fetch_api.mojom-blink.h"
+#include "services/network/public/mojom/trust_tokens.mojom-blink.h"
#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h"
#include "third_party/blink/public/platform/web_url_request.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_response_init.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_throw_dom_exception.h"
#include "third_party/blink/renderer/core/dom/abort_signal.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
@@ -25,6 +27,7 @@
#include "third_party/blink/renderer/core/fetch/form_data_bytes_consumer.h"
#include "third_party/blink/renderer/core/fetch/place_holder_bytes_consumer.h"
#include "third_party/blink/renderer/core/fetch/response.h"
+#include "third_party/blink/renderer/core/fetch/trust_token_to_mojom.h"
#include "third_party/blink/renderer/core/fileapi/blob.h"
#include "third_party/blink/renderer/core/frame/csp/content_security_policy.h"
#include "third_party/blink/renderer/core/frame/frame.h"
@@ -226,7 +229,9 @@ class FetchManager::Loader final
void PerformNetworkError(const String& message);
void PerformHTTPFetch(ExceptionState&);
void PerformDataFetch();
- void Failed(const String& message);
+ // If |dom_exception| is provided, throws the specified DOMException instead
+ // of the usual "Failed to fetch" TypeError.
+ void Failed(const String& message, DOMException* dom_exception);
void NotifyFinished();
ExecutionContext* GetExecutionContext() { return execution_context_; }
@@ -405,47 +410,9 @@ void FetchManager::Loader::DidReceiveResponse(
place_holder_body_ = MakeGarbageCollected<PlaceHolderBytesConsumer>();
FetchResponseData* response_data = FetchResponseData::CreateWithBuffer(
BodyStreamBuffer::Create(script_state, place_holder_body_, signal_));
- response_data->SetStatus(response.HttpStatusCode());
- if (response.CurrentRequestUrl().ProtocolIsAbout() ||
- response.CurrentRequestUrl().ProtocolIsData() ||
- response.CurrentRequestUrl().ProtocolIs("blob")) {
- response_data->SetStatusMessage("OK");
- } else {
- response_data->SetStatusMessage(response.HttpStatusText());
- }
- for (auto& it : response.HttpHeaderFields())
- response_data->HeaderList()->Append(it.key, it.value);
-
- // Corresponds to https://fetch.spec.whatwg.org/#main-fetch step:
- // "If |internalResponse|’s URL list is empty, then set it to a clone of
- // |request|’s URL list."
- if (response.UrlListViaServiceWorker().IsEmpty()) {
- // Note: |UrlListViaServiceWorker()| is empty, unless the response came from
- // a service worker, in which case it will only be empty if it was created
- // through new Response().
- response_data->SetURLList(url_list_);
- } else {
- DCHECK(response.WasFetchedViaServiceWorker());
- response_data->SetURLList(response.UrlListViaServiceWorker());
- }
-
- response_data->SetMimeType(response.MimeType());
- response_data->SetResponseTime(response.ResponseTime());
-
- if (response.WasCached()) {
- response_data->SetResponseSource(
- network::mojom::FetchResponseSource::kHttpCache);
- } else if (!response.WasFetchedViaServiceWorker()) {
- response_data->SetResponseSource(
- network::mojom::FetchResponseSource::kNetwork);
- }
-
- // Note if the response was loaded with credentials enabled.
- response_data->SetLoadedWithCredentials(
- fetch_request_data_->Credentials() == CredentialsMode::kInclude ||
- (fetch_request_data_->Credentials() == CredentialsMode::kSameOrigin &&
- tainting == FetchRequestData::kBasicTainting));
+ response_data->InitFromResourceResponse(
+ url_list_, fetch_request_data_->Credentials(), tainting, response);
FetchResponseData* tainted_response = nullptr;
@@ -530,11 +497,18 @@ void FetchManager::Loader::DidFinishLoading(uint64_t) {
}
void FetchManager::Loader::DidFail(const ResourceError& error) {
- Failed(String());
+ if (error.TrustTokenOperationError() !=
+ network::mojom::blink::TrustTokenOperationStatus::kOk) {
+ Failed(String(),
+ TrustTokenErrorToDOMException(error.TrustTokenOperationError()));
+ return;
+ }
+
+ Failed(String(), nullptr);
}
void FetchManager::Loader::DidFailRedirectCheck() {
- Failed(String());
+ Failed(String(), nullptr);
}
void FetchManager::Loader::Start(ExceptionState& exception_state) {
@@ -690,7 +664,7 @@ void FetchManager::Loader::PerformSchemeFetch(ExceptionState& exception_state) {
}
void FetchManager::Loader::PerformNetworkError(const String& message) {
- Failed(message);
+ Failed(message, nullptr);
}
void FetchManager::Loader::PerformHTTPFetch(ExceptionState& exception_state) {
@@ -801,7 +775,7 @@ void FetchManager::Loader::PerformHTTPFetch(ExceptionState& exception_state) {
threadable_loader_ = MakeGarbageCollected<ThreadableLoader>(
*execution_context_, this, resource_loader_options);
- threadable_loader_->Start(request);
+ threadable_loader_->Start(std::move(request));
}
// performDataFetch() is almost the same as performHTTPFetch(), except for:
@@ -829,10 +803,11 @@ void FetchManager::Loader::PerformDataFetch() {
threadable_loader_ = MakeGarbageCollected<ThreadableLoader>(
*execution_context_, this, resource_loader_options);
- threadable_loader_->Start(request);
+ threadable_loader_->Start(std::move(request));
}
-void FetchManager::Loader::Failed(const String& message) {
+void FetchManager::Loader::Failed(const String& message,
+ DOMException* dom_exception) {
if (failed_ || finished_)
return;
failed_ = true;
@@ -846,8 +821,12 @@ void FetchManager::Loader::Failed(const String& message) {
if (resolver_) {
ScriptState* state = resolver_->GetScriptState();
ScriptState::Scope scope(state);
- resolver_->Reject(V8ThrowException::CreateTypeError(state->GetIsolate(),
- "Failed to fetch"));
+ if (dom_exception) {
+ resolver_->Reject(dom_exception);
+ } else {
+ resolver_->Reject(V8ThrowException::CreateTypeError(state->GetIsolate(),
+ "Failed to fetch"));
+ }
}
NotifyFinished();
}
diff --git a/chromium/third_party/blink/renderer/core/fetch/fetch_request_data.cc b/chromium/third_party/blink/renderer/core/fetch/fetch_request_data.cc
index dbafa4d4649..2bc52ecc3a0 100644
--- a/chromium/third_party/blink/renderer/core/fetch/fetch_request_data.cc
+++ b/chromium/third_party/blink/renderer/core/fetch/fetch_request_data.cc
@@ -72,7 +72,8 @@ FetchRequestData* FetchRequestData::Create(
ScriptState* script_state,
const mojom::blink::FetchAPIRequest& fetch_api_request,
ForServiceWorkerFetchEvent for_service_worker_fetch_event) {
- FetchRequestData* request = MakeGarbageCollected<FetchRequestData>();
+ FetchRequestData* request = MakeGarbageCollected<FetchRequestData>(
+ script_state ? ExecutionContext::From(script_state) : nullptr);
request->url_ = fetch_api_request.url;
request->method_ = AtomicString(fetch_api_request.method);
for (const auto& pair : fetch_api_request.headers) {
@@ -130,7 +131,7 @@ FetchRequestData* FetchRequestData::Create(
}
FetchRequestData* FetchRequestData::CloneExceptBody() {
- auto* request = MakeGarbageCollected<FetchRequestData>();
+ auto* request = MakeGarbageCollected<FetchRequestData>(execution_context_);
request->url_ = url_;
request->method_ = method_;
request->header_list_ = header_list_->Clone();
@@ -168,9 +169,11 @@ FetchRequestData* FetchRequestData::Clone(ScriptState* script_state,
buffer_ = new1;
request->buffer_ = new2;
}
- if (url_loader_factory_) {
+ if (url_loader_factory_.is_bound()) {
url_loader_factory_->Clone(
- request->url_loader_factory_.BindNewPipeAndPassReceiver());
+ request->url_loader_factory_.BindNewPipeAndPassReceiver(
+ ExecutionContext::From(script_state)
+ ->GetTaskRunner(TaskType::kNetworking)));
}
return request;
}
@@ -192,7 +195,7 @@ FetchRequestData* FetchRequestData::Pass(ScriptState* script_state,
FetchRequestData::~FetchRequestData() {}
-FetchRequestData::FetchRequestData()
+FetchRequestData::FetchRequestData(ExecutionContext* execution_context)
: method_(http_names::kGET),
header_list_(MakeGarbageCollected<FetchHeaderList>()),
context_(mojom::RequestContextType::UNSPECIFIED),
@@ -206,11 +209,15 @@ FetchRequestData::FetchRequestData()
importance_(mojom::FetchImportanceMode::kImportanceAuto),
response_tainting_(kBasicTainting),
priority_(ResourceLoadPriority::kUnresolved),
- keepalive_(false) {}
+ keepalive_(false),
+ url_loader_factory_(execution_context),
+ execution_context_(execution_context) {}
void FetchRequestData::Trace(Visitor* visitor) {
visitor->Trace(buffer_);
visitor->Trace(header_list_);
+ visitor->Trace(url_loader_factory_);
+ visitor->Trace(execution_context_);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/fetch/fetch_request_data.h b/chromium/third_party/blink/renderer/core/fetch/fetch_request_data.h
index f33e8ff3b58..cf2e86c21b8 100644
--- a/chromium/third_party/blink/renderer/core/fetch/fetch_request_data.h
+++ b/chromium/third_party/blink/renderer/core/fetch/fetch_request_data.h
@@ -9,7 +9,6 @@
#include "base/memory/scoped_refptr.h"
#include "base/unguessable_token.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
-#include "mojo/public/cpp/bindings/remote.h"
#include "services/network/public/mojom/fetch_api.mojom-blink-forward.h"
#include "services/network/public/mojom/referrer_policy.mojom-blink-forward.h"
#include "services/network/public/mojom/trust_tokens.mojom-blink.h"
@@ -19,6 +18,8 @@
#include "third_party/blink/renderer/core/fetch/body_stream_buffer.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_load_priority.h"
+#include "third_party/blink/renderer/platform/mojo/heap_mojo_remote.h"
+#include "third_party/blink/renderer/platform/mojo/heap_mojo_wrapper_mode.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"
@@ -44,7 +45,7 @@ class CORE_EXPORT FetchRequestData final
FetchRequestData* Clone(ScriptState*, ExceptionState&);
FetchRequestData* Pass(ScriptState*, ExceptionState&);
- FetchRequestData();
+ explicit FetchRequestData(ExecutionContext* execution_context);
~FetchRequestData();
void SetMethod(AtomicString method) { method_ = method; }
@@ -120,7 +121,9 @@ class CORE_EXPORT FetchRequestData final
}
void SetURLLoaderFactory(
mojo::PendingRemote<network::mojom::blink::URLLoaderFactory> factory) {
- url_loader_factory_.Bind(std::move(factory));
+ url_loader_factory_.Bind(
+ std::move(factory),
+ execution_context_->GetTaskRunner(TaskType::kNetworking));
}
const base::UnguessableToken& WindowId() const { return window_id_; }
void SetWindowId(const base::UnguessableToken& id) { window_id_ = id; }
@@ -175,8 +178,11 @@ class CORE_EXPORT FetchRequestData final
// the system would otherwise decide to use to load this request.
// Currently used for blob: URLs, to ensure they can still be loaded even if
// the URL got revoked after creating the request.
- mojo::Remote<network::mojom::blink::URLLoaderFactory> url_loader_factory_;
+ HeapMojoRemote<network::mojom::blink::URLLoaderFactory,
+ HeapMojoWrapperMode::kWithoutContextObserver>
+ url_loader_factory_;
base::UnguessableToken window_id_;
+ Member<ExecutionContext> execution_context_;
DISALLOW_COPY_AND_ASSIGN(FetchRequestData);
};
diff --git a/chromium/third_party/blink/renderer/core/fetch/fetch_response_data.cc b/chromium/third_party/blink/renderer/core/fetch/fetch_response_data.cc
index 9609acb0e92..7c96506830c 100644
--- a/chromium/third_party/blink/renderer/core/fetch/fetch_response_data.cc
+++ b/chromium/third_party/blink/renderer/core/fetch/fetch_response_data.cc
@@ -4,9 +4,6 @@
#include "third_party/blink/renderer/core/fetch/fetch_response_data.h"
-#include "services/network/public/cpp/content_security_policy/content_security_policy.h"
-#include "services/network/public/cpp/features.h"
-#include "services/network/public/mojom/content_security_policy.mojom-blink.h"
#include "third_party/blink/public/mojom/fetch/fetch_api_response.mojom-blink.h"
#include "third_party/blink/renderer/core/fetch/fetch_header_list.h"
#include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer.h"
@@ -15,76 +12,13 @@
#include "third_party/blink/renderer/platform/loader/cors/cors.h"
#include "third_party/blink/renderer/platform/loader/fetch/fetch_utils.h"
#include "third_party/blink/renderer/platform/network/http_names.h"
+#include "third_party/blink/renderer/platform/network/http_parsers.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
-#include "third_party/blink/renderer/platform/wtf/text/string_utf8_adaptor.h"
-#include "url/gurl.h"
using Type = network::mojom::FetchResponseType;
using ResponseSource = network::mojom::FetchResponseSource;
-// TODO(lfg): Stop converting from/to blink type. Instead use mojo to
-// automagically convert this.
-namespace network {
-namespace mojom {
-
-blink::CSPSourcePtr ConvertToBlink(CSPSourcePtr source) {
- return blink::CSPSource::New(
- String::FromUTF8(source->scheme), String::FromUTF8(source->host),
- source->port, String::FromUTF8(source->path), source->is_host_wildcard,
- source->is_port_wildcard);
-}
-
-blink::CSPSourceListPtr ConvertToBlink(CSPSourceListPtr source_list) {
- WTF::Vector<blink::CSPSourcePtr> sources;
- for (auto& it : source_list->sources)
- sources.push_back(ConvertToBlink(std::move(it)));
-
- return blink::CSPSourceList::New(std::move(sources), source_list->allow_self,
- source_list->allow_star,
- source_list->allow_response_redirects);
-}
-
-blink::CSPDirectiveName ConvertToBlink(CSPDirectiveName name) {
- return static_cast<blink::CSPDirectiveName>(name);
-}
-
-blink::ContentSecurityPolicyHeaderPtr ConvertToBlink(
- ContentSecurityPolicyHeaderPtr header) {
- return blink::ContentSecurityPolicyHeader::New(
- String::FromUTF8(header->header_value), header->type, header->source);
-}
-
-blink::ContentSecurityPolicyPtr ConvertToBlink(
- ContentSecurityPolicyPtr policy_in) {
- auto policy = blink::ContentSecurityPolicy::New();
-
- policy->header = ConvertToBlink(std::move(policy_in->header));
- policy->use_reporting_api = policy_in->use_reporting_api;
-
- for (auto& directive : policy_in->directives) {
- policy->directives.insert(ConvertToBlink(directive.first),
- ConvertToBlink(std::move(directive.second)));
- }
-
- for (auto& endpoint : policy_in->report_endpoints)
- policy->report_endpoints.push_back(String::FromUTF8(endpoint));
-
- return policy;
-}
-
-WTF::Vector<blink::ContentSecurityPolicyPtr> ConvertToBlink(
- std::vector<ContentSecurityPolicyPtr> policies) {
- WTF::Vector<blink::ContentSecurityPolicyPtr> blink_policies;
- for (auto& policy : policies)
- blink_policies.push_back(ConvertToBlink(std::move(policy)));
-
- return blink_policies;
-}
-
-} // namespace mojom
-} // namespace network
-
namespace blink {
namespace {
@@ -330,31 +264,56 @@ mojom::blink::FetchAPIResponsePtr FetchResponseData::PopulateFetchAPIResponse(
response->loaded_with_credentials = loaded_with_credentials_;
for (const auto& header : HeaderList()->List())
response->headers.insert(header.first, header.second);
+ response->parsed_headers = ParseHeaders(
+ HeaderList()->GetAsRawString(status_, status_message_), request_url);
+ return response;
+}
- // Check if there's a Content-Security-Policy header and parse it if
- // necessary.
- // TODO(lfg). What about report only header?
- if (base::FeatureList::IsEnabled(
- network::features::kOutOfBlinkFrameAncestors)) {
- String content_security_policy_header;
- std::vector<network::mojom::ContentSecurityPolicyPtr> policies;
- if (HeaderList()->Get("content-security-policy",
- content_security_policy_header)) {
- network::AddContentSecurityPolicyFromHeaders(
- StringUTF8Adaptor(content_security_policy_header).AsStringPiece(),
- network::mojom::ContentSecurityPolicyType::kEnforce, request_url,
- &policies);
- }
- if (HeaderList()->Get("content-security-policy-report-only",
- content_security_policy_header)) {
- network::AddContentSecurityPolicyFromHeaders(
- StringUTF8Adaptor(content_security_policy_header).AsStringPiece(),
- network::mojom::ContentSecurityPolicyType::kReport, request_url,
- &policies);
- }
- response->content_security_policy = ConvertToBlink(std::move(policies));
+void FetchResponseData::InitFromResourceResponse(
+ const Vector<KURL>& request_url_list,
+ network::mojom::CredentialsMode request_credentials,
+ FetchRequestData::Tainting tainting,
+ const ResourceResponse& response) {
+ SetStatus(response.HttpStatusCode());
+ if (response.CurrentRequestUrl().ProtocolIsAbout() ||
+ response.CurrentRequestUrl().ProtocolIsData() ||
+ response.CurrentRequestUrl().ProtocolIs("blob")) {
+ SetStatusMessage("OK");
+ } else {
+ SetStatusMessage(response.HttpStatusText());
}
- return response;
+
+ for (auto& it : response.HttpHeaderFields())
+ HeaderList()->Append(it.key, it.value);
+
+ // Corresponds to https://fetch.spec.whatwg.org/#main-fetch step:
+ // "If |internalResponse|’s URL list is empty, then set it to a clone of
+ // |request|’s URL list."
+ if (response.UrlListViaServiceWorker().IsEmpty()) {
+ // Note: |UrlListViaServiceWorker()| is empty, unless the response came from
+ // a service worker, in which case it will only be empty if it was created
+ // through new Response().
+ SetURLList(request_url_list);
+ } else {
+ DCHECK(response.WasFetchedViaServiceWorker());
+ SetURLList(response.UrlListViaServiceWorker());
+ }
+
+ SetMimeType(response.MimeType());
+ SetResponseTime(response.ResponseTime());
+
+ if (response.WasCached()) {
+ SetResponseSource(network::mojom::FetchResponseSource::kHttpCache);
+ } else if (!response.WasFetchedViaServiceWorker()) {
+ SetResponseSource(network::mojom::FetchResponseSource::kNetwork);
+ }
+
+ // TODO(wanderview): Remove |tainting| and use |response.GetType()|
+ // instead once the OOR-CORS disabled path is removed.
+ SetLoadedWithCredentials(
+ request_credentials == network::mojom::CredentialsMode::kInclude ||
+ (request_credentials == network::mojom::CredentialsMode::kSameOrigin &&
+ tainting == FetchRequestData::kBasicTainting));
}
FetchResponseData::FetchResponseData(Type type,
diff --git a/chromium/third_party/blink/renderer/core/fetch/fetch_response_data.h b/chromium/third_party/blink/renderer/core/fetch/fetch_response_data.h
index 0c2af0c626a..1eb7454afb0 100644
--- a/chromium/third_party/blink/renderer/core/fetch/fetch_response_data.h
+++ b/chromium/third_party/blink/renderer/core/fetch/fetch_response_data.h
@@ -14,11 +14,12 @@
#include "third_party/blink/public/mojom/fetch/fetch_api_response.mojom-blink-forward.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/fetch/body_stream_buffer.h"
+#include "third_party/blink/renderer/core/fetch/fetch_request_data.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
+#include "third_party/blink/renderer/platform/loader/fetch/resource_response.h"
#include "third_party/blink/renderer/platform/network/http_header_set.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
-
#include "third_party/blink/renderer/platform/wtf/vector.h"
namespace blink {
@@ -117,6 +118,13 @@ class CORE_EXPORT FetchResponseData final
mojom::blink::FetchAPIResponsePtr PopulateFetchAPIResponse(
const KURL& request_url);
+ // Initialize non-body data from the given |response|.
+ void InitFromResourceResponse(
+ const Vector<KURL>& request_url_list,
+ network::mojom::CredentialsMode request_credentials,
+ FetchRequestData::Tainting tainting,
+ const ResourceResponse& response);
+
void Trace(Visitor*);
private:
diff --git a/chromium/third_party/blink/renderer/core/fetch/fetch_response_data_test.cc b/chromium/third_party/blink/renderer/core/fetch/fetch_response_data_test.cc
index af072b5bcbd..d7f8d314135 100644
--- a/chromium/third_party/blink/renderer/core/fetch/fetch_response_data_test.cc
+++ b/chromium/third_party/blink/renderer/core/fetch/fetch_response_data_test.cc
@@ -277,7 +277,7 @@ TEST_F(FetchResponseDataTest, ContentSecurityPolicy) {
mojom::blink::FetchAPIResponsePtr fetch_api_response =
internal_response->PopulateFetchAPIResponse(KURL());
- auto& csp = fetch_api_response->content_security_policy;
+ auto& csp = fetch_api_response->parsed_headers->content_security_policy;
EXPECT_EQ(csp.size(), 2U);
EXPECT_EQ(csp[0]->header->type,
diff --git a/chromium/third_party/blink/renderer/core/fetch/request.cc b/chromium/third_party/blink/renderer/core/fetch/request.cc
index ee851d89091..a6bec95916d 100644
--- a/chromium/third_party/blink/renderer/core/fetch/request.cc
+++ b/chromium/third_party/blink/renderer/core/fetch/request.cc
@@ -31,7 +31,7 @@
#include "third_party/blink/renderer/core/fetch/body_stream_buffer.h"
#include "third_party/blink/renderer/core/fetch/fetch_manager.h"
#include "third_party/blink/renderer/core/fetch/form_data_bytes_consumer.h"
-#include "third_party/blink/renderer/core/fetch/trust_token.h"
+#include "third_party/blink/renderer/core/fetch/trust_token_issuance_authorization.h"
#include "third_party/blink/renderer/core/fetch/trust_token_to_mojom.h"
#include "third_party/blink/renderer/core/fileapi/blob.h"
#include "third_party/blink/renderer/core/fileapi/public_url_manager.h"
@@ -66,7 +66,8 @@ using network::mojom::blink::TrustTokenOperationType;
FetchRequestData* CreateCopyOfFetchRequestDataForFetch(
ScriptState* script_state,
const FetchRequestData* original) {
- auto* request = MakeGarbageCollected<FetchRequestData>();
+ auto* request = MakeGarbageCollected<FetchRequestData>(
+ ExecutionContext::From(script_state));
request->SetURL(original->Url());
request->SetMethod(original->Method());
request->SetHeaderList(original->HeaderList()->Clone());
@@ -253,7 +254,8 @@ Request* Request::CreateRequestWithRequestOrString(
// integrity metadata is |request|'s integrity metadata."
FetchRequestData* request = CreateCopyOfFetchRequestDataForFetch(
script_state, input_request ? input_request->GetRequest()
- : MakeGarbageCollected<FetchRequestData>());
+ : MakeGarbageCollected<FetchRequestData>(
+ execution_context));
if (input_request) {
// "Set |signal| to input’s signal."
@@ -380,7 +382,7 @@ Request* Request::CreateRequestWithRequestOrString(
if (!SecurityPolicy::ReferrerPolicyFromString(
init->referrerPolicy(), kDoNotSupportReferrerPolicyLegacyKeywords,
&referrer_policy)) {
- DCHECK(init->referrerPolicy().IsEmpty());
+ DCHECK_EQ(init->referrerPolicy(), g_empty_string);
referrer_policy = network::mojom::ReferrerPolicy::kDefault;
}
@@ -392,18 +394,20 @@ Request* Request::CreateRequestWithRequestOrString(
// |fallbackMode| otherwise."
// - "If |mode| is "navigate", throw a TypeError."
// - "If |mode| is non-null, set |request|'s mode to |mode|."
- if (init->mode() == "navigate") {
- exception_state.ThrowTypeError(
- "Cannot construct a Request with a RequestInit whose mode member is "
- "set as 'navigate'.");
- return nullptr;
- }
- if (init->mode() == "same-origin") {
- request->SetMode(network::mojom::RequestMode::kSameOrigin);
- } else if (init->mode() == "no-cors") {
- request->SetMode(network::mojom::RequestMode::kNoCors);
- } else if (init->mode() == "cors") {
- request->SetMode(network::mojom::RequestMode::kCors);
+ if (init->hasMode()) {
+ if (init->mode() == "navigate") {
+ exception_state.ThrowTypeError(
+ "Cannot construct a Request with a RequestInit whose mode member is "
+ "set as 'navigate'.");
+ return nullptr;
+ }
+ if (init->mode() == "same-origin") {
+ request->SetMode(network::mojom::RequestMode::kSameOrigin);
+ } else if (init->mode() == "no-cors") {
+ request->SetMode(network::mojom::RequestMode::kNoCors);
+ } else if (init->mode() == "cors") {
+ request->SetMode(network::mojom::RequestMode::kCors);
+ }
} else {
// |inputRequest| is directly checked here instead of setting and
// checking |fallbackMode| as specified in the spec.
@@ -415,48 +419,47 @@ Request* Request::CreateRequestWithRequestOrString(
// "If |init|'s importance member is present, set |request|'s importance
// mode to it." For more information see Priority Hints at
// https://crbug.com/821464.
- DCHECK(init->importance().IsNull() ||
- RuntimeEnabledFeatures::PriorityHintsEnabled(execution_context));
- if (!init->importance().IsNull())
+ if (init->hasImportance()) {
UseCounter::Count(execution_context, WebFeature::kPriorityHints);
-
- if (init->importance() == "low") {
- request->SetImportance(mojom::FetchImportanceMode::kImportanceLow);
- } else if (init->importance() == "high") {
- request->SetImportance(mojom::FetchImportanceMode::kImportanceHigh);
+ if (init->importance() == "low") {
+ request->SetImportance(mojom::blink::FetchImportanceMode::kImportanceLow);
+ } else if (init->importance() == "high") {
+ request->SetImportance(
+ mojom::blink::FetchImportanceMode::kImportanceHigh);
+ }
}
// "Let |credentials| be |init|'s credentials member if it is present, and
// |fallbackCredentials| otherwise."
// "If |credentials| is non-null, set |request|'s credentials mode to
// |credentials|."
-
- base::Optional<network::mojom::CredentialsMode> credentials_result =
- ParseCredentialsMode(init->credentials());
- if (credentials_result) {
- request->SetCredentials(credentials_result.value());
+ if (init->hasCredentials()) {
+ request->SetCredentials(ParseCredentialsMode(init->credentials()).value());
} else if (!input_request) {
request->SetCredentials(network::mojom::CredentialsMode::kSameOrigin);
}
// "If |init|'s cache member is present, set |request|'s cache mode to it."
- if (init->cache() == "default") {
- request->SetCacheMode(mojom::FetchCacheMode::kDefault);
- } else if (init->cache() == "no-store") {
- request->SetCacheMode(mojom::FetchCacheMode::kNoStore);
- } else if (init->cache() == "reload") {
- request->SetCacheMode(mojom::FetchCacheMode::kBypassCache);
- } else if (init->cache() == "no-cache") {
- request->SetCacheMode(mojom::FetchCacheMode::kValidateCache);
- } else if (init->cache() == "force-cache") {
- request->SetCacheMode(mojom::FetchCacheMode::kForceCache);
- } else if (init->cache() == "only-if-cached") {
- request->SetCacheMode(mojom::FetchCacheMode::kOnlyIfCached);
+ if (init->hasCache()) {
+ auto&& cache = init->cache();
+ if (cache == "default") {
+ request->SetCacheMode(mojom::blink::FetchCacheMode::kDefault);
+ } else if (cache == "no-store") {
+ request->SetCacheMode(mojom::blink::FetchCacheMode::kNoStore);
+ } else if (cache == "reload") {
+ request->SetCacheMode(mojom::blink::FetchCacheMode::kBypassCache);
+ } else if (cache == "no-cache") {
+ request->SetCacheMode(mojom::blink::FetchCacheMode::kValidateCache);
+ } else if (cache == "force-cache") {
+ request->SetCacheMode(mojom::blink::FetchCacheMode::kForceCache);
+ } else if (cache == "only-if-cached") {
+ request->SetCacheMode(mojom::blink::FetchCacheMode::kOnlyIfCached);
+ }
}
// If |request|’s cache mode is "only-if-cached" and |request|’s mode is not
// "same-origin", then throw a TypeError.
- if (request->CacheMode() == mojom::FetchCacheMode::kOnlyIfCached &&
+ if (request->CacheMode() == mojom::blink::FetchCacheMode::kOnlyIfCached &&
request->Mode() != network::mojom::RequestMode::kSameOrigin) {
exception_state.ThrowTypeError(
"'only-if-cached' can be set only with 'same-origin' mode");
@@ -465,12 +468,14 @@ Request* Request::CreateRequestWithRequestOrString(
// "If |init|'s redirect member is present, set |request|'s redirect mode
// to it."
- if (init->redirect() == "follow") {
- request->SetRedirect(network::mojom::RedirectMode::kFollow);
- } else if (init->redirect() == "error") {
- request->SetRedirect(network::mojom::RedirectMode::kError);
- } else if (init->redirect() == "manual") {
- request->SetRedirect(network::mojom::RedirectMode::kManual);
+ if (init->hasRedirect()) {
+ if (init->redirect() == "follow") {
+ request->SetRedirect(network::mojom::RedirectMode::kFollow);
+ } else if (init->redirect() == "error") {
+ request->SetRedirect(network::mojom::RedirectMode::kError);
+ } else if (init->redirect() == "manual") {
+ request->SetRedirect(network::mojom::RedirectMode::kManual);
+ }
}
// "If |init|'s integrity member is present, set |request|'s
@@ -508,6 +513,9 @@ Request* Request::CreateRequestWithRequestOrString(
}
if (init->hasTrustToken()) {
+ UseCounter::Count(ExecutionContext::From(script_state),
+ mojom::blink::WebFeature::kTrustTokenFetch);
+
network::mojom::blink::TrustTokenParams params;
if (!ConvertTrustTokenToMojom(*init->trustToken(), &exception_state,
&params)) {
@@ -517,6 +525,13 @@ Request* Request::CreateRequestWithRequestOrString(
return nullptr;
}
+ if (!execution_context->IsSecureContext()) {
+ exception_state.ThrowTypeError(
+ "trustToken: TrustTokens operations are only available in secure "
+ "contexts.");
+ return nullptr;
+ }
+
if ((params.type == TrustTokenOperationType::kRedemption ||
params.type == TrustTokenOperationType::kSigning) &&
!execution_context->IsFeatureEnabled(
@@ -528,6 +543,16 @@ Request* Request::CreateRequestWithRequestOrString(
return nullptr;
}
+ VLOG(1) << "a";
+
+ if (params.type == TrustTokenOperationType::kIssuance &&
+ !IsTrustTokenIssuanceAvailableInExecutionContext(*execution_context)) {
+ exception_state.ThrowTypeError(
+ "trustToken: Issuance ('token-request') is disabled except in "
+ "contexts with the TrustTokens Origin Trial enabled.");
+ return nullptr;
+ }
+
request->SetTrustTokenParams(std::move(params));
}
@@ -707,6 +732,7 @@ base::Optional<network::mojom::CredentialsMode> Request::ParseCredentialsMode(
return network::mojom::CredentialsMode::kSameOrigin;
if (credentials_mode == "include")
return network::mojom::CredentialsMode::kInclude;
+ NOTREACHED();
return base::nullopt;
}
@@ -908,7 +934,6 @@ mojom::blink::FetchAPIRequestPtr Request::CreateFetchAPIRequest() const {
fetch_api_request->redirect_mode = request_->Redirect();
fetch_api_request->integrity = request_->Integrity();
fetch_api_request->is_history_navigation = request_->IsHistoryNavigation();
- fetch_api_request->request_context_type = request_->Context();
fetch_api_request->destination = request_->Destination();
// Strip off the fragment part of URL. So far, all callers expect the fragment
@@ -970,6 +995,8 @@ network::mojom::RequestDestination Request::GetRequestDestination() const {
}
void Request::Trace(Visitor* visitor) {
+ ScriptWrappable::Trace(visitor);
+ ActiveScriptWrappable<Request>::Trace(visitor);
Body::Trace(visitor);
visitor->Trace(request_);
visitor->Trace(headers_);
diff --git a/chromium/third_party/blink/renderer/core/fetch/request.h b/chromium/third_party/blink/renderer/core/fetch/request.h
index 04a2a59158e..23147aebd4f 100644
--- a/chromium/third_party/blink/renderer/core/fetch/request.h
+++ b/chromium/third_party/blink/renderer/core/fetch/request.h
@@ -29,8 +29,11 @@ class RequestInit;
using RequestInfo = RequestOrUSVString;
-class CORE_EXPORT Request final : public Body {
+class CORE_EXPORT Request final : public ScriptWrappable,
+ public ActiveScriptWrappable<Request>,
+ public Body {
DEFINE_WRAPPERTYPEINFO();
+ USING_GARBAGE_COLLECTED_MIXIN(Request);
public:
using ForServiceWorkerFetchEvent =
@@ -85,6 +88,11 @@ class CORE_EXPORT Request final : public Body {
// This function must be called with entering an appropriate V8 context.
Request* clone(ScriptState*, ExceptionState&);
+ // ScriptWrappable override
+ bool HasPendingActivity() const override {
+ return Body::HasPendingActivity();
+ }
+
FetchRequestData* PassRequestData(ScriptState*, ExceptionState&);
mojom::blink::FetchAPIRequestPtr CreateFetchAPIRequest() const;
bool HasBody() const;
diff --git a/chromium/third_party/blink/renderer/core/fetch/request_init.idl b/chromium/third_party/blink/renderer/core/fetch/request_init.idl
index 62428ff3a14..3f4f4ba2177 100644
--- a/chromium/third_party/blink/renderer/core/fetch/request_init.idl
+++ b/chromium/third_party/blink/renderer/core/fetch/request_init.idl
@@ -23,7 +23,11 @@ dictionary RequestInit {
boolean keepalive;
[RuntimeEnabled=PriorityHints] RequestImportance importance;
AbortSignal? signal;
- [RuntimeEnabled=TrustTokens, SecureContext] TrustToken trustToken;
+ // Even though Trust Tokens operations are only available in secure
+ // contexts, this has to be enforced after the fact because the
+ // SecureContext IDL attribute doesn't affect dictionary members.
+ [RuntimeEnabled=TrustTokens] TrustToken trustToken;
+
// TODO(domfarolino): add support for RequestInit window member.
//any window; // can only be set to null
};
diff --git a/chromium/third_party/blink/renderer/core/fetch/request_test.cc b/chromium/third_party/blink/renderer/core/fetch/request_test.cc
index f37d4d239b3..6e05308c72c 100644
--- a/chromium/third_party/blink/renderer/core/fetch/request_test.cc
+++ b/chromium/third_party/blink/renderer/core/fetch/request_test.cc
@@ -114,6 +114,7 @@ TEST(ServiceWorkerRequestTest, FromAndToFetchAPIRequest) {
EXPECT_EQ(kCredentialsMode, second_fetch_api_request->credentials_mode);
EXPECT_EQ(kCacheMode, second_fetch_api_request->cache_mode);
EXPECT_EQ(kRedirectMode, second_fetch_api_request->redirect_mode);
+ EXPECT_EQ(kDestination, second_fetch_api_request->destination);
EXPECT_EQ(referrer, second_fetch_api_request->referrer->url);
EXPECT_EQ(network::mojom::ReferrerPolicy::kAlways,
second_fetch_api_request->referrer->policy);
diff --git a/chromium/third_party/blink/renderer/core/fetch/response.cc b/chromium/third_party/blink/renderer/core/fetch/response.cc
index 9ca8b435767..f3bd7020c3f 100644
--- a/chromium/third_party/blink/renderer/core/fetch/response.cc
+++ b/chromium/third_party/blink/renderer/core/fetch/response.cc
@@ -555,6 +555,8 @@ FetchHeaderList* Response::InternalHeaderList() const {
}
void Response::Trace(Visitor* visitor) {
+ ScriptWrappable::Trace(visitor);
+ ActiveScriptWrappable<Response>::Trace(visitor);
Body::Trace(visitor);
visitor->Trace(response_);
visitor->Trace(headers_);
diff --git a/chromium/third_party/blink/renderer/core/fetch/response.h b/chromium/third_party/blink/renderer/core/fetch/response.h
index 758d6042a7c..9d0987f51a7 100644
--- a/chromium/third_party/blink/renderer/core/fetch/response.h
+++ b/chromium/third_party/blink/renderer/core/fetch/response.h
@@ -26,8 +26,11 @@ class ExceptionState;
class ResponseInit;
class ScriptState;
-class CORE_EXPORT Response final : public Body {
+class CORE_EXPORT Response final : public ScriptWrappable,
+ public ActiveScriptWrappable<Response>,
+ public Body {
DEFINE_WRAPPERTYPEINFO();
+ USING_GARBAGE_COLLECTED_MIXIN(Response);
public:
// These "create" function which takes a ScriptState* must be called with
diff --git a/chromium/third_party/blink/renderer/core/fetch/trust_token_issuance_authorization.cc b/chromium/third_party/blink/renderer/core/fetch/trust_token_issuance_authorization.cc
new file mode 100644
index 00000000000..1d829f8c942
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/fetch/trust_token_issuance_authorization.cc
@@ -0,0 +1,18 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/fetch/trust_token_issuance_authorization.h"
+
+#include "third_party/blink/renderer/core/execution_context/execution_context.h"
+#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
+
+namespace blink {
+
+bool IsTrustTokenIssuanceAvailableInExecutionContext(
+ const ExecutionContext& context) {
+ return context.FeatureEnabled(OriginTrialFeature::kTrustTokens) ||
+ RuntimeEnabledFeatures::TrustTokensAlwaysAllowIssuanceEnabled();
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/fetch/trust_token_issuance_authorization.h b/chromium/third_party/blink/renderer/core/fetch/trust_token_issuance_authorization.h
new file mode 100644
index 00000000000..a2c1d10b294
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/fetch/trust_token_issuance_authorization.h
@@ -0,0 +1,24 @@
+// 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_CORE_FETCH_TRUST_TOKEN_ISSUANCE_AUTHORIZATION_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_FETCH_TRUST_TOKEN_ISSUANCE_AUTHORIZATION_H_
+
+namespace blink {
+
+class ExecutionContext;
+
+// Returns whether it's OK to execute Trust Tokens issuance in the given
+// execution context. This depends on whether the context is participating in
+// the kTrustTokens origin trial, and whether the embedder has specified an
+// override of this requirement (e.g. for testing).
+//
+// For more information on Trust Tokens configuration, see the comment on
+// network::features::kTrustTokens.
+bool IsTrustTokenIssuanceAvailableInExecutionContext(
+ const ExecutionContext& context);
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_FETCH_TRUST_TOKEN_ISSUANCE_AUTHORIZATION_H_
diff --git a/chromium/third_party/blink/renderer/core/fetch/trust_token_to_mojom.cc b/chromium/third_party/blink/renderer/core/fetch/trust_token_to_mojom.cc
index 1fe53b72d8b..c0064cafe44 100644
--- a/chromium/third_party/blink/renderer/core/fetch/trust_token_to_mojom.cc
+++ b/chromium/third_party/blink/renderer/core/fetch/trust_token_to_mojom.cc
@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include "third_party/blink/renderer/core/fetch/trust_token_to_mojom.h"
+#include "third_party/blink/renderer/core/dom/dom_exception.h"
namespace blink {
@@ -87,4 +88,27 @@ bool ConvertTrustTokenToMojom(const TrustToken& in,
return true;
}
+DOMException* TrustTokenErrorToDOMException(
+ network::mojom::blink::TrustTokenOperationStatus error) {
+ // This should only be called on failure.
+ DCHECK_NE(error, network::mojom::blink::TrustTokenOperationStatus::kOk);
+
+ switch (error) {
+ case network::mojom::blink::TrustTokenOperationStatus::kAlreadyExists:
+ return DOMException::Create(
+ "Redemption operation aborted due to Signed Redemption Record "
+ "cache hit",
+ DOMException::GetErrorName(
+ DOMExceptionCode::kNoModificationAllowedError));
+ case network::mojom::blink::TrustTokenOperationStatus::kFailedPrecondition:
+ return DOMException::Create(
+ "Precondition failed during Trust Tokens operation",
+ DOMException::GetErrorName(DOMExceptionCode::kInvalidStateError));
+ default:
+ return DOMException::Create(
+ "Error executing Trust Tokens operation",
+ DOMException::GetErrorName(DOMExceptionCode::kOperationError));
+ }
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/fetch/trust_token_to_mojom.h b/chromium/third_party/blink/renderer/core/fetch/trust_token_to_mojom.h
index a18f2a245b8..4097c23e879 100644
--- a/chromium/third_party/blink/renderer/core/fetch/trust_token_to_mojom.h
+++ b/chromium/third_party/blink/renderer/core/fetch/trust_token_to_mojom.h
@@ -6,11 +6,13 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_FETCH_TRUST_TOKEN_TO_MOJOM_H_
#include "services/network/public/mojom/trust_tokens.mojom-blink.h"
-#include "third_party/blink/renderer/core/fetch/trust_token.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_trust_token.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
+class DOMException;
+
// Converts an IDL trustToken object to its Mojo counterpart.
// The elements of trustToken (and of TrustTokenParams) comprise:
// - an operation type, always populated
@@ -32,6 +34,13 @@ bool ConvertTrustTokenToMojom(const TrustToken& in,
ExceptionState* exception_state,
network::mojom::blink::TrustTokenParams* out);
+// Converts a Mojo TrustTokenOperationStatus denoting an error into a
+// DOMException suitable for displaying to the API's client.
+//
+// This should only be called on failure; |status| must not equal kOk.
+DOMException* TrustTokenErrorToDOMException(
+ network::mojom::blink::TrustTokenOperationStatus error);
+
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_CORE_FETCH_TRUST_TOKEN_TO_MOJOM_H_
diff --git a/chromium/third_party/blink/renderer/core/fileapi/file_reader.cc b/chromium/third_party/blink/renderer/core/fileapi/file_reader.cc
index e556e849c64..2ba5fc1b845 100644
--- a/chromium/third_party/blink/renderer/core/fileapi/file_reader.cc
+++ b/chromium/third_party/blink/renderer/core/fileapi/file_reader.cc
@@ -34,11 +34,11 @@
#include "base/timer/elapsed_timer.h"
#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/renderer/bindings/core/v8/string_or_array_buffer.h"
-#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/events/progress_event.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/fileapi/file.h"
#include "third_party/blink/renderer/core/fileapi/file_error.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/web_feature.h"
#include "third_party/blink/renderer/core/probe/core_probes.h"
#include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer.h"
@@ -293,8 +293,8 @@ void FileReader::ReadInternal(Blob* blob,
// A document loader will not load new resources once the Document has
// detached from its frame.
- Document* document = Document::DynamicFrom(context);
- if (document && !document->GetFrame()) {
+ LocalDOMWindow* window = DynamicTo<LocalDOMWindow>(context);
+ if (window && !window->GetFrame()) {
exception_state.ThrowDOMException(
DOMExceptionCode::kAbortError,
"Reading from a Document-detached FileReader is not supported.");
diff --git a/chromium/third_party/blink/renderer/core/fileapi/public_url_manager.cc b/chromium/third_party/blink/renderer/core/fileapi/public_url_manager.cc
index 87bad05d26f..e23e101178e 100644
--- a/chromium/third_party/blink/renderer/core/fileapi/public_url_manager.cc
+++ b/chromium/third_party/blink/renderer/core/fileapi/public_url_manager.cc
@@ -36,6 +36,7 @@
#include "third_party/blink/renderer/platform/blob/blob_url.h"
#include "third_party/blink/renderer/platform/blob/blob_url_null_origin_map.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
+#include "third_party/blink/renderer/platform/scheduler/main_thread/task_type_names.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/vector.h"
@@ -53,7 +54,14 @@ static void RemoveFromNullOriginMapIfNecessary(const KURL& blob_url) {
} // namespace
PublicURLManager::PublicURLManager(ExecutionContext* context)
- : ExecutionContextLifecycleObserver(context), is_stopped_(false) {}
+ : ExecutionContextLifecycleObserver(context),
+ is_stopped_(false),
+ url_store_(context) {
+ BlobDataHandle::GetBlobRegistry()->URLStoreForOrigin(
+ context->GetSecurityOrigin(),
+ url_store_.BindNewEndpointAndPassReceiver(
+ context->GetTaskRunner(TaskType::kFileReading)));
+}
String PublicURLManager::RegisterURL(URLRegistrable* registrable) {
if (is_stopped_)
@@ -67,10 +75,6 @@ String PublicURLManager::RegisterURL(URLRegistrable* registrable) {
if (registrable->IsMojoBlob()) {
// Measure how much jank the following synchronous IPC introduces.
SCOPED_UMA_HISTOGRAM_TIMER("Storage.Blob.RegisterPublicURLTime");
- if (!url_store_) {
- BlobDataHandle::GetBlobRegistry()->URLStoreForOrigin(
- origin, url_store_.BindNewEndpointAndPassReceiver());
- }
mojo::PendingRemote<mojom::blink::Blob> blob_remote;
mojo::PendingReceiver<mojom::blink::Blob> blob_receiver =
blob_remote.InitWithNewPipeAndPassReceiver();
@@ -100,11 +104,6 @@ void PublicURLManager::Revoke(const KURL& url) {
GetExecutionContext()->GetSecurityOrigin()))
return;
- if (!url_store_) {
- BlobDataHandle::GetBlobRegistry()->URLStoreForOrigin(
- GetExecutionContext()->GetSecurityOrigin(),
- url_store_.BindNewEndpointAndPassReceiver());
- }
url_store_->Revoke(url);
mojo_urls_.erase(url.GetString());
@@ -124,11 +123,6 @@ void PublicURLManager::Resolve(
return;
DCHECK(url.ProtocolIs("blob"));
- if (!url_store_) {
- BlobDataHandle::GetBlobRegistry()->URLStoreForOrigin(
- GetExecutionContext()->GetSecurityOrigin(),
- url_store_.BindNewEndpointAndPassReceiver());
- }
url_store_->ResolveAsURLLoaderFactory(url, std::move(factory_receiver));
}
@@ -139,11 +133,6 @@ void PublicURLManager::Resolve(
return;
DCHECK(url.ProtocolIs("blob"));
- if (!url_store_) {
- BlobDataHandle::GetBlobRegistry()->URLStoreForOrigin(
- GetExecutionContext()->GetSecurityOrigin(),
- url_store_.BindNewEndpointAndPassReceiver());
- }
url_store_->ResolveForNavigation(url, std::move(token_receiver));
}
@@ -161,11 +150,10 @@ void PublicURLManager::ContextDestroyed() {
url_to_registry_.clear();
mojo_urls_.clear();
-
- url_store_.reset();
}
void PublicURLManager::Trace(Visitor* visitor) {
+ visitor->Trace(url_store_);
ExecutionContextLifecycleObserver::Trace(visitor);
}
diff --git a/chromium/third_party/blink/renderer/core/fileapi/public_url_manager.h b/chromium/third_party/blink/renderer/core/fileapi/public_url_manager.h
index 3ba1a72ef63..dd9b508d52a 100644
--- a/chromium/third_party/blink/renderer/core/fileapi/public_url_manager.h
+++ b/chromium/third_party/blink/renderer/core/fileapi/public_url_manager.h
@@ -33,6 +33,7 @@
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
+#include "third_party/blink/renderer/platform/mojo/heap_mojo_associated_remote.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/text/wtf_string.h"
@@ -74,7 +75,7 @@ class CORE_EXPORT PublicURLManager final
void Trace(Visitor*) override;
void SetURLStoreForTesting(
- mojo::AssociatedRemote<mojom::blink::BlobURLStore> url_store) {
+ HeapMojoAssociatedRemote<mojom::blink::BlobURLStore> url_store) {
url_store_ = std::move(url_store);
}
@@ -87,7 +88,7 @@ class CORE_EXPORT PublicURLManager final
bool is_stopped_;
- mojo::AssociatedRemote<mojom::blink::BlobURLStore> url_store_;
+ HeapMojoAssociatedRemote<mojom::blink::BlobURLStore> url_store_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/fileapi/public_url_manager_test.cc b/chromium/third_party/blink/renderer/core/fileapi/public_url_manager_test.cc
index 5360c48ca5b..daba5f43ef2 100644
--- a/chromium/third_party/blink/renderer/core/fileapi/public_url_manager_test.cc
+++ b/chromium/third_party/blink/renderer/core/fileapi/public_url_manager_test.cc
@@ -75,7 +75,7 @@ class PublicURLManagerTest : public testing::Test {
// wants.
execution_context_->SetUpSecurityContextForTesting();
- mojo::AssociatedRemote<BlobURLStore> url_store_remote;
+ HeapMojoAssociatedRemote<BlobURLStore> url_store_remote(execution_context_);
url_store_receiver_.Bind(
url_store_remote.BindNewEndpointAndPassDedicatedReceiverForTesting());
url_manager().SetURLStoreForTesting(std::move(url_store_remote));
diff --git a/chromium/third_party/blink/renderer/core/frame/BUILD.gn b/chromium/third_party/blink/renderer/core/frame/BUILD.gn
index f6c78c5dde4..bf09a36ee47 100644
--- a/chromium/third_party/blink/renderer/core/frame/BUILD.gn
+++ b/chromium/third_party/blink/renderer/core/frame/BUILD.gn
@@ -92,6 +92,8 @@ blink_core_sources("frame") {
"intervention.h",
"intervention_report_body.cc",
"intervention_report_body.h",
+ "is_input_pending_options.cc",
+ "is_input_pending_options.h",
"layout_subtree_root_list.cc",
"layout_subtree_root_list.h",
"local_dom_window.cc",
@@ -177,8 +179,6 @@ blink_core_sources("frame") {
"scheduling.h",
"screen.cc",
"screen.h",
- "screen_orientation_controller.cc",
- "screen_orientation_controller.h",
"settings.cc",
"settings.h",
"settings_delegate.cc",
@@ -217,6 +217,6 @@ blink_core_sources("frame") {
deps = [
"//skia",
"//ui/base/cursor",
- "//ui/base/mojom:cursor_type_blink",
+ "//ui/base/cursor/mojom:cursor_type_blink",
]
}
diff --git a/chromium/third_party/blink/renderer/core/frame/DEPS b/chromium/third_party/blink/renderer/core/frame/DEPS
index 2bc0bcb5041..9ca14d95bb6 100644
--- a/chromium/third_party/blink/renderer/core/frame/DEPS
+++ b/chromium/third_party/blink/renderer/core/frame/DEPS
@@ -11,6 +11,9 @@ specific_include_rules = {
"remote_frame_view.cc": [
"+components/paint_preview/common/paint_preview_tracker.h",
],
+ "visual_viewport.cc": [
+ "+cc/layers/solid_color_scrollbar_layer.h",
+ ],
"web_frame_widget_base.cc": [
"+cc/trees/swap_promise.h",
],
diff --git a/chromium/third_party/blink/renderer/core/frame/ad_tracker.cc b/chromium/third_party/blink/renderer/core/frame/ad_tracker.cc
index 9476585d36b..3d57716273c 100644
--- a/chromium/third_party/blink/renderer/core/frame/ad_tracker.cc
+++ b/chromium/third_party/blink/renderer/core/frame/ad_tracker.cc
@@ -10,9 +10,11 @@
#include "third_party/blink/renderer/bindings/core/v8/source_location.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
#include "third_party/blink/renderer/core/core_probe_sink.h"
-#include "third_party/blink/renderer/core/dom/document.h"
+#include "third_party/blink/renderer/core/execution_context/execution_context.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/probe/core_probes.h"
+#include "third_party/blink/renderer/platform/loader/fetch/fetch_initiator_type_names.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_request.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
#include "third_party/blink/renderer/platform/wtf/casting.h"
@@ -24,8 +26,8 @@ namespace {
bool IsKnownAdExecutionContext(ExecutionContext* execution_context) {
// TODO(jkarlin): Do the same check for worker contexts.
- if (auto* document = Document::DynamicFrom(execution_context)) {
- LocalFrame* frame = document->GetFrame();
+ if (auto* window = DynamicTo<LocalDOMWindow>(execution_context)) {
+ LocalFrame* frame = window->GetFrame();
if (frame && frame->IsAdSubframe())
return true;
}
@@ -51,15 +53,22 @@ AdTracker* AdTracker::FromExecutionContext(
ExecutionContext* execution_context) {
if (!execution_context)
return nullptr;
- if (auto* document = Document::DynamicFrom(execution_context)) {
- LocalFrame* frame = document->GetFrame();
- if (frame) {
+ if (auto* window = DynamicTo<LocalDOMWindow>(execution_context)) {
+ if (LocalFrame* frame = window->GetFrame()) {
return frame->GetAdTracker();
}
}
return nullptr;
}
+// static
+bool AdTracker::IsAdScriptExecutingInDocument(Document* document,
+ StackType stack_type) {
+ AdTracker* ad_tracker =
+ document->GetFrame() ? document->GetFrame()->GetAdTracker() : nullptr;
+ return ad_tracker && ad_tracker->IsAdScriptInStack(stack_type);
+}
+
AdTracker::AdTracker(LocalFrame* local_root)
: local_root_(local_root),
async_stack_enabled_(
@@ -163,14 +172,26 @@ void AdTracker::Did(const probe::CallFunction& probe) {
DidExecuteScript();
}
-bool AdTracker::CalculateIfAdSubresource(ExecutionContext* execution_context,
- const ResourceRequest& request,
- ResourceType resource_type,
- bool known_ad) {
- // Check if the document loading the resource is an ad or if any executing
- // script is an ad.
- known_ad = known_ad || IsKnownAdExecutionContext(execution_context) ||
- IsAdScriptInStack(StackType::kBottomAndTop);
+bool AdTracker::CalculateIfAdSubresource(
+ ExecutionContext* execution_context,
+ const ResourceRequest& request,
+ ResourceType resource_type,
+ const FetchInitiatorInfo& initiator_info,
+ bool known_ad) {
+ // Check if the document loading the resource is an ad.
+ known_ad = known_ad || IsKnownAdExecutionContext(execution_context);
+
+ // We skip script checking for stylesheet-initiated resource requests as the
+ // stack may represent the cause of a style recalculation rather than the
+ // actual resources themselves. Instead, the ad bit is set according to the
+ // CSSParserContext when the request is made. See crbug.com/1051605.
+ if (initiator_info.name == fetch_initiator_type_names::kCSS ||
+ initiator_info.name == fetch_initiator_type_names::kUacss) {
+ return known_ad;
+ }
+
+ // Check if any executing script is an ad.
+ known_ad = known_ad || IsAdScriptInStack(StackType::kBottomAndTop);
// If it is a script marked as an ad and it's not in an ad context, append it
// to the known ad script set. We don't need to keep track of ad scripts in ad
diff --git a/chromium/third_party/blink/renderer/core/frame/ad_tracker.h b/chromium/third_party/blink/renderer/core/frame/ad_tracker.h
index 04e15e4221a..10be17661e4 100644
--- a/chromium/third_party/blink/renderer/core/frame/ad_tracker.h
+++ b/chromium/third_party/blink/renderer/core/frame/ad_tracker.h
@@ -10,6 +10,7 @@
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/probe/async_task_id.h"
#include "third_party/blink/renderer/platform/heap/member.h"
+#include "third_party/blink/renderer/platform/loader/fetch/fetch_initiator_info.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
#include "third_party/blink/renderer/platform/wtf/hash_map.h"
#include "third_party/blink/renderer/platform/wtf/hash_set.h"
@@ -39,6 +40,10 @@ class CORE_EXPORT AdTracker : public GarbageCollected<AdTracker> {
// Finds an AdTracker for a given ExecutionContext.
static AdTracker* FromExecutionContext(ExecutionContext*);
+ static bool IsAdScriptExecutingInDocument(
+ Document* document,
+ StackType stack_type = StackType::kBottomAndTop);
+
// Instrumenting methods.
// Called when a script module or script gets executed from native code.
void Will(const probe::ExecuteScript&);
@@ -49,15 +54,17 @@ class CORE_EXPORT AdTracker : public GarbageCollected<AdTracker> {
void Did(const probe::CallFunction&);
// Called when a subresource request is about to be sent or is redirected.
- // Returns true if:
- // - If the resource is loaded in an ad iframe
- // - If ad script is in the v8 stack
+ // Returns true if any of the following are true:
+ // - the resource is loaded in an ad iframe
// - |known_ad| is true
+ // - ad script is in the v8 stack and the resource was not requested by CSS.
// Virtual for testing.
- virtual bool CalculateIfAdSubresource(ExecutionContext* execution_context,
- const ResourceRequest& request,
- ResourceType resource_type,
- bool known_ad);
+ virtual bool CalculateIfAdSubresource(
+ ExecutionContext* execution_context,
+ const ResourceRequest& request,
+ ResourceType resource_type,
+ const FetchInitiatorInfo& initiator_info,
+ bool known_ad);
// Called when an async task is created. Check at this point for ad script on
// the stack and annotate the task if so.
diff --git a/chromium/third_party/blink/renderer/core/frame/ad_tracker_test.cc b/chromium/third_party/blink/renderer/core/frame/ad_tracker_test.cc
index 8f86535abab..1b8bcca9fd8 100644
--- a/chromium/third_party/blink/renderer/core/frame/ad_tracker_test.cc
+++ b/chromium/third_party/blink/renderer/core/frame/ad_tracker_test.cc
@@ -11,6 +11,7 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/renderer/core/dom/element_traversal.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/html/html_image_element.h"
#include "third_party/blink/renderer/core/probe/async_task_id.h"
@@ -30,6 +31,77 @@ const unsigned char kSmallGifData[] = {0x47, 0x49, 0x46, 0x38, 0x39, 0x61, 0x01,
0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01,
0x00, 0x00, 0x02, 0x00, 0x3b};
+const char kFrameURL[] = "https://example.com/frame.html";
+
+const char kVanillaFontURL[] = "https://example.com/font.woff2";
+const char kVanillaImageURL[] = "https://example.com/pixel.png";
+const char kVanillaScriptURL[] = "https://example.com/script.js";
+const char kVanillaStylesheetURL[] = "https://example.com/style.css";
+const char kVanillaImportedStylesheetURL[] = "https://example.com/imported.css";
+
+String ConvertToAdURL(String vanilla_url) {
+ return vanilla_url + "?ad=true";
+}
+
+// The pages include a div with class="test" to ensure the resources in the
+// stylesheet are loaded.
+const char kPageWithVanillaExternalStylesheet[] = R"HTML(
+ <head><link rel="stylesheet" href="style.css"></head>
+ <body><div class="test">Test</div></body>
+ )HTML";
+const char kPageWithAdExternalStylesheet[] = R"HTML(
+ <head><link rel="stylesheet" href="style.css?ad=true"></head>
+ <body><div class="test">Test</div></body>
+ )HTML";
+const char kPageWithVanillaScript[] = R"HTML(
+ <head><script defer src="script.js"></script></head>
+ <body><div class="test">Test</div></body>
+ )HTML";
+const char kPageWithAdScript[] = R"HTML(
+ <head><script defer src="script.js?ad=true"></script></head>
+ <body><div class="test">Test</div></body>
+ )HTML";
+const char kPageWithStyleTagLoadingVanillaResources[] = R"HTML(
+ <head><style>
+ @font-face {
+ font-family: "Vanilla";
+ src: url("font.woff2") format("woff2");
+ }
+ .test {
+ font-family: "Vanilla";
+ background-image: url("pixel.png");
+ }
+ </style></head>
+ <body><div class="test">Test</div></body>
+ )HTML";
+
+const char kScriptToCreateFrame[] = R"SCRIPT(
+ let iframe = document.createElement("iframe");
+ iframe.src = "frame.html";
+ document.body.appendChild(iframe);
+ )SCRIPT";
+
+const char kStylesheetWithVanillaResources[] = R"CSS(
+ @font-face {
+ font-family: "Vanilla";
+ src: url("font.woff2") format("woff2");
+ }
+ .test {
+ font-family: "Vanilla";
+ background-image: url("pixel.png");
+ }
+ )CSS";
+const char kStylesheetWithAdResources[] = R"CSS(
+ @font-face {
+ font-family: "Ad";
+ src: url("font.woff2?ad=true") format("woff2");
+ }
+ .test {
+ font-family: "Ad";
+ background-image: url("pixel.png?ad=true");
+ }
+ )CSS";
+
class TestAdTracker : public AdTracker {
public:
explicit TestAdTracker(LocalFrame* frame) : AdTracker(frame) {}
@@ -51,11 +123,25 @@ class TestAdTracker : public AdTracker {
return is_ad_.at(url);
}
+ bool UrlHasBeenRequested(const String& url) const {
+ return is_ad_.Contains(url);
+ }
+
void SetSimTest() { sim_test_ = true; }
+ void WaitForSubresource(const String& url) {
+ if (base::Contains(is_ad_, url)) {
+ return;
+ }
+ url_to_wait_for_ = url;
+ base::RunLoop run_loop;
+ quit_closure_ = run_loop.QuitClosure();
+ run_loop.Run();
+ }
+
protected:
String ScriptAtTopOfStack() override {
- if (sim_test_)
+ if (sim_test_ && !script_at_top_)
return AdTracker::ScriptAtTopOfStack();
return script_at_top_;
}
@@ -70,6 +156,7 @@ class TestAdTracker : public AdTracker {
bool CalculateIfAdSubresource(ExecutionContext* execution_context,
const ResourceRequest& resource_request,
ResourceType resource_type,
+ const FetchInitiatorInfo& initiator_info,
bool ad_request) override {
if (!ad_suffix_.IsEmpty() &&
resource_request.Url().GetString().EndsWith(ad_suffix_)) {
@@ -77,9 +164,15 @@ class TestAdTracker : public AdTracker {
}
ad_request = AdTracker::CalculateIfAdSubresource(
- execution_context, resource_request, resource_type, ad_request);
+ execution_context, resource_request, resource_type, initiator_info,
+ ad_request);
+
+ String resource_url = resource_request.Url().GetString();
+ is_ad_.insert(resource_url, ad_request);
- is_ad_.insert(resource_request.Url().GetString(), ad_request);
+ if (quit_closure_ && url_to_wait_for_ == resource_url) {
+ std::move(quit_closure_).Run();
+ }
return ad_request;
}
@@ -89,6 +182,9 @@ class TestAdTracker : public AdTracker {
Member<ExecutionContext> execution_context_;
String ad_suffix_;
bool sim_test_ = false;
+
+ base::OnceClosure quit_closure_;
+ String url_to_wait_for_;
};
} // namespace
@@ -105,13 +201,15 @@ class AdTrackerTest : public testing::Test {
if (ad_tracker_)
ad_tracker_->Shutdown();
ad_tracker_ = MakeGarbageCollected<TestAdTracker>(GetFrame());
- ad_tracker_->SetExecutionContext(
- page_holder_->GetDocument().ToExecutionContext());
+ ad_tracker_->SetExecutionContext(ExecutionContext());
}
void WillExecuteScript(const String& script_url) {
- ad_tracker_->WillExecuteScript(
- page_holder_->GetDocument().ToExecutionContext(), String(script_url));
+ ad_tracker_->WillExecuteScript(ExecutionContext(), String(script_url));
+ }
+
+ ExecutionContext* ExecutionContext() {
+ return page_holder_->GetFrame().DomWindow();
}
void DidExecuteScript() { ad_tracker_->DidExecuteScript(); }
@@ -127,8 +225,7 @@ class AdTrackerTest : public testing::Test {
}
void AppendToKnownAdScripts(const String& url) {
- ad_tracker_->AppendToKnownAdScripts(
- *page_holder_->GetDocument().ToExecutionContext(), url);
+ ad_tracker_->AppendToKnownAdScripts(*ExecutionContext(), url);
}
Persistent<TestAdTracker> ad_tracker_;
@@ -368,8 +465,9 @@ TEST_F(AdTrackerSimTest, ScriptLoadedWhileExecutingAdScript) {
vanilla_script.Complete("");
- EXPECT_TRUE(IsKnownAdScript(GetDocument().ToExecutionContext(), kAdUrl));
- EXPECT_TRUE(IsKnownAdScript(GetDocument().ToExecutionContext(), kVanillaUrl));
+ EXPECT_TRUE(IsKnownAdScript(GetDocument().GetExecutionContext(), kAdUrl));
+ EXPECT_TRUE(
+ IsKnownAdScript(GetDocument().GetExecutionContext(), kVanillaUrl));
EXPECT_TRUE(ad_tracker_->RequestWithUrlTaggedAsAd(kAdUrl));
EXPECT_TRUE(ad_tracker_->RequestWithUrlTaggedAsAd(kVanillaUrl));
}
@@ -398,8 +496,7 @@ TEST_F(AdTrackerSimTest, ScriptDetectedByContext) {
// Now run unknown script in the child's context. It should be considered an
// ad based on context alone.
- ad_tracker_->SetExecutionContext(
- child_frame->GetDocument()->ToExecutionContext());
+ ad_tracker_->SetExecutionContext(child_frame->DomWindow());
ad_tracker_->SetScriptAtTopOfStack("foo.js");
EXPECT_TRUE(
ad_tracker_->IsAdScriptInStack(AdTracker::StackType::kBottomAndTop));
@@ -534,7 +631,7 @@ TEST_F(AdTrackerSimTest, ImageLoadedWhileExecutingAdScriptAsyncEnabled) {
vanilla_image.Complete(gif);
- EXPECT_TRUE(IsKnownAdScript(GetDocument().ToExecutionContext(), kAdUrl));
+ EXPECT_TRUE(IsKnownAdScript(GetDocument().GetExecutionContext(), kAdUrl));
EXPECT_TRUE(ad_tracker_->RequestWithUrlTaggedAsAd(kAdUrl));
// Image loading is async, so we should catch this when async stacks are
@@ -588,7 +685,7 @@ TEST_F(AdTrackerSimTest, ImageLoadedWhileExecutingAdScriptAsyncDisabled) {
vanilla_image.Complete(gif);
- EXPECT_TRUE(IsKnownAdScript(GetDocument().ToExecutionContext(), kAdUrl));
+ EXPECT_TRUE(IsKnownAdScript(GetDocument().GetExecutionContext(), kAdUrl));
EXPECT_TRUE(ad_tracker_->RequestWithUrlTaggedAsAd(kAdUrl));
// Image loading is async, so we won't catch this when async stacks aren't
@@ -633,7 +730,7 @@ TEST_F(AdTrackerSimTest, DataURLImageLoadedWhileExecutingAdScriptAsyncEnabled) {
// Wait for script to run.
base::RunLoop().RunUntilIdle();
- EXPECT_TRUE(IsKnownAdScript(GetDocument().ToExecutionContext(), kAdUrl));
+ EXPECT_TRUE(IsKnownAdScript(GetDocument().GetExecutionContext(), kAdUrl));
EXPECT_TRUE(ad_tracker_->RequestWithUrlTaggedAsAd(kAdUrl));
// Walk through the DOM to get the image element.
@@ -673,7 +770,7 @@ TEST_F(AdTrackerSimTest, FrameLoadedWhileExecutingAdScript) {
vanilla_page.Complete("<img src=vanilla_img.jpg></img>");
vanilla_image.Complete("");
- EXPECT_TRUE(IsKnownAdScript(GetDocument().ToExecutionContext(), kAdUrl));
+ EXPECT_TRUE(IsKnownAdScript(GetDocument().GetExecutionContext(), kAdUrl));
EXPECT_TRUE(ad_tracker_->RequestWithUrlTaggedAsAd(kAdUrl));
Frame* child_frame = GetDocument().GetFrame()->Tree().FirstChild();
EXPECT_TRUE(To<LocalFrame>(child_frame)->IsAdSubframe());
@@ -715,10 +812,10 @@ TEST_F(AdTrackerSimTest, Contexts) {
Frame* subframe = GetDocument().GetFrame()->Tree().FirstChild();
auto* local_subframe = To<LocalFrame>(subframe);
EXPECT_TRUE(
- IsKnownAdScript(local_subframe->GetDocument()->ToExecutionContext(),
+ IsKnownAdScript(local_subframe->GetDocument()->GetExecutionContext(),
String("https://example.com/library.js")));
- EXPECT_FALSE(IsKnownAdScript(GetDocument().ToExecutionContext(),
+ EXPECT_FALSE(IsKnownAdScript(GetDocument().GetExecutionContext(),
String("https://example.com/library.js")));
}
@@ -772,6 +869,421 @@ TEST_F(AdTrackerSimTest, SameOriginDocWrittenSubframeFromAdScript) {
EXPECT_TRUE(local_subframe->IsAdSubframe());
}
+// This test class allows easy running of tests that only differ by whether
+// one resource (or a set of resources) is vanilla or an ad.
+class AdTrackerVanillaOrAdSimTest : public AdTrackerSimTest,
+ public ::testing::WithParamInterface<bool> {
+ public:
+ bool IsAdRun() { return GetParam(); }
+
+ String FlipURLOnAdRun(String vanilla_url) {
+ return IsAdRun() ? ConvertToAdURL(vanilla_url) : vanilla_url;
+ }
+};
+
+TEST_P(AdTrackerVanillaOrAdSimTest, VanillaExternalStylesheetLoadsResources) {
+ String font_url = FlipURLOnAdRun(kVanillaFontURL);
+ String image_url = FlipURLOnAdRun(kVanillaImageURL);
+ SimSubresourceRequest stylesheet(kVanillaStylesheetURL, "text/css");
+ SimSubresourceRequest font(font_url, "font/woff2");
+ SimSubresourceRequest image(image_url, "image/png");
+
+ ad_tracker_->SetAdSuffix("ad=true");
+
+ main_resource_->Complete(kPageWithVanillaExternalStylesheet);
+ stylesheet.Complete(IsAdRun() ? kStylesheetWithAdResources
+ : kStylesheetWithVanillaResources);
+
+ // Wait for stylesheet to fetch resources.
+ ad_tracker_->WaitForSubresource(font_url);
+ ad_tracker_->WaitForSubresource(image_url);
+
+ font.Complete();
+ image.Complete();
+
+ EXPECT_FALSE(ad_tracker_->RequestWithUrlTaggedAsAd(kVanillaStylesheetURL));
+ EXPECT_EQ(ad_tracker_->RequestWithUrlTaggedAsAd(font_url), IsAdRun());
+ EXPECT_EQ(ad_tracker_->RequestWithUrlTaggedAsAd(image_url), IsAdRun());
+}
+
+TEST_P(AdTrackerVanillaOrAdSimTest, AdExternalStylesheetLoadsResources) {
+ String font_url = FlipURLOnAdRun(kVanillaFontURL);
+ String image_url = FlipURLOnAdRun(kVanillaImageURL);
+ String ad_stylesheet_url = ConvertToAdURL(kVanillaStylesheetURL);
+ SimSubresourceRequest stylesheet(ad_stylesheet_url, "text/css");
+ SimSubresourceRequest font(font_url, "font/woff2");
+ SimSubresourceRequest image(image_url, "image/png");
+
+ ad_tracker_->SetAdSuffix("ad=true");
+
+ main_resource_->Complete(kPageWithAdExternalStylesheet);
+ stylesheet.Complete(IsAdRun() ? kStylesheetWithAdResources
+ : kStylesheetWithVanillaResources);
+
+ // Wait for stylesheet to fetch resources.
+ ad_tracker_->WaitForSubresource(font_url);
+ ad_tracker_->WaitForSubresource(image_url);
+
+ font.Complete();
+ image.Complete();
+
+ EXPECT_TRUE(ad_tracker_->RequestWithUrlTaggedAsAd(ad_stylesheet_url));
+ EXPECT_TRUE(ad_tracker_->RequestWithUrlTaggedAsAd(font_url));
+ EXPECT_TRUE(ad_tracker_->RequestWithUrlTaggedAsAd(image_url));
+}
+
+TEST_P(AdTrackerVanillaOrAdSimTest, LinkRelStylesheetAddedByScript) {
+ String script_url = FlipURLOnAdRun(kVanillaScriptURL);
+ SimSubresourceRequest script(script_url, "text/javascript");
+ SimSubresourceRequest stylesheet(kVanillaStylesheetURL, "text/css");
+ SimSubresourceRequest font(kVanillaFontURL, "font/woff2");
+ SimSubresourceRequest image(kVanillaImageURL, "image/png");
+
+ ad_tracker_->SetAdSuffix("ad=true");
+
+ main_resource_->Complete(IsAdRun() ? kPageWithAdScript
+ : kPageWithVanillaScript);
+ script.Complete(R"SCRIPT(
+ let link = document.createElement("link");
+ link.rel = "stylesheet";
+ link.href = "style.css";
+ document.head.appendChild(link);
+ )SCRIPT");
+
+ // Wait for script to run.
+ ad_tracker_->WaitForSubresource(kVanillaStylesheetURL);
+
+ stylesheet.Complete(kStylesheetWithVanillaResources);
+
+ // Wait for stylesheet to fetch resources.
+ ad_tracker_->WaitForSubresource(kVanillaFontURL);
+ ad_tracker_->WaitForSubresource(kVanillaImageURL);
+
+ font.Complete();
+ image.Complete();
+
+ EXPECT_EQ(ad_tracker_->RequestWithUrlTaggedAsAd(script_url), IsAdRun());
+ EXPECT_EQ(ad_tracker_->RequestWithUrlTaggedAsAd(kVanillaStylesheetURL),
+ IsAdRun());
+ EXPECT_EQ(ad_tracker_->RequestWithUrlTaggedAsAd(kVanillaFontURL), IsAdRun());
+ EXPECT_EQ(ad_tracker_->RequestWithUrlTaggedAsAd(kVanillaImageURL), IsAdRun());
+}
+
+TEST_P(AdTrackerVanillaOrAdSimTest, ExternalStylesheetInFrame) {
+ String script_url = FlipURLOnAdRun(kVanillaScriptURL);
+ SimRequest frame(kFrameURL, "text/html");
+ SimSubresourceRequest script(script_url, "text/javascript");
+ SimSubresourceRequest stylesheet(kVanillaStylesheetURL, "text/css");
+ SimSubresourceRequest font(kVanillaFontURL, "font/woff2");
+ SimSubresourceRequest image(kVanillaImageURL, "image/png");
+
+ ad_tracker_->SetAdSuffix("ad=true");
+
+ main_resource_->Complete(IsAdRun() ? kPageWithAdScript
+ : kPageWithVanillaScript);
+ script.Complete(kScriptToCreateFrame);
+ frame.Complete(kPageWithVanillaExternalStylesheet);
+ stylesheet.Complete(kStylesheetWithVanillaResources);
+
+ // Wait for stylesheet to fetch resources.
+ ad_tracker_->WaitForSubresource(kVanillaFontURL);
+ ad_tracker_->WaitForSubresource(kVanillaImageURL);
+
+ font.Complete();
+ image.Complete();
+
+ Frame* subframe = GetDocument().GetFrame()->Tree().FirstChild();
+ auto* local_subframe = To<LocalFrame>(subframe);
+ EXPECT_EQ(local_subframe->IsAdSubframe(), IsAdRun());
+
+ EXPECT_EQ(ad_tracker_->RequestWithUrlTaggedAsAd(script_url), IsAdRun());
+ EXPECT_EQ(ad_tracker_->RequestWithUrlTaggedAsAd(kVanillaStylesheetURL),
+ IsAdRun());
+ EXPECT_EQ(ad_tracker_->RequestWithUrlTaggedAsAd(kVanillaFontURL), IsAdRun());
+ EXPECT_EQ(ad_tracker_->RequestWithUrlTaggedAsAd(kVanillaImageURL), IsAdRun());
+}
+
+// Note that we skip fonts as at rules aren't valid in inline CSS.
+TEST_P(AdTrackerVanillaOrAdSimTest, InlineCSSSetByScript) {
+ String script_url = FlipURLOnAdRun(kVanillaScriptURL);
+ SimSubresourceRequest script(script_url, "text/javascript");
+ SimSubresourceRequest image(kVanillaImageURL, "image/png");
+
+ ad_tracker_->SetAdSuffix("ad=true");
+
+ main_resource_->Complete(IsAdRun() ? kPageWithAdScript
+ : kPageWithVanillaScript);
+ script.Complete(R"SCRIPT(
+ let div = document.getElementsByClassName("test")[0];
+ div.style = "background-image: url('pixel.png');";
+ )SCRIPT");
+
+ ad_tracker_->WaitForSubresource(kVanillaImageURL);
+
+ image.Complete();
+
+ EXPECT_EQ(ad_tracker_->RequestWithUrlTaggedAsAd(script_url), IsAdRun());
+ EXPECT_EQ(ad_tracker_->RequestWithUrlTaggedAsAd(kVanillaImageURL), IsAdRun());
+}
+
+TEST_F(AdTrackerSimTest, StyleTagInMainframe) {
+ SimSubresourceRequest font(kVanillaFontURL, "font/woff2");
+ SimSubresourceRequest image(kVanillaImageURL, "image/png");
+
+ ad_tracker_->SetAdSuffix("ad=true");
+
+ main_resource_->Complete(kPageWithStyleTagLoadingVanillaResources);
+
+ // Wait for stylesheet to fetch resources.
+ ad_tracker_->WaitForSubresource(kVanillaFontURL);
+ ad_tracker_->WaitForSubresource(kVanillaImageURL);
+
+ font.Complete();
+ image.Complete();
+
+ EXPECT_FALSE(ad_tracker_->RequestWithUrlTaggedAsAd(kVanillaFontURL));
+ EXPECT_FALSE(ad_tracker_->RequestWithUrlTaggedAsAd(kVanillaImageURL));
+}
+
+// This verifies that style tag resources in ad frames are correctly tagged
+// according to the heuristic that all requests from an ad frame should also be
+// tagged as ads.
+TEST_P(AdTrackerVanillaOrAdSimTest, StyleTagInSubframe) {
+ String script_url = FlipURLOnAdRun(kVanillaScriptURL);
+ SimRequest frame(kFrameURL, "text/html");
+ SimSubresourceRequest script(script_url, "text/javascript");
+ SimSubresourceRequest font(kVanillaFontURL, "font/woff2");
+ SimSubresourceRequest image(kVanillaImageURL, "image/png");
+
+ ad_tracker_->SetAdSuffix("ad=true");
+
+ main_resource_->Complete(IsAdRun() ? kPageWithAdScript
+ : kPageWithVanillaScript);
+ script.Complete(kScriptToCreateFrame);
+ frame.Complete(kPageWithStyleTagLoadingVanillaResources);
+
+ // Wait for stylesheet to fetch resources.
+ ad_tracker_->WaitForSubresource(kVanillaFontURL);
+ ad_tracker_->WaitForSubresource(kVanillaImageURL);
+
+ font.Complete();
+ image.Complete();
+
+ Frame* subframe = GetDocument().GetFrame()->Tree().FirstChild();
+ auto* local_subframe = To<LocalFrame>(subframe);
+ EXPECT_EQ(local_subframe->IsAdSubframe(), IsAdRun());
+
+ EXPECT_EQ(ad_tracker_->RequestWithUrlTaggedAsAd(script_url), IsAdRun());
+ EXPECT_EQ(ad_tracker_->RequestWithUrlTaggedAsAd(kVanillaFontURL), IsAdRun());
+ EXPECT_EQ(ad_tracker_->RequestWithUrlTaggedAsAd(kVanillaImageURL), IsAdRun());
+}
+
+TEST_P(AdTrackerVanillaOrAdSimTest, StyleTagAddedByScript) {
+ String script_url = FlipURLOnAdRun(kVanillaScriptURL);
+ SimSubresourceRequest script(script_url, "text/javascript");
+ SimSubresourceRequest font(kVanillaFontURL, "font/woff2");
+ SimSubresourceRequest image(kVanillaImageURL, "image/png");
+
+ ad_tracker_->SetAdSuffix("ad=true");
+
+ main_resource_->Complete(IsAdRun() ? kPageWithAdScript
+ : kPageWithVanillaScript);
+ script.Complete(String::Format(
+ R"SCRIPT(
+ let style = document.createElement("style");
+ let text = document.createTextNode(`%s`);
+ style.appendChild(text);
+ document.head.appendChild(style);
+ )SCRIPT",
+ kStylesheetWithVanillaResources));
+
+ // Wait for stylesheet to fetch resources.
+ ad_tracker_->WaitForSubresource(kVanillaFontURL);
+ ad_tracker_->WaitForSubresource(kVanillaImageURL);
+
+ font.Complete();
+ image.Complete();
+
+ EXPECT_EQ(ad_tracker_->RequestWithUrlTaggedAsAd(script_url), IsAdRun());
+ EXPECT_EQ(ad_tracker_->RequestWithUrlTaggedAsAd(kVanillaFontURL), IsAdRun());
+ EXPECT_EQ(ad_tracker_->RequestWithUrlTaggedAsAd(kVanillaImageURL), IsAdRun());
+}
+
+TEST_P(AdTrackerVanillaOrAdSimTest, VanillaImportInStylesheet) {
+ String stylesheet_url = FlipURLOnAdRun(kVanillaStylesheetURL);
+ SimSubresourceRequest stylesheet(stylesheet_url, "text/css");
+ SimSubresourceRequest imported_stylesheet(kVanillaImportedStylesheetURL,
+ "text/css");
+ SimSubresourceRequest font(kVanillaFontURL, "font/woff2");
+ SimSubresourceRequest image(kVanillaImageURL, "image/png");
+
+ ad_tracker_->SetAdSuffix("ad=true");
+
+ main_resource_->Complete(IsAdRun() ? kPageWithAdExternalStylesheet
+ : kPageWithVanillaExternalStylesheet);
+ stylesheet.Complete(R"CSS(
+ @import url(imported.css);
+ )CSS");
+ imported_stylesheet.Complete(kStylesheetWithVanillaResources);
+
+ // Wait for stylesheets to fetch resources.
+ ad_tracker_->WaitForSubresource(kVanillaFontURL);
+ ad_tracker_->WaitForSubresource(kVanillaImageURL);
+
+ font.Complete();
+ image.Complete();
+
+ EXPECT_EQ(ad_tracker_->RequestWithUrlTaggedAsAd(stylesheet_url), IsAdRun());
+ EXPECT_EQ(
+ ad_tracker_->RequestWithUrlTaggedAsAd(kVanillaImportedStylesheetURL),
+ IsAdRun());
+ EXPECT_EQ(ad_tracker_->RequestWithUrlTaggedAsAd(kVanillaFontURL), IsAdRun());
+ EXPECT_EQ(ad_tracker_->RequestWithUrlTaggedAsAd(kVanillaImageURL), IsAdRun());
+}
+
+TEST_P(AdTrackerVanillaOrAdSimTest, AdImportInStylesheet) {
+ String stylesheet_url = FlipURLOnAdRun(kVanillaStylesheetURL);
+ String ad_imported_stylesheet_url =
+ ConvertToAdURL(kVanillaImportedStylesheetURL);
+ SimSubresourceRequest stylesheet(stylesheet_url, "text/css");
+ SimSubresourceRequest imported_stylesheet(ad_imported_stylesheet_url,
+ "text/css");
+ SimSubresourceRequest font(kVanillaFontURL, "font/woff2");
+ SimSubresourceRequest image(kVanillaImageURL, "image/png");
+
+ ad_tracker_->SetAdSuffix("ad=true");
+
+ main_resource_->Complete(IsAdRun() ? kPageWithAdExternalStylesheet
+ : kPageWithVanillaExternalStylesheet);
+ stylesheet.Complete(R"CSS(
+ @import url(imported.css?ad=true);
+ )CSS");
+ imported_stylesheet.Complete(kStylesheetWithVanillaResources);
+
+ // Wait for stylesheets to fetch resources.
+ ad_tracker_->WaitForSubresource(kVanillaFontURL);
+ ad_tracker_->WaitForSubresource(kVanillaImageURL);
+
+ font.Complete();
+ image.Complete();
+
+ EXPECT_EQ(ad_tracker_->RequestWithUrlTaggedAsAd(stylesheet_url), IsAdRun());
+ EXPECT_TRUE(
+ ad_tracker_->RequestWithUrlTaggedAsAd(ad_imported_stylesheet_url));
+ EXPECT_TRUE(ad_tracker_->RequestWithUrlTaggedAsAd(kVanillaFontURL));
+ EXPECT_TRUE(ad_tracker_->RequestWithUrlTaggedAsAd(kVanillaImageURL));
+}
+
+TEST_P(AdTrackerVanillaOrAdSimTest, ImageSetInStylesheet) {
+ String stylesheet_url = FlipURLOnAdRun(kVanillaStylesheetURL);
+ SimSubresourceRequest stylesheet(stylesheet_url, "text/css");
+ SimSubresourceRequest image(kVanillaImageURL, "image/png");
+
+ ad_tracker_->SetAdSuffix("ad=true");
+
+ main_resource_->Complete(IsAdRun() ? kPageWithAdExternalStylesheet
+ : kPageWithVanillaExternalStylesheet);
+
+ // The image with the lowest scale factor that is still larger than the
+ // device's scale factor is used.
+ stylesheet.Complete(R"CSS(
+ .test {
+ background-image: -webkit-image-set( url("pixel.png") 100x,
+ url("too_high.png") 999x);
+ }
+ )CSS");
+
+ // Wait for stylesheet to fetch resource.
+ ad_tracker_->WaitForSubresource(kVanillaImageURL);
+
+ image.Complete();
+
+ EXPECT_EQ(ad_tracker_->RequestWithUrlTaggedAsAd(stylesheet_url), IsAdRun());
+ EXPECT_EQ(ad_tracker_->RequestWithUrlTaggedAsAd(kVanillaImageURL), IsAdRun());
+}
+
+TEST_P(AdTrackerVanillaOrAdSimTest, ConstructableCSSCreatedByScript) {
+ String script_url = FlipURLOnAdRun(kVanillaScriptURL);
+ SimSubresourceRequest script(script_url, "text/javascript");
+ SimSubresourceRequest font(kVanillaFontURL, "font/woff2");
+ SimSubresourceRequest image(kVanillaImageURL, "image/png");
+
+ ad_tracker_->SetAdSuffix("ad=true");
+
+ main_resource_->Complete(IsAdRun() ? kPageWithAdScript
+ : kPageWithVanillaScript);
+ script.Complete(R"SCRIPT(
+ const sheet = new CSSStyleSheet();
+ sheet.insertRule(`
+ @font-face {
+ font-family: "Vanilla";
+ src: url("font.woff2") format("woff2");
+ }`);
+ sheet.insertRule(`
+ .test {
+ font-family: "Vanilla";
+ background-image: url("pixel.png");
+ }`);
+ document.adoptedStyleSheets = [sheet];
+ )SCRIPT");
+
+ // Wait for stylesheet to fetch resources.
+ ad_tracker_->WaitForSubresource(kVanillaFontURL);
+ ad_tracker_->WaitForSubresource(kVanillaImageURL);
+
+ font.Complete();
+ image.Complete();
+
+ EXPECT_EQ(ad_tracker_->RequestWithUrlTaggedAsAd(script_url), IsAdRun());
+ EXPECT_EQ(ad_tracker_->RequestWithUrlTaggedAsAd(kVanillaFontURL), IsAdRun());
+ EXPECT_EQ(ad_tracker_->RequestWithUrlTaggedAsAd(kVanillaImageURL), IsAdRun());
+}
+
+// Vanilla resources loaded due to an ad's script's style recalculation
+// shouldn't be tagged.
+TEST_F(AdTrackerSimTest, StyleRecalcCausedByAdScript) {
+ String ad_script_url = ConvertToAdURL(kVanillaScriptURL);
+ SimSubresourceRequest script(ad_script_url, "text/javascript");
+ SimSubresourceRequest stylesheet(kVanillaStylesheetURL, "text/css");
+ SimSubresourceRequest font(kVanillaFontURL, "font/woff2");
+ SimSubresourceRequest image(kVanillaImageURL, "image/png");
+
+ ad_tracker_->SetAdSuffix("ad=true");
+
+ main_resource_->Complete(R"HTML(
+ <head><link rel="stylesheet" href="style.css">
+ <script async src="script.js?ad=true"></script></head>
+ <body><div>Test</div></body>
+ )HTML");
+ stylesheet.Complete(kStylesheetWithVanillaResources);
+
+ base::RunLoop().RunUntilIdle();
+ EXPECT_FALSE(ad_tracker_->UrlHasBeenRequested(kVanillaFontURL));
+ EXPECT_FALSE(ad_tracker_->UrlHasBeenRequested(kVanillaImageURL));
+
+ // We override these to ensure the ad script appears on top of the stack when
+ // the requests are made.
+ ad_tracker_->SetExecutionContext(GetDocument().GetExecutionContext());
+ ad_tracker_->SetScriptAtTopOfStack(ad_script_url);
+
+ script.Complete(R"SCRIPT(
+ let div = document.getElementsByTagName("div")[0];
+ div.className = "test";
+ )SCRIPT");
+
+ // Wait for stylesheets to fetch resources.
+ ad_tracker_->WaitForSubresource(kVanillaFontURL);
+ ad_tracker_->WaitForSubresource(kVanillaImageURL);
+
+ font.Complete();
+ image.Complete();
+
+ EXPECT_TRUE(ad_tracker_->RequestWithUrlTaggedAsAd(ad_script_url));
+ EXPECT_FALSE(ad_tracker_->RequestWithUrlTaggedAsAd(kVanillaStylesheetURL));
+ EXPECT_FALSE(ad_tracker_->RequestWithUrlTaggedAsAd(kVanillaFontURL));
+ EXPECT_FALSE(ad_tracker_->RequestWithUrlTaggedAsAd(kVanillaImageURL));
+}
+
class AdTrackerDisabledSimTest : public SimTest,
private ScopedAdTaggingForTest {
protected:
@@ -793,4 +1305,8 @@ TEST_F(AdTrackerDisabledSimTest, VerifyAdTrackingDisabled) {
EXPECT_FALSE(GetDocument().GetFrame()->IsAdSubframe());
}
+INSTANTIATE_TEST_SUITE_P(All,
+ AdTrackerVanillaOrAdSimTest,
+ ::testing::Values(true, false));
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/frame/bar_prop.cc b/chromium/third_party/blink/renderer/core/frame/bar_prop.cc
index 85dc13c2646..e1c3b2ba5d1 100644
--- a/chromium/third_party/blink/renderer/core/frame/bar_prop.cc
+++ b/chromium/third_party/blink/renderer/core/frame/bar_prop.cc
@@ -35,11 +35,11 @@
namespace blink {
BarProp::BarProp(LocalFrame* frame, Type type)
- : DOMWindowClient(frame), type_(type) {}
+ : ExecutionContextClient(frame), type_(type) {}
void BarProp::Trace(Visitor* visitor) {
ScriptWrappable::Trace(visitor);
- DOMWindowClient::Trace(visitor);
+ ExecutionContextClient::Trace(visitor);
}
bool BarProp::visible() const {
diff --git a/chromium/third_party/blink/renderer/core/frame/bar_prop.h b/chromium/third_party/blink/renderer/core/frame/bar_prop.h
index 5f1d7148259..8ddf97912d0 100644
--- a/chromium/third_party/blink/renderer/core/frame/bar_prop.h
+++ b/chromium/third_party/blink/renderer/core/frame/bar_prop.h
@@ -37,7 +37,7 @@ namespace blink {
class LocalFrame;
-class BarProp final : public ScriptWrappable, public DOMWindowClient {
+class BarProp final : public ScriptWrappable, public ExecutionContextClient {
DEFINE_WRAPPERTYPEINFO();
USING_GARBAGE_COLLECTED_MIXIN(BarProp);
diff --git a/chromium/third_party/blink/renderer/core/frame/browser_controls_test.cc b/chromium/third_party/blink/renderer/core/frame/browser_controls_test.cc
index a42014e9d50..5bb535b1c29 100644
--- a/chromium/third_party/blink/renderer/core/frame/browser_controls_test.cc
+++ b/chromium/third_party/blink/renderer/core/frame/browser_controls_test.cc
@@ -32,7 +32,7 @@
#include "build/build_config.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/platform/web_coalesced_input_event.h"
+#include "third_party/blink/public/common/input/web_coalesced_input_event.h"
#include "third_party/blink/public/platform/web_url_loader_mock_factory.h"
#include "third_party/blink/public/web/web_element.h"
#include "third_party/blink/public/web/web_settings.h"
@@ -113,23 +113,23 @@ class BrowserControlsTest : public testing::Test,
WebInputEvent::GetStaticTimeStampForTests(),
WebGestureDevice::kTouchscreen);
event.SetPositionInWidget(FloatPoint(100, 100));
- if (type == WebInputEvent::kGestureScrollUpdate) {
+ if (type == WebInputEvent::Type::kGestureScrollUpdate) {
event.data.scroll_update.delta_x = delta_x;
event.data.scroll_update.delta_y = delta_y;
- } else if (type == WebInputEvent::kGestureScrollBegin) {
+ } else if (type == WebInputEvent::Type::kGestureScrollBegin) {
event.data.scroll_begin.delta_x_hint = delta_x;
event.data.scroll_begin.delta_y_hint = delta_y;
}
- return WebCoalescedInputEvent(event);
+ return WebCoalescedInputEvent(event, ui::LatencyInfo());
}
void VerticalScroll(float delta_y) {
GetWebView()->MainFrameWidget()->HandleInputEvent(
- GenerateEvent(WebInputEvent::kGestureScrollBegin, 0, delta_y));
+ GenerateEvent(WebInputEvent::Type::kGestureScrollBegin, 0, delta_y));
GetWebView()->MainFrameWidget()->HandleInputEvent(
- GenerateEvent(WebInputEvent::kGestureScrollUpdate, 0, delta_y));
+ GenerateEvent(WebInputEvent::Type::kGestureScrollUpdate, 0, delta_y));
GetWebView()->MainFrameWidget()->HandleInputEvent(
- GenerateEvent(WebInputEvent::kGestureScrollEnd));
+ GenerateEvent(WebInputEvent::Type::kGestureScrollEnd));
}
Element* GetElementById(const WebString& id) {
@@ -182,23 +182,23 @@ class BrowserControlsSimTest : public SimTest {
WebInputEvent::GetStaticTimeStampForTests(),
WebGestureDevice::kTouchscreen);
event.SetPositionInWidget(FloatPoint(100, 100));
- if (type == WebInputEvent::kGestureScrollUpdate) {
+ if (type == WebInputEvent::Type::kGestureScrollUpdate) {
event.data.scroll_update.delta_x = delta_x;
event.data.scroll_update.delta_y = delta_y;
- } else if (type == WebInputEvent::kGestureScrollBegin) {
+ } else if (type == WebInputEvent::Type::kGestureScrollBegin) {
event.data.scroll_begin.delta_x_hint = delta_x;
event.data.scroll_begin.delta_y_hint = delta_y;
}
- return WebCoalescedInputEvent(event);
+ return WebCoalescedInputEvent(event, ui::LatencyInfo());
}
void VerticalScroll(float delta_y) {
WebView().MainFrameWidget()->HandleInputEvent(
- GenerateEvent(WebInputEvent::kGestureScrollBegin, 0, delta_y));
+ GenerateEvent(WebInputEvent::Type::kGestureScrollBegin, 0, delta_y));
WebView().MainFrameWidget()->HandleInputEvent(
- GenerateEvent(WebInputEvent::kGestureScrollUpdate, 0, delta_y));
+ GenerateEvent(WebInputEvent::Type::kGestureScrollUpdate, 0, delta_y));
WebView().MainFrameWidget()->HandleInputEvent(
- GenerateEvent(WebInputEvent::kGestureScrollEnd));
+ GenerateEvent(WebInputEvent::Type::kGestureScrollEnd));
}
};
@@ -220,12 +220,12 @@ TEST_F(BrowserControlsTest, MAYBE(HideOnScrollDown)) {
web_view->GetBrowserControls().SetShownRatio(1, 1);
web_view->MainFrameWidget()->HandleInputEvent(
- GenerateEvent(WebInputEvent::kGestureScrollBegin));
+ GenerateEvent(WebInputEvent::Type::kGestureScrollBegin));
EXPECT_FLOAT_EQ(50.f, web_view->GetBrowserControls().ContentOffset());
// Browser controls should be scrolled partially and page should not scroll.
web_view->MainFrameWidget()->HandleInputEvent(
- GenerateEvent(WebInputEvent::kGestureScrollUpdate, 0, -25.f));
+ GenerateEvent(WebInputEvent::Type::kGestureScrollUpdate, 0, -25.f));
EXPECT_FLOAT_EQ(25.f, web_view->GetBrowserControls().ContentOffset());
EXPECT_EQ(ScrollOffset(0, 0),
GetFrame()->View()->LayoutViewport()->GetScrollOffset());
@@ -234,14 +234,14 @@ TEST_F(BrowserControlsTest, MAYBE(HideOnScrollDown)) {
// should be
// consumed by the page.
web_view->MainFrameWidget()->HandleInputEvent(
- GenerateEvent(WebInputEvent::kGestureScrollUpdate, 0, -40.f));
+ GenerateEvent(WebInputEvent::Type::kGestureScrollUpdate, 0, -40.f));
EXPECT_FLOAT_EQ(0.f, web_view->GetBrowserControls().ContentOffset());
EXPECT_EQ(ScrollOffset(0, 15),
GetFrame()->View()->LayoutViewport()->GetScrollOffset());
// Only page should consume scroll
web_view->MainFrameWidget()->HandleInputEvent(
- GenerateEvent(WebInputEvent::kGestureScrollUpdate, 0, -20.f));
+ GenerateEvent(WebInputEvent::Type::kGestureScrollUpdate, 0, -20.f));
EXPECT_FLOAT_EQ(0.f, web_view->GetBrowserControls().ContentOffset());
EXPECT_EQ(ScrollOffset(0, 35),
GetFrame()->View()->LayoutViewport()->GetScrollOffset());
@@ -256,13 +256,13 @@ TEST_F(BrowserControlsTest, MAYBE(HideBottomControlsOnScrollDown)) {
web_view->GetBrowserControls().SetShownRatio(0.0, 1);
web_view->MainFrameWidget()->HandleInputEvent(
- GenerateEvent(WebInputEvent::kGestureScrollBegin));
+ GenerateEvent(WebInputEvent::Type::kGestureScrollBegin));
EXPECT_FLOAT_EQ(0.f, web_view->GetBrowserControls().ContentOffset());
// Bottom controls and page content should both scroll and there should be
// no content offset.
web_view->MainFrameWidget()->HandleInputEvent(
- GenerateEvent(WebInputEvent::kGestureScrollUpdate, 0, -25.f));
+ GenerateEvent(WebInputEvent::Type::kGestureScrollUpdate, 0, -25.f));
EXPECT_FLOAT_EQ(0.f, web_view->GetBrowserControls().ContentOffset());
EXPECT_FLOAT_EQ(0.5f, web_view->GetBrowserControls().BottomShownRatio());
EXPECT_EQ(ScrollOffset(0, 25.f),
@@ -270,11 +270,11 @@ TEST_F(BrowserControlsTest, MAYBE(HideBottomControlsOnScrollDown)) {
// Browser controls should become completely hidden.
web_view->MainFrameWidget()->HandleInputEvent(
- GenerateEvent(WebInputEvent::kGestureScrollBegin));
+ GenerateEvent(WebInputEvent::Type::kGestureScrollBegin));
web_view->MainFrameWidget()->HandleInputEvent(
- GenerateEvent(WebInputEvent::kGestureScrollUpdate, 0, -40.f));
+ GenerateEvent(WebInputEvent::Type::kGestureScrollUpdate, 0, -40.f));
web_view->MainFrameWidget()->HandleInputEvent(
- GenerateEvent(WebInputEvent::kGestureScrollEnd));
+ GenerateEvent(WebInputEvent::Type::kGestureScrollEnd));
EXPECT_FLOAT_EQ(0.f, web_view->GetBrowserControls().ContentOffset());
EXPECT_FLOAT_EQ(0.f, web_view->GetBrowserControls().BottomShownRatio());
EXPECT_EQ(ScrollOffset(0, 65.f),
@@ -290,17 +290,17 @@ TEST_F(BrowserControlsTest, MAYBE(ShowOnScrollUp)) {
web_view->GetBrowserControls().SetShownRatio(0, 0);
web_view->MainFrameWidget()->HandleInputEvent(
- GenerateEvent(WebInputEvent::kGestureScrollBegin));
+ GenerateEvent(WebInputEvent::Type::kGestureScrollBegin));
EXPECT_FLOAT_EQ(0.f, web_view->GetBrowserControls().ContentOffset());
web_view->MainFrameWidget()->HandleInputEvent(
- GenerateEvent(WebInputEvent::kGestureScrollUpdate, 0, 10.f));
+ GenerateEvent(WebInputEvent::Type::kGestureScrollUpdate, 0, 10.f));
EXPECT_FLOAT_EQ(10.f, web_view->GetBrowserControls().ContentOffset());
EXPECT_EQ(ScrollOffset(0, 0),
GetFrame()->View()->LayoutViewport()->GetScrollOffset());
web_view->MainFrameWidget()->HandleInputEvent(
- GenerateEvent(WebInputEvent::kGestureScrollUpdate, 0, 50.f));
+ GenerateEvent(WebInputEvent::Type::kGestureScrollUpdate, 0, 50.f));
EXPECT_FLOAT_EQ(50.f, web_view->GetBrowserControls().ContentOffset());
EXPECT_EQ(ScrollOffset(0, 0),
GetFrame()->View()->LayoutViewport()->GetScrollOffset());
@@ -315,25 +315,25 @@ TEST_F(BrowserControlsTest, MAYBE(ShowBottomControlsOnScrollUp)) {
web_view->GetBrowserControls().SetShownRatio(0, 0);
web_view->MainFrameWidget()->HandleInputEvent(
- GenerateEvent(WebInputEvent::kGestureScrollBegin));
+ GenerateEvent(WebInputEvent::Type::kGestureScrollBegin));
EXPECT_FLOAT_EQ(0.f, web_view->GetBrowserControls().ContentOffset());
// Allow some space to scroll up.
web_view->MainFrameWidget()->HandleInputEvent(
- GenerateEvent(WebInputEvent::kGestureScrollBegin));
+ GenerateEvent(WebInputEvent::Type::kGestureScrollBegin));
web_view->MainFrameWidget()->HandleInputEvent(
- GenerateEvent(WebInputEvent::kGestureScrollUpdate, 0, -50.f));
+ GenerateEvent(WebInputEvent::Type::kGestureScrollUpdate, 0, -50.f));
web_view->MainFrameWidget()->HandleInputEvent(
- GenerateEvent(WebInputEvent::kGestureScrollEnd));
+ GenerateEvent(WebInputEvent::Type::kGestureScrollEnd));
web_view->MainFrameWidget()->HandleInputEvent(
- GenerateEvent(WebInputEvent::kGestureScrollBegin));
+ GenerateEvent(WebInputEvent::Type::kGestureScrollBegin));
web_view->MainFrameWidget()->HandleInputEvent(
- GenerateEvent(WebInputEvent::kGestureScrollUpdate, 0, 25.f));
+ GenerateEvent(WebInputEvent::Type::kGestureScrollUpdate, 0, 25.f));
EXPECT_FLOAT_EQ(0.5f, web_view->GetBrowserControls().BottomShownRatio());
web_view->MainFrameWidget()->HandleInputEvent(
- GenerateEvent(WebInputEvent::kGestureScrollEnd));
+ GenerateEvent(WebInputEvent::Type::kGestureScrollEnd));
EXPECT_FLOAT_EQ(0.f, web_view->GetBrowserControls().ContentOffset());
EXPECT_FLOAT_EQ(1.f, web_view->GetBrowserControls().BottomShownRatio());
EXPECT_EQ(ScrollOffset(0, 25),
@@ -352,13 +352,13 @@ TEST_F(BrowserControlsTest, MAYBE(ScrollDownThenUp)) {
ScrollOffset(0, 100), mojom::blink::ScrollType::kProgrammatic);
web_view->MainFrameWidget()->HandleInputEvent(
- GenerateEvent(WebInputEvent::kGestureScrollBegin));
+ GenerateEvent(WebInputEvent::Type::kGestureScrollBegin));
EXPECT_FLOAT_EQ(50.f, web_view->GetBrowserControls().ContentOffset());
// Scroll down to completely hide browser controls. Excess deltaY (100px)
// should be consumed by the page.
web_view->MainFrameWidget()->HandleInputEvent(
- GenerateEvent(WebInputEvent::kGestureScrollUpdate, 0, -150.f));
+ GenerateEvent(WebInputEvent::Type::kGestureScrollUpdate, 0, -150.f));
EXPECT_FLOAT_EQ(0.f, web_view->GetBrowserControls().ContentOffset());
EXPECT_EQ(ScrollOffset(0, 200),
GetFrame()->View()->LayoutViewport()->GetScrollOffset());
@@ -366,13 +366,13 @@ TEST_F(BrowserControlsTest, MAYBE(ScrollDownThenUp)) {
// Scroll up and ensure the browser controls does not move until we recover
// 100px previously scrolled.
web_view->MainFrameWidget()->HandleInputEvent(
- GenerateEvent(WebInputEvent::kGestureScrollUpdate, 0, 40.f));
+ GenerateEvent(WebInputEvent::Type::kGestureScrollUpdate, 0, 40.f));
EXPECT_FLOAT_EQ(0.f, web_view->GetBrowserControls().ContentOffset());
EXPECT_EQ(ScrollOffset(0, 160),
GetFrame()->View()->LayoutViewport()->GetScrollOffset());
web_view->MainFrameWidget()->HandleInputEvent(
- GenerateEvent(WebInputEvent::kGestureScrollUpdate, 0, 60.f));
+ GenerateEvent(WebInputEvent::Type::kGestureScrollUpdate, 0, 60.f));
EXPECT_FLOAT_EQ(0.f, web_view->GetBrowserControls().ContentOffset());
EXPECT_EQ(ScrollOffset(0, 100),
GetFrame()->View()->LayoutViewport()->GetScrollOffset());
@@ -380,14 +380,14 @@ TEST_F(BrowserControlsTest, MAYBE(ScrollDownThenUp)) {
// Now we have hit the threshold so further scroll up should be consumed by
// browser controls.
web_view->MainFrameWidget()->HandleInputEvent(
- GenerateEvent(WebInputEvent::kGestureScrollUpdate, 0, 30.f));
+ GenerateEvent(WebInputEvent::Type::kGestureScrollUpdate, 0, 30.f));
EXPECT_FLOAT_EQ(30.f, web_view->GetBrowserControls().ContentOffset());
EXPECT_EQ(ScrollOffset(0, 100),
GetFrame()->View()->LayoutViewport()->GetScrollOffset());
// Once top control is fully shown then page should consume any excess scroll.
web_view->MainFrameWidget()->HandleInputEvent(
- GenerateEvent(WebInputEvent::kGestureScrollUpdate, 0, 70.f));
+ GenerateEvent(WebInputEvent::Type::kGestureScrollUpdate, 0, 70.f));
EXPECT_FLOAT_EQ(50.f, web_view->GetBrowserControls().ContentOffset());
EXPECT_EQ(ScrollOffset(0, 50),
GetFrame()->View()->LayoutViewport()->GetScrollOffset());
@@ -405,26 +405,26 @@ TEST_F(BrowserControlsTest, MAYBE(ScrollUpThenDown)) {
ScrollOffset(0, 100), mojom::blink::ScrollType::kProgrammatic);
web_view->MainFrameWidget()->HandleInputEvent(
- GenerateEvent(WebInputEvent::kGestureScrollBegin));
+ GenerateEvent(WebInputEvent::Type::kGestureScrollBegin));
EXPECT_FLOAT_EQ(0.f, web_view->GetBrowserControls().ContentOffset());
// Scroll up to completely show browser controls. Excess deltaY (50px) should
// be consumed by the page.
web_view->MainFrameWidget()->HandleInputEvent(
- GenerateEvent(WebInputEvent::kGestureScrollUpdate, 0, 100.f));
+ GenerateEvent(WebInputEvent::Type::kGestureScrollUpdate, 0, 100.f));
EXPECT_FLOAT_EQ(50.f, web_view->GetBrowserControls().ContentOffset());
EXPECT_EQ(ScrollOffset(0, 50),
GetFrame()->View()->LayoutViewport()->GetScrollOffset());
// Scroll down and ensure only browser controls is scrolled
web_view->MainFrameWidget()->HandleInputEvent(
- GenerateEvent(WebInputEvent::kGestureScrollUpdate, 0, -40.f));
+ GenerateEvent(WebInputEvent::Type::kGestureScrollUpdate, 0, -40.f));
EXPECT_FLOAT_EQ(10.f, web_view->GetBrowserControls().ContentOffset());
EXPECT_EQ(ScrollOffset(0, 50),
GetFrame()->View()->LayoutViewport()->GetScrollOffset());
web_view->MainFrameWidget()->HandleInputEvent(
- GenerateEvent(WebInputEvent::kGestureScrollUpdate, 0, -60.f));
+ GenerateEvent(WebInputEvent::Type::kGestureScrollUpdate, 0, -60.f));
EXPECT_FLOAT_EQ(0.f, web_view->GetBrowserControls().ContentOffset());
EXPECT_EQ(ScrollOffset(0, 100),
GetFrame()->View()->LayoutViewport()->GetScrollOffset());
@@ -439,18 +439,18 @@ TEST_F(BrowserControlsTest, MAYBE(HorizontalScroll)) {
web_view->GetBrowserControls().SetShownRatio(1, 1);
web_view->MainFrameWidget()->HandleInputEvent(
- GenerateEvent(WebInputEvent::kGestureScrollBegin));
+ GenerateEvent(WebInputEvent::Type::kGestureScrollBegin));
EXPECT_FLOAT_EQ(50.f, web_view->GetBrowserControls().ContentOffset());
// Browser controls should not consume horizontal scroll.
web_view->MainFrameWidget()->HandleInputEvent(
- GenerateEvent(WebInputEvent::kGestureScrollUpdate, -110.f, -100.f));
+ GenerateEvent(WebInputEvent::Type::kGestureScrollUpdate, -110.f, -100.f));
EXPECT_FLOAT_EQ(0.f, web_view->GetBrowserControls().ContentOffset());
EXPECT_EQ(ScrollOffset(110, 50),
GetFrame()->View()->LayoutViewport()->GetScrollOffset());
web_view->MainFrameWidget()->HandleInputEvent(
- GenerateEvent(WebInputEvent::kGestureScrollUpdate, -40.f, 0));
+ GenerateEvent(WebInputEvent::Type::kGestureScrollUpdate, -40.f, 0));
EXPECT_FLOAT_EQ(0.f, web_view->GetBrowserControls().ContentOffset());
EXPECT_EQ(ScrollOffset(150, 50),
GetFrame()->View()->LayoutViewport()->GetScrollOffset());
@@ -468,12 +468,12 @@ TEST_F(BrowserControlsTest, MAYBE(PageScaleHasNoImpact)) {
web_view->GetBrowserControls().SetShownRatio(1, 1);
web_view->MainFrameWidget()->HandleInputEvent(
- GenerateEvent(WebInputEvent::kGestureScrollBegin));
+ GenerateEvent(WebInputEvent::Type::kGestureScrollBegin));
EXPECT_FLOAT_EQ(50.f, web_view->GetBrowserControls().ContentOffset());
// Browser controls should be scrolled partially and page should not scroll.
web_view->MainFrameWidget()->HandleInputEvent(
- GenerateEvent(WebInputEvent::kGestureScrollUpdate, 0, -20.f));
+ GenerateEvent(WebInputEvent::Type::kGestureScrollUpdate, 0, -20.f));
EXPECT_FLOAT_EQ(30.f, web_view->GetBrowserControls().ContentOffset());
EXPECT_EQ(ScrollOffset(0, 0),
GetFrame()->View()->GetScrollableArea()->GetScrollOffset());
@@ -481,32 +481,32 @@ TEST_F(BrowserControlsTest, MAYBE(PageScaleHasNoImpact)) {
// Browser controls should consume 30px and become hidden. Excess scroll
// should be consumed by the page at 2x scale.
web_view->MainFrameWidget()->HandleInputEvent(
- GenerateEvent(WebInputEvent::kGestureScrollUpdate, 0, -70.f));
+ GenerateEvent(WebInputEvent::Type::kGestureScrollUpdate, 0, -70.f));
EXPECT_FLOAT_EQ(0.f, web_view->GetBrowserControls().ContentOffset());
EXPECT_EQ(ScrollOffset(0, 20),
GetFrame()->View()->GetScrollableArea()->GetScrollOffset());
web_view->MainFrameWidget()->HandleInputEvent(
- GenerateEvent(WebInputEvent::kGestureScrollEnd));
+ GenerateEvent(WebInputEvent::Type::kGestureScrollEnd));
// Change page scale and test.
web_view->SetPageScaleFactor(0.5);
web_view->MainFrameWidget()->HandleInputEvent(
- GenerateEvent(WebInputEvent::kGestureScrollBegin));
+ GenerateEvent(WebInputEvent::Type::kGestureScrollBegin));
EXPECT_FLOAT_EQ(0.f, web_view->GetBrowserControls().ContentOffset());
EXPECT_EQ(ScrollOffset(0, 20),
GetFrame()->View()->GetScrollableArea()->GetScrollOffset());
web_view->MainFrameWidget()->HandleInputEvent(
- GenerateEvent(WebInputEvent::kGestureScrollUpdate, 0, 50.f));
+ GenerateEvent(WebInputEvent::Type::kGestureScrollUpdate, 0, 50.f));
EXPECT_FLOAT_EQ(50.f, web_view->GetBrowserControls().ContentOffset());
EXPECT_EQ(ScrollOffset(0, 20),
GetFrame()->View()->GetScrollableArea()->GetScrollOffset());
// At 0.5x scale scrolling 10px should take us to the top of the page.
web_view->MainFrameWidget()->HandleInputEvent(
- GenerateEvent(WebInputEvent::kGestureScrollUpdate, 0, 10.f));
+ GenerateEvent(WebInputEvent::Type::kGestureScrollUpdate, 0, 10.f));
EXPECT_FLOAT_EQ(50.f, web_view->GetBrowserControls().ContentOffset());
EXPECT_EQ(ScrollOffset(0, 0),
GetFrame()->View()->GetScrollableArea()->GetScrollOffset());
@@ -557,18 +557,18 @@ TEST_F(BrowserControlsTest, MAYBE(ScrollableSubregionScrollFirst)) {
// Now scroll down should start hiding browser controls but main frame
// should not scroll.
GetWebView()->MainFrameWidget()->HandleInputEvent(
- GenerateEvent(WebInputEvent::kGestureScrollBegin, 0, -40.f));
+ GenerateEvent(WebInputEvent::Type::kGestureScrollBegin, 0, -40.f));
GetWebView()->MainFrameWidget()->HandleInputEvent(
- GenerateEvent(WebInputEvent::kGestureScrollUpdate, 0, -40.f));
+ GenerateEvent(WebInputEvent::Type::kGestureScrollUpdate, 0, -40.f));
EXPECT_FLOAT_EQ(10.f, web_view->GetBrowserControls().ContentOffset());
EXPECT_EQ(ScrollOffset(0, 50),
GetFrame()->View()->LayoutViewport()->GetScrollOffset());
// Continued scroll down should scroll down the main frame
GetWebView()->MainFrameWidget()->HandleInputEvent(
- GenerateEvent(WebInputEvent::kGestureScrollUpdate, 0, -40.f));
+ GenerateEvent(WebInputEvent::Type::kGestureScrollUpdate, 0, -40.f));
GetWebView()->MainFrameWidget()->HandleInputEvent(
- GenerateEvent(WebInputEvent::kGestureScrollEnd));
+ GenerateEvent(WebInputEvent::Type::kGestureScrollEnd));
EXPECT_FLOAT_EQ(0.f, web_view->GetBrowserControls().ContentOffset());
EXPECT_EQ(ScrollOffset(0, 80),
GetFrame()->View()->LayoutViewport()->GetScrollOffset());
@@ -583,18 +583,18 @@ TEST_F(BrowserControlsTest, MAYBE(ScrollableSubregionScrollFirst)) {
// Now scroll up should start showing browser controls but main frame
// should not scroll.
GetWebView()->MainFrameWidget()->HandleInputEvent(
- GenerateEvent(WebInputEvent::kGestureScrollBegin, 0, 40.f));
+ GenerateEvent(WebInputEvent::Type::kGestureScrollBegin, 0, 40.f));
GetWebView()->MainFrameWidget()->HandleInputEvent(
- GenerateEvent(WebInputEvent::kGestureScrollUpdate, 0, 40.f));
+ GenerateEvent(WebInputEvent::Type::kGestureScrollUpdate, 0, 40.f));
EXPECT_FLOAT_EQ(40.f, web_view->GetBrowserControls().ContentOffset());
EXPECT_EQ(ScrollOffset(0, 80),
GetFrame()->View()->LayoutViewport()->GetScrollOffset());
// Continued scroll up scroll up the main frame
GetWebView()->MainFrameWidget()->HandleInputEvent(
- GenerateEvent(WebInputEvent::kGestureScrollUpdate, 0, 40.f));
+ GenerateEvent(WebInputEvent::Type::kGestureScrollUpdate, 0, 40.f));
GetWebView()->MainFrameWidget()->HandleInputEvent(
- GenerateEvent(WebInputEvent::kGestureScrollEnd));
+ GenerateEvent(WebInputEvent::Type::kGestureScrollEnd));
EXPECT_FLOAT_EQ(50.f, web_view->GetBrowserControls().ContentOffset());
EXPECT_EQ(ScrollOffset(0, 50),
GetFrame()->View()->LayoutViewport()->GetScrollOffset());
@@ -620,18 +620,18 @@ TEST_F(BrowserControlsTest, MAYBE(ScrollableIframeScrollFirst)) {
// Now scroll down should start hiding browser controls but main frame
// should not scroll.
GetWebView()->MainFrameWidget()->HandleInputEvent(
- GenerateEvent(WebInputEvent::kGestureScrollBegin, 0, -40.f));
+ GenerateEvent(WebInputEvent::Type::kGestureScrollBegin, 0, -40.f));
GetWebView()->MainFrameWidget()->HandleInputEvent(
- GenerateEvent(WebInputEvent::kGestureScrollUpdate, 0, -40.f));
+ GenerateEvent(WebInputEvent::Type::kGestureScrollUpdate, 0, -40.f));
EXPECT_FLOAT_EQ(10.f, web_view->GetBrowserControls().ContentOffset());
EXPECT_EQ(ScrollOffset(0, 50),
GetFrame()->View()->LayoutViewport()->GetScrollOffset());
// Continued scroll down should scroll down the main frame
GetWebView()->MainFrameWidget()->HandleInputEvent(
- GenerateEvent(WebInputEvent::kGestureScrollUpdate, 0, -40.f));
+ GenerateEvent(WebInputEvent::Type::kGestureScrollUpdate, 0, -40.f));
GetWebView()->MainFrameWidget()->HandleInputEvent(
- GenerateEvent(WebInputEvent::kGestureScrollEnd));
+ GenerateEvent(WebInputEvent::Type::kGestureScrollEnd));
EXPECT_FLOAT_EQ(0.f, web_view->GetBrowserControls().ContentOffset());
EXPECT_EQ(ScrollOffset(0, 80),
GetFrame()->View()->LayoutViewport()->GetScrollOffset());
@@ -646,18 +646,18 @@ TEST_F(BrowserControlsTest, MAYBE(ScrollableIframeScrollFirst)) {
// Now scroll up should start showing browser controls but main frame
// should not scroll.
GetWebView()->MainFrameWidget()->HandleInputEvent(
- GenerateEvent(WebInputEvent::kGestureScrollBegin, 0, 40.f));
+ GenerateEvent(WebInputEvent::Type::kGestureScrollBegin, 0, 40.f));
GetWebView()->MainFrameWidget()->HandleInputEvent(
- GenerateEvent(WebInputEvent::kGestureScrollUpdate, 0, 40.f));
+ GenerateEvent(WebInputEvent::Type::kGestureScrollUpdate, 0, 40.f));
EXPECT_FLOAT_EQ(40.f, web_view->GetBrowserControls().ContentOffset());
EXPECT_EQ(ScrollOffset(0, 80),
GetFrame()->View()->LayoutViewport()->GetScrollOffset());
// Continued scroll up scroll up the main frame
GetWebView()->MainFrameWidget()->HandleInputEvent(
- GenerateEvent(WebInputEvent::kGestureScrollUpdate, 0, 40.f));
+ GenerateEvent(WebInputEvent::Type::kGestureScrollUpdate, 0, 40.f));
GetWebView()->MainFrameWidget()->HandleInputEvent(
- GenerateEvent(WebInputEvent::kGestureScrollEnd));
+ GenerateEvent(WebInputEvent::Type::kGestureScrollEnd));
EXPECT_FLOAT_EQ(50.f, web_view->GetBrowserControls().ContentOffset());
EXPECT_EQ(ScrollOffset(0, 50),
GetFrame()->View()->LayoutViewport()->GetScrollOffset());
@@ -728,13 +728,13 @@ TEST_F(BrowserControlsTest, MAYBE(ScrollUpPastLimitDoesNotHide)) {
web_view->MainFrameImpl()->SetScrollOffset(WebSize(0, 10000));
GetVisualViewport().SetLocation(FloatPoint(0, 0));
GetWebView()->MainFrameWidget()->HandleInputEvent(
- GenerateEvent(WebInputEvent::kGestureScrollBegin, 0, -10.f));
+ GenerateEvent(WebInputEvent::Type::kGestureScrollBegin, 0, -10.f));
GetWebView()->MainFrameWidget()->HandleInputEvent(
- GenerateEvent(WebInputEvent::kGestureScrollUpdate, 0, -10.f));
+ GenerateEvent(WebInputEvent::Type::kGestureScrollUpdate, 0, -10.f));
EXPECT_FLOAT_EQ(40, web_view->GetBrowserControls().ContentOffset());
GetWebView()->MainFrameWidget()->HandleInputEvent(
- GenerateEvent(WebInputEvent::kGestureScrollEnd));
+ GenerateEvent(WebInputEvent::Type::kGestureScrollEnd));
EXPECT_FLOAT_EQ(50, web_view->GetBrowserControls().ContentOffset());
web_view->GetBrowserControls().SetShownRatio(1, 1);
@@ -742,13 +742,13 @@ TEST_F(BrowserControlsTest, MAYBE(ScrollUpPastLimitDoesNotHide)) {
web_view->MainFrameImpl()->SetScrollOffset(WebSize(0, 0));
GetVisualViewport().SetLocation(FloatPoint(0, 10000));
GetWebView()->MainFrameWidget()->HandleInputEvent(
- GenerateEvent(WebInputEvent::kGestureScrollBegin, 0, -20.f));
+ GenerateEvent(WebInputEvent::Type::kGestureScrollBegin, 0, -20.f));
GetWebView()->MainFrameWidget()->HandleInputEvent(
- GenerateEvent(WebInputEvent::kGestureScrollUpdate, 0, -20.f));
+ GenerateEvent(WebInputEvent::Type::kGestureScrollUpdate, 0, -20.f));
EXPECT_FLOAT_EQ(30, web_view->GetBrowserControls().ContentOffset());
GetWebView()->MainFrameWidget()->HandleInputEvent(
- GenerateEvent(WebInputEvent::kGestureScrollEnd));
+ GenerateEvent(WebInputEvent::Type::kGestureScrollEnd));
EXPECT_FLOAT_EQ(50, web_view->GetBrowserControls().ContentOffset());
web_view->GetBrowserControls().SetShownRatio(1, 1);
@@ -835,13 +835,13 @@ TEST_F(BrowserControlsSimTest, MAYBE(StateConstraints)) {
// Setting permitted state to "both" should not change an in-flight offset.
WebView().MainFrameWidget()->HandleInputEvent(
- GenerateEvent(WebInputEvent::kGestureScrollBegin, 0, 20.f));
+ GenerateEvent(WebInputEvent::Type::kGestureScrollBegin, 0, 20.f));
WebView().MainFrameWidget()->HandleInputEvent(
- GenerateEvent(WebInputEvent::kGestureScrollUpdate, 0, 20.f));
+ GenerateEvent(WebInputEvent::Type::kGestureScrollUpdate, 0, 20.f));
EXPECT_FLOAT_EQ(20, WebView().GetBrowserControls().ContentOffset());
WebView().MainFrameWidget()->HandleInputEvent(
- GenerateEvent(WebInputEvent::kGestureScrollEnd));
+ GenerateEvent(WebInputEvent::Type::kGestureScrollEnd));
EXPECT_FLOAT_EQ(0, WebView().GetBrowserControls().ContentOffset());
Compositor().layer_tree_host()->UpdateBrowserControlsState(
cc::BrowserControlsState::kBoth, cc::BrowserControlsState::kBoth, false);
@@ -1310,9 +1310,9 @@ TEST_F(BrowserControlsTest,
web_view->SetPageScaleFactor(page_scale);
{
web_view->MainFrameWidget()->HandleInputEvent(
- GenerateEvent(WebInputEvent::kGestureScrollBegin));
+ GenerateEvent(WebInputEvent::Type::kGestureScrollBegin));
web_view->MainFrameWidget()->HandleInputEvent(
- GenerateEvent(WebInputEvent::kGestureScrollUpdate, 0, -10000));
+ GenerateEvent(WebInputEvent::Type::kGestureScrollUpdate, 0, -10000));
ASSERT_EQ(0.f, web_view->GetBrowserControls().ContentOffset());
@@ -1323,7 +1323,7 @@ TEST_F(BrowserControlsTest,
EXPECT_EQ(expected_root_offset, root_viewport->GetScrollOffset().Height());
web_view->MainFrameWidget()->HandleInputEvent(
- GenerateEvent(WebInputEvent::kGestureScrollEnd));
+ GenerateEvent(WebInputEvent::Type::kGestureScrollEnd));
}
// Commit the browser controls resize so that the browser controls do not
@@ -1346,9 +1346,9 @@ TEST_F(BrowserControlsTest,
// to the document (i.e. the user shouldn't see a movement).
{
web_view->MainFrameWidget()->HandleInputEvent(
- GenerateEvent(WebInputEvent::kGestureScrollBegin));
+ GenerateEvent(WebInputEvent::Type::kGestureScrollBegin));
web_view->MainFrameWidget()->HandleInputEvent(
- GenerateEvent(WebInputEvent::kGestureScrollUpdate, 0, 80));
+ GenerateEvent(WebInputEvent::Type::kGestureScrollUpdate, 0, 80));
GetVisualViewport().ClampToBoundaries();
view->LayoutViewport()->SetScrollOffset(
@@ -1359,7 +1359,7 @@ TEST_F(BrowserControlsTest,
EXPECT_EQ(expected_root_offset, root_viewport->GetScrollOffset().Height());
web_view->MainFrameWidget()->HandleInputEvent(
- GenerateEvent(WebInputEvent::kGestureScrollEnd));
+ GenerateEvent(WebInputEvent::Type::kGestureScrollEnd));
}
}
@@ -1557,9 +1557,9 @@ TEST_F(BrowserControlsTest, MAYBE(ScrollWithMinHeightSetForTopControlsOnly)) {
{top_height, 20, bottom_height, 0, false, true});
// Scroll down to hide the controls.
web_view->MainFrameWidget()->HandleInputEvent(
- GenerateEvent(WebInputEvent::kGestureScrollBegin));
+ GenerateEvent(WebInputEvent::Type::kGestureScrollBegin));
web_view->MainFrameWidget()->HandleInputEvent(
- GenerateEvent(WebInputEvent::kGestureScrollUpdate, 0, -100));
+ GenerateEvent(WebInputEvent::Type::kGestureScrollUpdate, 0, -100));
// The bottom controls should be completely hidden while the top controls are
// at the minimum height.
@@ -1569,7 +1569,7 @@ TEST_F(BrowserControlsTest, MAYBE(ScrollWithMinHeightSetForTopControlsOnly)) {
// Scrolling back up should bring the browser controls shown ratios back to 1.
web_view->MainFrameWidget()->HandleInputEvent(
- GenerateEvent(WebInputEvent::kGestureScrollUpdate, 0, 100));
+ GenerateEvent(WebInputEvent::Type::kGestureScrollUpdate, 0, 100));
EXPECT_EQ(1.f, web_view->GetBrowserControls().BottomShownRatio());
EXPECT_EQ(1.f, web_view->GetBrowserControls().TopShownRatio());
EXPECT_EQ(top_height, web_view->GetBrowserControls().ContentOffset());
@@ -1587,11 +1587,11 @@ TEST_F(BrowserControlsTest, MAYBE(ScrollWithMinHeightSet)) {
{top_height, 20, bottom_height, 10, false, true});
web_view->MainFrameWidget()->HandleInputEvent(
- GenerateEvent(WebInputEvent::kGestureScrollBegin));
+ GenerateEvent(WebInputEvent::Type::kGestureScrollBegin));
web_view->MainFrameWidget()->HandleInputEvent(
- GenerateEvent(WebInputEvent::kGestureScrollUpdate, 0, -100));
+ GenerateEvent(WebInputEvent::Type::kGestureScrollUpdate, 0, -100));
web_view->MainFrameWidget()->HandleInputEvent(
- GenerateEvent(WebInputEvent::kGestureScrollEnd));
+ GenerateEvent(WebInputEvent::Type::kGestureScrollEnd));
// Browser controls don't scroll off completely, and stop scrolling at the min
// height.
@@ -1600,19 +1600,19 @@ TEST_F(BrowserControlsTest, MAYBE(ScrollWithMinHeightSet)) {
// Ending the scroll then scrolling again shouldn't make any difference.
web_view->MainFrameWidget()->HandleInputEvent(
- GenerateEvent(WebInputEvent::kGestureScrollBegin));
+ GenerateEvent(WebInputEvent::Type::kGestureScrollBegin));
web_view->MainFrameWidget()->HandleInputEvent(
- GenerateEvent(WebInputEvent::kGestureScrollUpdate, 0, -50));
+ GenerateEvent(WebInputEvent::Type::kGestureScrollUpdate, 0, -50));
web_view->MainFrameWidget()->HandleInputEvent(
- GenerateEvent(WebInputEvent::kGestureScrollEnd));
+ GenerateEvent(WebInputEvent::Type::kGestureScrollEnd));
EXPECT_EQ(20, web_view->GetBrowserControls().ContentOffset());
EXPECT_EQ(10, web_view->GetBrowserControls().BottomContentOffset());
// Finally, scroll back up to show the controls completely.
web_view->MainFrameWidget()->HandleInputEvent(
- GenerateEvent(WebInputEvent::kGestureScrollBegin));
+ GenerateEvent(WebInputEvent::Type::kGestureScrollBegin));
web_view->MainFrameWidget()->HandleInputEvent(
- GenerateEvent(WebInputEvent::kGestureScrollUpdate, 0, 100));
+ GenerateEvent(WebInputEvent::Type::kGestureScrollUpdate, 0, 100));
EXPECT_EQ(top_height, web_view->GetBrowserControls().ContentOffset());
EXPECT_EQ(bottom_height,
web_view->GetBrowserControls().BottomContentOffset());
diff --git a/chromium/third_party/blink/renderer/core/frame/csp/content_security_policy.cc b/chromium/third_party/blink/renderer/core/frame/csp/content_security_policy.cc
index 80d48328047..5c8a945baf9 100644
--- a/chromium/third_party/blink/renderer/core/frame/csp/content_security_policy.cc
+++ b/chromium/third_party/blink/renderer/core/frame/csp/content_security_policy.cc
@@ -29,6 +29,8 @@
#include <utility>
#include "base/debug/dump_without_crashing.h"
+#include "services/network/public/cpp/web_sandbox_flags.h"
+#include "services/network/public/mojom/web_sandbox_flags.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/task_type.h"
@@ -50,7 +52,6 @@
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/local_frame_client.h"
#include "third_party/blink/renderer/core/frame/location.h"
-#include "third_party/blink/renderer/core/frame/sandbox_flags.h"
#include "third_party/blink/renderer/core/html/html_script_element.h"
#include "third_party/blink/renderer/core/inspector/console_message.h"
#include "third_party/blink/renderer/platform/bindings/dom_wrapper_world.h"
@@ -156,7 +157,7 @@ ContentSecurityPolicy::ContentSecurityPolicy()
override_inline_style_allowed_(false),
script_hash_algorithms_used_(kContentSecurityPolicyHashAlgorithmNone),
style_hash_algorithms_used_(kContentSecurityPolicyHashAlgorithmNone),
- sandbox_mask_(mojom::blink::WebSandboxFlags::kNone),
+ sandbox_mask_(network::mojom::blink::WebSandboxFlags::kNone),
require_trusted_types_(false),
insecure_request_policy_(
mojom::blink::InsecureRequestPolicy::kLeaveInsecureRequestsAlone) {}
@@ -200,19 +201,14 @@ void ContentSecurityPolicy::ApplyPolicySideEffectsToDelegate() {
// Set mixed content checking and sandbox flags, then dump all the parsing
// error messages, then poke at histograms.
- if (sandbox_mask_ != mojom::blink::WebSandboxFlags::kNone) {
+ if (sandbox_mask_ != network::mojom::blink::WebSandboxFlags::kNone) {
Count(WebFeature::kSandboxViaCSP);
delegate_->SetSandboxFlags(sandbox_mask_);
}
if (require_trusted_types_) {
- if (delegate_->GetSecureContextMode() ==
- SecureContextMode::kSecureContext) {
- delegate_->SetRequireTrustedTypes();
- Count(WebFeature::kTrustedTypesEnabled);
- } else {
- ReportNonsecureTrustedTypes();
- }
+ delegate_->SetRequireTrustedTypes();
+ Count(WebFeature::kTrustedTypesEnabled);
}
delegate_->AddInsecureRequestPolicy(insecure_request_policy_);
@@ -649,13 +645,15 @@ bool ContentSecurityPolicy::AllowPluginTypeForDocument(
bool ContentSecurityPolicy::AllowRequestWithoutIntegrity(
mojom::RequestContextType context,
+ network::mojom::RequestDestination request_destination,
const KURL& url,
RedirectStatus redirect_status,
ReportingDisposition reporting_disposition,
CheckHeaderType check_header_type) const {
for (const auto& policy : policies_) {
if (CheckHeaderTypeMatches(check_header_type, policy->HeaderType()) &&
- !policy->AllowRequestWithoutIntegrity(context, url, redirect_status,
+ !policy->AllowRequestWithoutIntegrity(context, request_destination, url,
+ redirect_status,
reporting_disposition))
return false;
}
@@ -729,6 +727,7 @@ GetDirectiveTypeFromRequestContextType(mojom::RequestContextType context) {
bool ContentSecurityPolicy::AllowRequest(
mojom::RequestContextType context,
+ network::mojom::RequestDestination request_destination,
const KURL& url,
const String& nonce,
const IntegrityMetadataSet& integrity_metadata,
@@ -737,13 +736,15 @@ bool ContentSecurityPolicy::AllowRequest(
ReportingDisposition reporting_disposition,
CheckHeaderType check_header_type) const {
if (integrity_metadata.IsEmpty() &&
- !AllowRequestWithoutIntegrity(context, url, redirect_status,
- reporting_disposition, check_header_type)) {
+ !AllowRequestWithoutIntegrity(context, request_destination, url,
+ redirect_status, reporting_disposition,
+ check_header_type)) {
return false;
}
base::Optional<ContentSecurityPolicy::DirectiveType> type =
GetDirectiveTypeFromRequestContextType(context);
+
if (!type)
return true;
return AllowFromSource(*type, url, redirect_status, reporting_disposition,
@@ -928,7 +929,8 @@ const KURL ContentSecurityPolicy::FallbackUrlForPlugin() const {
return delegate_ ? delegate_->Url() : KURL();
}
-void ContentSecurityPolicy::EnforceSandboxFlags(SandboxFlags mask) {
+void ContentSecurityPolicy::EnforceSandboxFlags(
+ network::mojom::blink::WebSandboxFlags mask) {
sandbox_mask_ |= mask;
}
@@ -1058,10 +1060,25 @@ static void GatherSecurityPolicyViolationEventData(
if (!source_location)
source_location = delegate->GetSourceLocation();
if (source_location && source_location->LineNumber()) {
- KURL source = KURL(source_location->Url());
- init->setSourceFile(StripURLForUseInReport(delegate->GetSecurityOrigin(),
- source, redirect_status,
- effective_type));
+ KURL source_url = KURL(source_location->Url());
+ // The source file might be a script loaded from a redirect. Web browser
+ // usually tries to hide post-redirect information. The script might be
+ // cross-origin with the document, but also with other scripts. As a result,
+ // everything is cleared no matter the |source_url| origin.
+ // See https://crbug.com/1074317
+ //
+ // Note: The username, password and ref are stripped later below by
+ // StripURLForUseInReport(..)
+ source_url.SetQuery(String());
+
+ // TODO(arthursonzogni): |redirect_status| refers to the redirect status of
+ // the |blocked_url|. This is unrelated to |source_url|. Why using it in
+ // this case? This is obviously wrong:
+ String source_file =
+ StripURLForUseInReport(delegate->GetSecurityOrigin(), source_url,
+ redirect_status, effective_type);
+
+ init->setSourceFile(source_file);
init->setLineNumber(source_location->LineNumber());
init->setColumnNumber(source_location->ColumnNumber());
} else {
@@ -1248,11 +1265,12 @@ void ContentSecurityPolicy::ReportValueForEmptyDirective(const String& name,
"'. The directive has been applied, and the value ignored.");
}
-void ContentSecurityPolicy::ReportNonsecureTrustedTypes() {
- LogToConsole(
- "The Content Security Policy directive "
- "'require-trusted-types-for' only has an effect in a secure "
- "context. The directive has been ignored.");
+void ContentSecurityPolicy::ReportMixedContentReportURI(
+ const String& endpoint) {
+ LogToConsole("The Content Security Policy directive specifies as endpoint '" +
+ endpoint +
+ "'. This endpoint will be ignored since it violates the policy "
+ "for Mixed Content.");
}
void ContentSecurityPolicy::ReportInvalidInReportOnly(const String& name) {
@@ -1397,12 +1415,11 @@ void ContentSecurityPolicy::ReportInvalidSourceExpression(
LogToConsole(message);
}
-void ContentSecurityPolicy::ReportMissingReportURI(const String& policy) {
- LogToConsole("The Content Security Policy '" + policy +
- "' was delivered in report-only mode, but does not specify a "
- "'report-uri'; the policy will have no effect. Please either "
- "add a 'report-uri' directive, or deliver the policy via the "
- "'Content-Security-Policy' header.");
+void ContentSecurityPolicy::ReportMultipleReportToEndpoints() {
+ LogToConsole(
+ "The Content Security Policy directive 'report-to' contains more than "
+ "one endpoint. Only the first one will be used, the other ones will be "
+ "ignored.");
}
void ContentSecurityPolicy::LogToConsole(const String& message,
diff --git a/chromium/third_party/blink/renderer/core/frame/csp/content_security_policy.h b/chromium/third_party/blink/renderer/core/frame/csp/content_security_policy.h
index 54d3b7c35e7..29fe4bae016 100644
--- a/chromium/third_party/blink/renderer/core/frame/csp/content_security_policy.h
+++ b/chromium/third_party/blink/renderer/core/frame/csp/content_security_policy.h
@@ -30,6 +30,7 @@
#include <utility>
#include "services/network/public/mojom/content_security_policy.mojom-blink.h"
+#include "services/network/public/mojom/web_sandbox_flags.mojom-blink-forward.h"
#include "third_party/blink/public/mojom/devtools/console_message.mojom-blink.h"
#include "third_party/blink/public/mojom/security_context/insecure_request_policy.mojom-blink-forward.h"
#include "third_party/blink/public/platform/web_content_security_policy_struct.h"
@@ -73,7 +74,6 @@ class SecurityPolicyViolationEventInit;
class SourceLocation;
enum class ResourceType : uint8_t;
-using SandboxFlags = mojom::blink::WebSandboxFlags;
typedef HeapVector<Member<CSPDirectiveList>> CSPDirectiveListVector;
typedef HeapVector<Member<ConsoleMessage>> ConsoleMessageVector;
typedef std::pair<String, network::mojom::ContentSecurityPolicyType>
@@ -89,10 +89,6 @@ class CORE_EXPORT ContentSecurityPolicyDelegate : public GarbageCollectedMixin {
// See https://w3c.github.io/webappsec-csp/#policy-self-origin.
virtual const SecurityOrigin* GetSecurityOrigin() = 0;
- // Returns the SecureContextMode for the context to which the delegate is
- // bound.
- virtual SecureContextMode GetSecureContextMode() = 0;
-
// Returns the URL this content security policy is bound to.
// Used for https://w3c.github.io/webappsec-csp/#violation-url and so.
// Note: Url() is used for several purposes that are specced slightly
@@ -101,7 +97,7 @@ class CORE_EXPORT ContentSecurityPolicyDelegate : public GarbageCollectedMixin {
virtual const KURL& Url() const = 0;
// Directives support.
- virtual void SetSandboxFlags(SandboxFlags) = 0;
+ virtual void SetSandboxFlags(network::mojom::blink::WebSandboxFlags) = 0;
virtual void SetRequireTrustedTypes() = 0;
virtual void AddInsecureRequestPolicy(
mojom::blink::InsecureRequestPolicy) = 0;
@@ -332,14 +328,20 @@ class CORE_EXPORT ContentSecurityPolicy final
ReportingDisposition = ReportingDisposition::kReport) const;
bool IsFrameAncestorsEnforced() const;
+ // TODO(crbug.com/889751): Remove "mojom::RequestContextType" once
+ // all the code migrates.
bool AllowRequestWithoutIntegrity(
mojom::RequestContextType,
+ network::mojom::RequestDestination,
const KURL&,
RedirectStatus = RedirectStatus::kNoRedirect,
ReportingDisposition = ReportingDisposition::kReport,
CheckHeaderType = CheckHeaderType::kCheckAll) const;
+ // TODO(crbug.com/889751): Remove "mojom::RequestContextType" once
+ // all the code migrates.
bool AllowRequest(mojom::RequestContextType,
+ network::mojom::RequestDestination,
const KURL&,
const String& nonce,
const IntegrityMetadataSet&,
@@ -382,7 +384,7 @@ class CORE_EXPORT ContentSecurityPolicy final
void ReportInvalidSandboxFlags(const String&);
void ReportInvalidSourceExpression(const String& directive_name,
const String& source);
- void ReportMissingReportURI(const String&);
+ void ReportMultipleReportToEndpoints();
void ReportUnsupportedDirective(const String&);
void ReportInvalidInReportOnly(const String&);
void ReportInvalidDirectiveInMeta(const String& directive_name);
@@ -390,7 +392,7 @@ class CORE_EXPORT ContentSecurityPolicy final
void ReportMetaOutsideHead(const String&);
void ReportValueForEmptyDirective(const String& directive_name,
const String& value);
- void ReportNonsecureTrustedTypes();
+ void ReportMixedContentReportURI(const String& endpoint);
// If a frame is passed in, the report will be sent using it as a context. If
// no frame is passed in, the report will be sent via this object's
@@ -425,7 +427,7 @@ class CORE_EXPORT ContentSecurityPolicy final
// Used as <object>'s URL when there is no `src` attribute.
const KURL FallbackUrlForPlugin() const;
- void EnforceSandboxFlags(SandboxFlags);
+ void EnforceSandboxFlags(network::mojom::blink::WebSandboxFlags);
void RequireTrustedTypes();
bool IsRequireTrustedTypes() const { return require_trusted_types_; }
String EvalDisabledErrorMessage() const;
@@ -474,6 +476,7 @@ class CORE_EXPORT ContentSecurityPolicy final
// Returns the 'wasm-eval' source is supported.
bool SupportsWasmEval() const { return supports_wasm_eval_; }
+ void SetSupportsWasmEval(bool value) { supports_wasm_eval_ = value; }
// Sometimes we don't know the initiator or it might be destroyed already
// for certain navigational checks. We create a string version of the relevant
@@ -486,7 +489,9 @@ class CORE_EXPORT ContentSecurityPolicy final
// context will be used for all sandbox checks but there are situations
// (before installing the document that this CSP will bind to) when
// there is no execution context to enforce the sandbox flags.
- SandboxFlags GetSandboxMask() const { return sandbox_mask_; }
+ network::mojom::blink::WebSandboxFlags GetSandboxMask() const {
+ return sandbox_mask_;
+ }
bool HasPolicyFromSource(network::mojom::ContentSecurityPolicySource) const;
@@ -577,7 +582,7 @@ class CORE_EXPORT ContentSecurityPolicy final
uint8_t style_hash_algorithms_used_;
// State flags used to configure the environment after parsing a policy.
- SandboxFlags sandbox_mask_;
+ network::mojom::blink::WebSandboxFlags sandbox_mask_;
bool require_trusted_types_;
String disable_eval_error_message_;
mojom::blink::InsecureRequestPolicy insecure_request_policy_;
diff --git a/chromium/third_party/blink/renderer/core/frame/csp/content_security_policy_fuzzer.cc b/chromium/third_party/blink/renderer/core/frame/csp/content_security_policy_fuzzer.cc
index b6d50a9e7a0..00bef2f4c04 100644
--- a/chromium/third_party/blink/renderer/core/frame/csp/content_security_policy_fuzzer.cc
+++ b/chromium/third_party/blink/renderer/core/frame/csp/content_security_policy_fuzzer.cc
@@ -30,7 +30,7 @@ int LLVMFuzzerInitialize(int* argc, char*** argv) {
// CSP is bound.
scoped_refptr<SharedBuffer> empty_document_data = SharedBuffer::Create();
g_page_holder->GetFrame().Loader().ForceSandboxFlags(
- mojom::blink::WebSandboxFlags::kAll);
+ network::mojom::blink::WebSandboxFlags::kAll);
g_page_holder->GetFrame().ForceSynchronousDocumentInstall(
"text/html", empty_document_data);
return 0;
diff --git a/chromium/third_party/blink/renderer/core/frame/csp/content_security_policy_test.cc b/chromium/third_party/blink/renderer/core/frame/csp/content_security_policy_test.cc
index e6206ef33ec..b3e0efc8097 100644
--- a/chromium/third_party/blink/renderer/core/frame/csp/content_security_policy_test.cc
+++ b/chromium/third_party/blink/renderer/core/frame/csp/content_security_policy_test.cc
@@ -235,15 +235,18 @@ TEST_F(ContentSecurityPolicyTest, FrameAncestorsInMeta) {
// delivered in <meta> elements.
TEST_F(ContentSecurityPolicyTest, SandboxInMeta) {
csp->BindToDelegate(execution_context->GetContentSecurityPolicyDelegate());
- EXPECT_EQ(mojom::blink::WebSandboxFlags::kNone, csp->GetSandboxMask());
+ EXPECT_EQ(network::mojom::blink::WebSandboxFlags::kNone,
+ csp->GetSandboxMask());
csp->DidReceiveHeader("sandbox;", ContentSecurityPolicyType::kEnforce,
ContentSecurityPolicySource::kMeta);
- EXPECT_EQ(mojom::blink::WebSandboxFlags::kNone, csp->GetSandboxMask());
+ EXPECT_EQ(network::mojom::blink::WebSandboxFlags::kNone,
+ csp->GetSandboxMask());
execution_context->GetSecurityContext().ApplySandboxFlags(
- mojom::blink::WebSandboxFlags::kAll);
+ network::mojom::blink::WebSandboxFlags::kAll);
csp->DidReceiveHeader("sandbox;", ContentSecurityPolicyType::kEnforce,
ContentSecurityPolicySource::kHTTP);
- EXPECT_EQ(mojom::blink::WebSandboxFlags::kAll, csp->GetSandboxMask());
+ EXPECT_EQ(network::mojom::blink::WebSandboxFlags::kAll,
+ csp->GetSandboxMask());
}
// Tests that report-uri directives are discarded from policies
@@ -273,18 +276,24 @@ TEST_F(ContentSecurityPolicyTest, ObjectSrc) {
csp->DidReceiveHeader("object-src 'none';",
ContentSecurityPolicyType::kEnforce,
ContentSecurityPolicySource::kMeta);
- EXPECT_FALSE(csp->AllowRequest(
- mojom::RequestContextType::OBJECT, url, String(), IntegrityMetadataSet(),
- kParserInserted, ResourceRequest::RedirectStatus::kNoRedirect,
- ReportingDisposition::kSuppressReporting));
- EXPECT_FALSE(csp->AllowRequest(
- mojom::RequestContextType::EMBED, url, String(), IntegrityMetadataSet(),
- kParserInserted, ResourceRequest::RedirectStatus::kNoRedirect,
- ReportingDisposition::kSuppressReporting));
- EXPECT_TRUE(csp->AllowRequest(
- mojom::RequestContextType::PLUGIN, url, String(), IntegrityMetadataSet(),
- kParserInserted, ResourceRequest::RedirectStatus::kNoRedirect,
- ReportingDisposition::kSuppressReporting));
+ EXPECT_FALSE(csp->AllowRequest(mojom::RequestContextType::OBJECT,
+ network::mojom::RequestDestination::kEmpty,
+ url, String(), IntegrityMetadataSet(),
+ kParserInserted,
+ ResourceRequest::RedirectStatus::kNoRedirect,
+ ReportingDisposition::kSuppressReporting));
+ EXPECT_FALSE(csp->AllowRequest(mojom::RequestContextType::EMBED,
+ network::mojom::RequestDestination::kEmbed,
+ url, String(), IntegrityMetadataSet(),
+ kParserInserted,
+ ResourceRequest::RedirectStatus::kNoRedirect,
+ ReportingDisposition::kSuppressReporting));
+ EXPECT_TRUE(csp->AllowRequest(mojom::RequestContextType::PLUGIN,
+ network::mojom::RequestDestination::kEmpty, url,
+ String(), IntegrityMetadataSet(),
+ kParserInserted,
+ ResourceRequest::RedirectStatus::kNoRedirect,
+ ReportingDisposition::kSuppressReporting));
}
TEST_F(ContentSecurityPolicyTest, ConnectSrc) {
@@ -293,28 +302,36 @@ TEST_F(ContentSecurityPolicyTest, ConnectSrc) {
csp->DidReceiveHeader("connect-src 'none';",
ContentSecurityPolicyType::kEnforce,
ContentSecurityPolicySource::kMeta);
- EXPECT_FALSE(csp->AllowRequest(mojom::RequestContextType::SUBRESOURCE, url,
- String(), IntegrityMetadataSet(),
+ EXPECT_FALSE(csp->AllowRequest(mojom::RequestContextType::SUBRESOURCE,
+ network::mojom::RequestDestination::kEmpty,
+ url, String(), IntegrityMetadataSet(),
kParserInserted,
ResourceRequest::RedirectStatus::kNoRedirect,
ReportingDisposition::kSuppressReporting));
EXPECT_FALSE(csp->AllowRequest(mojom::RequestContextType::XML_HTTP_REQUEST,
+ network::mojom::RequestDestination::kEmpty,
url, String(), IntegrityMetadataSet(),
kParserInserted,
ResourceRequest::RedirectStatus::kNoRedirect,
ReportingDisposition::kSuppressReporting));
- EXPECT_FALSE(csp->AllowRequest(
- mojom::RequestContextType::BEACON, url, String(), IntegrityMetadataSet(),
- kParserInserted, ResourceRequest::RedirectStatus::kNoRedirect,
- ReportingDisposition::kSuppressReporting));
- EXPECT_FALSE(csp->AllowRequest(
- mojom::RequestContextType::FETCH, url, String(), IntegrityMetadataSet(),
- kParserInserted, ResourceRequest::RedirectStatus::kNoRedirect,
- ReportingDisposition::kSuppressReporting));
- EXPECT_TRUE(csp->AllowRequest(
- mojom::RequestContextType::PLUGIN, url, String(), IntegrityMetadataSet(),
- kParserInserted, ResourceRequest::RedirectStatus::kNoRedirect,
- ReportingDisposition::kSuppressReporting));
+ EXPECT_FALSE(csp->AllowRequest(mojom::RequestContextType::BEACON,
+ network::mojom::RequestDestination::kEmpty,
+ url, String(), IntegrityMetadataSet(),
+ kParserInserted,
+ ResourceRequest::RedirectStatus::kNoRedirect,
+ ReportingDisposition::kSuppressReporting));
+ EXPECT_FALSE(csp->AllowRequest(mojom::RequestContextType::FETCH,
+ network::mojom::RequestDestination::kEmpty,
+ url, String(), IntegrityMetadataSet(),
+ kParserInserted,
+ ResourceRequest::RedirectStatus::kNoRedirect,
+ ReportingDisposition::kSuppressReporting));
+ EXPECT_TRUE(csp->AllowRequest(mojom::RequestContextType::PLUGIN,
+ network::mojom::RequestDestination::kEmpty, url,
+ String(), IntegrityMetadataSet(),
+ kParserInserted,
+ ResourceRequest::RedirectStatus::kNoRedirect,
+ ReportingDisposition::kSuppressReporting));
}
// Tests that requests for scripts and styles are blocked
// if `require-sri-for` delivered in HTTP header requires integrity be present
@@ -327,72 +344,96 @@ TEST_F(ContentSecurityPolicyTest, RequireSRIForInHeaderMissingIntegrity) {
policy->DidReceiveHeader("require-sri-for script style",
ContentSecurityPolicyType::kEnforce,
ContentSecurityPolicySource::kHTTP);
- EXPECT_FALSE(policy->AllowRequest(
- mojom::RequestContextType::SCRIPT, url, String(), IntegrityMetadataSet(),
- kParserInserted, ResourceRequest::RedirectStatus::kNoRedirect,
- ReportingDisposition::kSuppressReporting));
- EXPECT_FALSE(policy->AllowRequest(
- mojom::RequestContextType::IMPORT, url, String(), IntegrityMetadataSet(),
- kParserInserted, ResourceRequest::RedirectStatus::kNoRedirect,
- ReportingDisposition::kSuppressReporting));
- EXPECT_FALSE(policy->AllowRequest(
- mojom::RequestContextType::STYLE, url, String(), IntegrityMetadataSet(),
- kParserInserted, ResourceRequest::RedirectStatus::kNoRedirect,
- ReportingDisposition::kSuppressReporting));
EXPECT_FALSE(
- policy->AllowRequest(mojom::RequestContextType::SERVICE_WORKER, url,
+ policy->AllowRequest(mojom::RequestContextType::SCRIPT,
+ network::mojom::RequestDestination::kScript, url,
String(), IntegrityMetadataSet(), kParserInserted,
ResourceRequest::RedirectStatus::kNoRedirect,
ReportingDisposition::kSuppressReporting));
EXPECT_FALSE(
- policy->AllowRequest(mojom::RequestContextType::SHARED_WORKER, url,
+ policy->AllowRequest(mojom::RequestContextType::IMPORT,
+ network::mojom::RequestDestination::kEmpty, url,
+ String(), IntegrityMetadataSet(), kParserInserted,
+ ResourceRequest::RedirectStatus::kNoRedirect,
+ ReportingDisposition::kSuppressReporting));
+ EXPECT_FALSE(
+ policy->AllowRequest(mojom::RequestContextType::STYLE,
+ network::mojom::RequestDestination::kStyle, url,
String(), IntegrityMetadataSet(), kParserInserted,
ResourceRequest::RedirectStatus::kNoRedirect,
ReportingDisposition::kSuppressReporting));
EXPECT_FALSE(policy->AllowRequest(
- mojom::RequestContextType::WORKER, url, String(), IntegrityMetadataSet(),
- kParserInserted, ResourceRequest::RedirectStatus::kNoRedirect,
+ mojom::RequestContextType::SERVICE_WORKER,
+ network::mojom::RequestDestination::kServiceWorker, url, String(),
+ IntegrityMetadataSet(), kParserInserted,
+ ResourceRequest::RedirectStatus::kNoRedirect,
ReportingDisposition::kSuppressReporting));
- EXPECT_TRUE(policy->AllowRequest(
- mojom::RequestContextType::IMAGE, url, String(), IntegrityMetadataSet(),
- kParserInserted, ResourceRequest::RedirectStatus::kNoRedirect,
+ EXPECT_FALSE(policy->AllowRequest(
+ mojom::RequestContextType::SHARED_WORKER,
+ network::mojom::RequestDestination::kSharedWorker, url, String(),
+ IntegrityMetadataSet(), kParserInserted,
+ ResourceRequest::RedirectStatus::kNoRedirect,
ReportingDisposition::kSuppressReporting));
+ EXPECT_FALSE(
+ policy->AllowRequest(mojom::RequestContextType::WORKER,
+ network::mojom::RequestDestination::kWorker, url,
+ String(), IntegrityMetadataSet(), kParserInserted,
+ ResourceRequest::RedirectStatus::kNoRedirect,
+ ReportingDisposition::kSuppressReporting));
+ EXPECT_TRUE(policy->AllowRequest(mojom::RequestContextType::IMAGE,
+ network::mojom::RequestDestination::kImage,
+ url, String(), IntegrityMetadataSet(),
+ kParserInserted,
+ ResourceRequest::RedirectStatus::kNoRedirect,
+ ReportingDisposition::kSuppressReporting));
// Report
policy = MakeGarbageCollected<ContentSecurityPolicy>();
policy->BindToDelegate(execution_context->GetContentSecurityPolicyDelegate());
policy->DidReceiveHeader("require-sri-for script style",
ContentSecurityPolicyType::kReport,
ContentSecurityPolicySource::kHTTP);
- EXPECT_TRUE(policy->AllowRequest(
- mojom::RequestContextType::SCRIPT, url, String(), IntegrityMetadataSet(),
- kParserInserted, ResourceRequest::RedirectStatus::kNoRedirect,
- ReportingDisposition::kSuppressReporting));
- EXPECT_TRUE(policy->AllowRequest(
- mojom::RequestContextType::IMPORT, url, String(), IntegrityMetadataSet(),
- kParserInserted, ResourceRequest::RedirectStatus::kNoRedirect,
- ReportingDisposition::kSuppressReporting));
- EXPECT_TRUE(policy->AllowRequest(
- mojom::RequestContextType::STYLE, url, String(), IntegrityMetadataSet(),
- kParserInserted, ResourceRequest::RedirectStatus::kNoRedirect,
- ReportingDisposition::kSuppressReporting));
- EXPECT_TRUE(policy->AllowRequest(mojom::RequestContextType::SERVICE_WORKER,
+ EXPECT_TRUE(policy->AllowRequest(mojom::RequestContextType::SCRIPT,
+ network::mojom::RequestDestination::kScript,
url, String(), IntegrityMetadataSet(),
kParserInserted,
ResourceRequest::RedirectStatus::kNoRedirect,
ReportingDisposition::kSuppressReporting));
- EXPECT_TRUE(policy->AllowRequest(mojom::RequestContextType::SHARED_WORKER,
+ EXPECT_TRUE(policy->AllowRequest(mojom::RequestContextType::IMPORT,
+ network::mojom::RequestDestination::kEmpty,
+ url, String(), IntegrityMetadataSet(),
+ kParserInserted,
+ ResourceRequest::RedirectStatus::kNoRedirect,
+ ReportingDisposition::kSuppressReporting));
+ EXPECT_TRUE(policy->AllowRequest(mojom::RequestContextType::STYLE,
+ network::mojom::RequestDestination::kStyle,
url, String(), IntegrityMetadataSet(),
kParserInserted,
ResourceRequest::RedirectStatus::kNoRedirect,
ReportingDisposition::kSuppressReporting));
EXPECT_TRUE(policy->AllowRequest(
- mojom::RequestContextType::WORKER, url, String(), IntegrityMetadataSet(),
- kParserInserted, ResourceRequest::RedirectStatus::kNoRedirect,
+ mojom::RequestContextType::SERVICE_WORKER,
+ network::mojom::RequestDestination::kServiceWorker, url, String(),
+ IntegrityMetadataSet(), kParserInserted,
+ ResourceRequest::RedirectStatus::kNoRedirect,
ReportingDisposition::kSuppressReporting));
EXPECT_TRUE(policy->AllowRequest(
- mojom::RequestContextType::IMAGE, url, String(), IntegrityMetadataSet(),
- kParserInserted, ResourceRequest::RedirectStatus::kNoRedirect,
+ mojom::RequestContextType::SHARED_WORKER,
+ network::mojom::RequestDestination::kSharedWorker, url, String(),
+ IntegrityMetadataSet(), kParserInserted,
+ ResourceRequest::RedirectStatus::kNoRedirect,
ReportingDisposition::kSuppressReporting));
+ EXPECT_TRUE(policy->AllowRequest(mojom::RequestContextType::WORKER,
+ network::mojom::RequestDestination::kWorker,
+ url, String(), IntegrityMetadataSet(),
+ kParserInserted,
+ ResourceRequest::RedirectStatus::kNoRedirect,
+ ReportingDisposition::kSuppressReporting));
+ EXPECT_TRUE(policy->AllowRequest(mojom::RequestContextType::IMAGE,
+ network::mojom::RequestDestination::kImage,
+ url, String(), IntegrityMetadataSet(),
+ kParserInserted,
+ ResourceRequest::RedirectStatus::kNoRedirect,
+ ReportingDisposition::kSuppressReporting));
}
// Tests that requests for scripts and styles are allowed
@@ -410,36 +451,48 @@ TEST_F(ContentSecurityPolicyTest, RequireSRIForInHeaderPresentIntegrity) {
policy->DidReceiveHeader("require-sri-for script style",
ContentSecurityPolicyType::kEnforce,
ContentSecurityPolicySource::kHTTP);
- EXPECT_TRUE(policy->AllowRequest(
- mojom::RequestContextType::SCRIPT, url, String(), integrity_metadata,
- kParserInserted, ResourceRequest::RedirectStatus::kNoRedirect,
- ReportingDisposition::kSuppressReporting));
- EXPECT_TRUE(policy->AllowRequest(
- mojom::RequestContextType::IMPORT, url, String(), integrity_metadata,
- kParserInserted, ResourceRequest::RedirectStatus::kNoRedirect,
- ReportingDisposition::kSuppressReporting));
- EXPECT_TRUE(policy->AllowRequest(
- mojom::RequestContextType::STYLE, url, String(), integrity_metadata,
- kParserInserted, ResourceRequest::RedirectStatus::kNoRedirect,
- ReportingDisposition::kSuppressReporting));
- EXPECT_TRUE(policy->AllowRequest(mojom::RequestContextType::SERVICE_WORKER,
+ EXPECT_TRUE(policy->AllowRequest(mojom::RequestContextType::SCRIPT,
+ network::mojom::RequestDestination::kScript,
url, String(), integrity_metadata,
kParserInserted,
ResourceRequest::RedirectStatus::kNoRedirect,
ReportingDisposition::kSuppressReporting));
- EXPECT_TRUE(policy->AllowRequest(mojom::RequestContextType::SHARED_WORKER,
+ EXPECT_TRUE(policy->AllowRequest(mojom::RequestContextType::IMPORT,
+ network::mojom::RequestDestination::kEmpty,
+ url, String(), integrity_metadata,
+ kParserInserted,
+ ResourceRequest::RedirectStatus::kNoRedirect,
+ ReportingDisposition::kSuppressReporting));
+ EXPECT_TRUE(policy->AllowRequest(mojom::RequestContextType::STYLE,
+ network::mojom::RequestDestination::kStyle,
+ url, String(), integrity_metadata,
+ kParserInserted,
+ ResourceRequest::RedirectStatus::kNoRedirect,
+ ReportingDisposition::kSuppressReporting));
+ EXPECT_TRUE(
+ policy->AllowRequest(mojom::RequestContextType::SERVICE_WORKER,
+ network::mojom::RequestDestination::kServiceWorker,
+ url, String(), integrity_metadata, kParserInserted,
+ ResourceRequest::RedirectStatus::kNoRedirect,
+ ReportingDisposition::kSuppressReporting));
+ EXPECT_TRUE(
+ policy->AllowRequest(mojom::RequestContextType::SHARED_WORKER,
+ network::mojom::RequestDestination::kSharedWorker,
+ url, String(), integrity_metadata, kParserInserted,
+ ResourceRequest::RedirectStatus::kNoRedirect,
+ ReportingDisposition::kSuppressReporting));
+ EXPECT_TRUE(policy->AllowRequest(mojom::RequestContextType::WORKER,
+ network::mojom::RequestDestination::kWorker,
+ url, String(), integrity_metadata,
+ kParserInserted,
+ ResourceRequest::RedirectStatus::kNoRedirect,
+ ReportingDisposition::kSuppressReporting));
+ EXPECT_TRUE(policy->AllowRequest(mojom::RequestContextType::IMAGE,
+ network::mojom::RequestDestination::kImage,
url, String(), integrity_metadata,
kParserInserted,
ResourceRequest::RedirectStatus::kNoRedirect,
ReportingDisposition::kSuppressReporting));
- EXPECT_TRUE(policy->AllowRequest(
- mojom::RequestContextType::WORKER, url, String(), integrity_metadata,
- kParserInserted, ResourceRequest::RedirectStatus::kNoRedirect,
- ReportingDisposition::kSuppressReporting));
- EXPECT_TRUE(policy->AllowRequest(
- mojom::RequestContextType::IMAGE, url, String(), integrity_metadata,
- kParserInserted, ResourceRequest::RedirectStatus::kNoRedirect,
- ReportingDisposition::kSuppressReporting));
// Content-Security-Policy-Report-Only is not supported in meta element,
// so nothing should be blocked
policy = MakeGarbageCollected<ContentSecurityPolicy>();
@@ -447,36 +500,48 @@ TEST_F(ContentSecurityPolicyTest, RequireSRIForInHeaderPresentIntegrity) {
policy->DidReceiveHeader("require-sri-for script style",
ContentSecurityPolicyType::kReport,
ContentSecurityPolicySource::kHTTP);
- EXPECT_TRUE(policy->AllowRequest(
- mojom::RequestContextType::SCRIPT, url, String(), integrity_metadata,
- kParserInserted, ResourceRequest::RedirectStatus::kNoRedirect,
- ReportingDisposition::kSuppressReporting));
- EXPECT_TRUE(policy->AllowRequest(
- mojom::RequestContextType::IMPORT, url, String(), integrity_metadata,
- kParserInserted, ResourceRequest::RedirectStatus::kNoRedirect,
- ReportingDisposition::kSuppressReporting));
- EXPECT_TRUE(policy->AllowRequest(
- mojom::RequestContextType::STYLE, url, String(), integrity_metadata,
- kParserInserted, ResourceRequest::RedirectStatus::kNoRedirect,
- ReportingDisposition::kSuppressReporting));
- EXPECT_TRUE(policy->AllowRequest(mojom::RequestContextType::SERVICE_WORKER,
+ EXPECT_TRUE(policy->AllowRequest(mojom::RequestContextType::SCRIPT,
+ network::mojom::RequestDestination::kScript,
url, String(), integrity_metadata,
kParserInserted,
ResourceRequest::RedirectStatus::kNoRedirect,
ReportingDisposition::kSuppressReporting));
- EXPECT_TRUE(policy->AllowRequest(mojom::RequestContextType::SHARED_WORKER,
+ EXPECT_TRUE(policy->AllowRequest(mojom::RequestContextType::IMPORT,
+ network::mojom::RequestDestination::kEmpty,
+ url, String(), integrity_metadata,
+ kParserInserted,
+ ResourceRequest::RedirectStatus::kNoRedirect,
+ ReportingDisposition::kSuppressReporting));
+ EXPECT_TRUE(policy->AllowRequest(mojom::RequestContextType::STYLE,
+ network::mojom::RequestDestination::kStyle,
+ url, String(), integrity_metadata,
+ kParserInserted,
+ ResourceRequest::RedirectStatus::kNoRedirect,
+ ReportingDisposition::kSuppressReporting));
+ EXPECT_TRUE(
+ policy->AllowRequest(mojom::RequestContextType::SERVICE_WORKER,
+ network::mojom::RequestDestination::kServiceWorker,
+ url, String(), integrity_metadata, kParserInserted,
+ ResourceRequest::RedirectStatus::kNoRedirect,
+ ReportingDisposition::kSuppressReporting));
+ EXPECT_TRUE(
+ policy->AllowRequest(mojom::RequestContextType::SHARED_WORKER,
+ network::mojom::RequestDestination::kSharedWorker,
+ url, String(), integrity_metadata, kParserInserted,
+ ResourceRequest::RedirectStatus::kNoRedirect,
+ ReportingDisposition::kSuppressReporting));
+ EXPECT_TRUE(policy->AllowRequest(mojom::RequestContextType::WORKER,
+ network::mojom::RequestDestination::kWorker,
+ url, String(), integrity_metadata,
+ kParserInserted,
+ ResourceRequest::RedirectStatus::kNoRedirect,
+ ReportingDisposition::kSuppressReporting));
+ EXPECT_TRUE(policy->AllowRequest(mojom::RequestContextType::IMAGE,
+ network::mojom::RequestDestination::kImage,
url, String(), integrity_metadata,
kParserInserted,
ResourceRequest::RedirectStatus::kNoRedirect,
ReportingDisposition::kSuppressReporting));
- EXPECT_TRUE(policy->AllowRequest(
- mojom::RequestContextType::WORKER, url, String(), integrity_metadata,
- kParserInserted, ResourceRequest::RedirectStatus::kNoRedirect,
- ReportingDisposition::kSuppressReporting));
- EXPECT_TRUE(policy->AllowRequest(
- mojom::RequestContextType::IMAGE, url, String(), integrity_metadata,
- kParserInserted, ResourceRequest::RedirectStatus::kNoRedirect,
- ReportingDisposition::kSuppressReporting));
}
// Tests that requests for scripts and styles are blocked
@@ -490,36 +555,48 @@ TEST_F(ContentSecurityPolicyTest, RequireSRIForInMetaMissingIntegrity) {
policy->DidReceiveHeader("require-sri-for script style",
ContentSecurityPolicyType::kEnforce,
ContentSecurityPolicySource::kMeta);
- EXPECT_FALSE(policy->AllowRequest(
- mojom::RequestContextType::SCRIPT, url, String(), IntegrityMetadataSet(),
- kParserInserted, ResourceRequest::RedirectStatus::kNoRedirect,
- ReportingDisposition::kSuppressReporting));
- EXPECT_FALSE(policy->AllowRequest(
- mojom::RequestContextType::IMPORT, url, String(), IntegrityMetadataSet(),
- kParserInserted, ResourceRequest::RedirectStatus::kNoRedirect,
- ReportingDisposition::kSuppressReporting));
- EXPECT_FALSE(policy->AllowRequest(
- mojom::RequestContextType::STYLE, url, String(), IntegrityMetadataSet(),
- kParserInserted, ResourceRequest::RedirectStatus::kNoRedirect,
- ReportingDisposition::kSuppressReporting));
EXPECT_FALSE(
- policy->AllowRequest(mojom::RequestContextType::SERVICE_WORKER, url,
+ policy->AllowRequest(mojom::RequestContextType::SCRIPT,
+ network::mojom::RequestDestination::kScript, url,
String(), IntegrityMetadataSet(), kParserInserted,
ResourceRequest::RedirectStatus::kNoRedirect,
ReportingDisposition::kSuppressReporting));
EXPECT_FALSE(
- policy->AllowRequest(mojom::RequestContextType::SHARED_WORKER, url,
+ policy->AllowRequest(mojom::RequestContextType::IMPORT,
+ network::mojom::RequestDestination::kEmpty, url,
+ String(), IntegrityMetadataSet(), kParserInserted,
+ ResourceRequest::RedirectStatus::kNoRedirect,
+ ReportingDisposition::kSuppressReporting));
+ EXPECT_FALSE(
+ policy->AllowRequest(mojom::RequestContextType::STYLE,
+ network::mojom::RequestDestination::kStyle, url,
String(), IntegrityMetadataSet(), kParserInserted,
ResourceRequest::RedirectStatus::kNoRedirect,
ReportingDisposition::kSuppressReporting));
EXPECT_FALSE(policy->AllowRequest(
- mojom::RequestContextType::WORKER, url, String(), IntegrityMetadataSet(),
- kParserInserted, ResourceRequest::RedirectStatus::kNoRedirect,
+ mojom::RequestContextType::SERVICE_WORKER,
+ network::mojom::RequestDestination::kServiceWorker, url, String(),
+ IntegrityMetadataSet(), kParserInserted,
+ ResourceRequest::RedirectStatus::kNoRedirect,
ReportingDisposition::kSuppressReporting));
- EXPECT_TRUE(policy->AllowRequest(
- mojom::RequestContextType::IMAGE, url, String(), IntegrityMetadataSet(),
- kParserInserted, ResourceRequest::RedirectStatus::kNoRedirect,
+ EXPECT_FALSE(policy->AllowRequest(
+ mojom::RequestContextType::SHARED_WORKER,
+ network::mojom::RequestDestination::kSharedWorker, url, String(),
+ IntegrityMetadataSet(), kParserInserted,
+ ResourceRequest::RedirectStatus::kNoRedirect,
ReportingDisposition::kSuppressReporting));
+ EXPECT_FALSE(
+ policy->AllowRequest(mojom::RequestContextType::WORKER,
+ network::mojom::RequestDestination::kWorker, url,
+ String(), IntegrityMetadataSet(), kParserInserted,
+ ResourceRequest::RedirectStatus::kNoRedirect,
+ ReportingDisposition::kSuppressReporting));
+ EXPECT_TRUE(policy->AllowRequest(mojom::RequestContextType::IMAGE,
+ network::mojom::RequestDestination::kImage,
+ url, String(), IntegrityMetadataSet(),
+ kParserInserted,
+ ResourceRequest::RedirectStatus::kNoRedirect,
+ ReportingDisposition::kSuppressReporting));
// Content-Security-Policy-Report-Only is not supported in meta element,
// so nothing should be blocked
policy = MakeGarbageCollected<ContentSecurityPolicy>();
@@ -527,36 +604,48 @@ TEST_F(ContentSecurityPolicyTest, RequireSRIForInMetaMissingIntegrity) {
policy->DidReceiveHeader("require-sri-for script style",
ContentSecurityPolicyType::kReport,
ContentSecurityPolicySource::kMeta);
- EXPECT_TRUE(policy->AllowRequest(
- mojom::RequestContextType::SCRIPT, url, String(), IntegrityMetadataSet(),
- kParserInserted, ResourceRequest::RedirectStatus::kNoRedirect,
- ReportingDisposition::kSuppressReporting));
- EXPECT_TRUE(policy->AllowRequest(
- mojom::RequestContextType::IMPORT, url, String(), IntegrityMetadataSet(),
- kParserInserted, ResourceRequest::RedirectStatus::kNoRedirect,
- ReportingDisposition::kSuppressReporting));
- EXPECT_TRUE(policy->AllowRequest(
- mojom::RequestContextType::STYLE, url, String(), IntegrityMetadataSet(),
- kParserInserted, ResourceRequest::RedirectStatus::kNoRedirect,
- ReportingDisposition::kSuppressReporting));
- EXPECT_TRUE(policy->AllowRequest(mojom::RequestContextType::SERVICE_WORKER,
+ EXPECT_TRUE(policy->AllowRequest(mojom::RequestContextType::SCRIPT,
+ network::mojom::RequestDestination::kScript,
+ url, String(), IntegrityMetadataSet(),
+ kParserInserted,
+ ResourceRequest::RedirectStatus::kNoRedirect,
+ ReportingDisposition::kSuppressReporting));
+ EXPECT_TRUE(policy->AllowRequest(mojom::RequestContextType::IMPORT,
+ network::mojom::RequestDestination::kEmpty,
url, String(), IntegrityMetadataSet(),
kParserInserted,
ResourceRequest::RedirectStatus::kNoRedirect,
ReportingDisposition::kSuppressReporting));
- EXPECT_TRUE(policy->AllowRequest(mojom::RequestContextType::SHARED_WORKER,
+ EXPECT_TRUE(policy->AllowRequest(mojom::RequestContextType::STYLE,
+ network::mojom::RequestDestination::kStyle,
url, String(), IntegrityMetadataSet(),
kParserInserted,
ResourceRequest::RedirectStatus::kNoRedirect,
ReportingDisposition::kSuppressReporting));
EXPECT_TRUE(policy->AllowRequest(
- mojom::RequestContextType::WORKER, url, String(), IntegrityMetadataSet(),
- kParserInserted, ResourceRequest::RedirectStatus::kNoRedirect,
+ mojom::RequestContextType::SERVICE_WORKER,
+ network::mojom::RequestDestination::kServiceWorker, url, String(),
+ IntegrityMetadataSet(), kParserInserted,
+ ResourceRequest::RedirectStatus::kNoRedirect,
ReportingDisposition::kSuppressReporting));
EXPECT_TRUE(policy->AllowRequest(
- mojom::RequestContextType::IMAGE, url, String(), IntegrityMetadataSet(),
- kParserInserted, ResourceRequest::RedirectStatus::kNoRedirect,
+ mojom::RequestContextType::SHARED_WORKER,
+ network::mojom::RequestDestination::kSharedWorker, url, String(),
+ IntegrityMetadataSet(), kParserInserted,
+ ResourceRequest::RedirectStatus::kNoRedirect,
ReportingDisposition::kSuppressReporting));
+ EXPECT_TRUE(policy->AllowRequest(mojom::RequestContextType::WORKER,
+ network::mojom::RequestDestination::kWorker,
+ url, String(), IntegrityMetadataSet(),
+ kParserInserted,
+ ResourceRequest::RedirectStatus::kNoRedirect,
+ ReportingDisposition::kSuppressReporting));
+ EXPECT_TRUE(policy->AllowRequest(mojom::RequestContextType::IMAGE,
+ network::mojom::RequestDestination::kImage,
+ url, String(), IntegrityMetadataSet(),
+ kParserInserted,
+ ResourceRequest::RedirectStatus::kNoRedirect,
+ ReportingDisposition::kSuppressReporting));
}
// Tests that requests for scripts and styles are allowed
@@ -574,36 +663,48 @@ TEST_F(ContentSecurityPolicyTest, RequireSRIForInMetaPresentIntegrity) {
policy->DidReceiveHeader("require-sri-for script style",
ContentSecurityPolicyType::kEnforce,
ContentSecurityPolicySource::kMeta);
- EXPECT_TRUE(policy->AllowRequest(
- mojom::RequestContextType::SCRIPT, url, String(), integrity_metadata,
- kParserInserted, ResourceRequest::RedirectStatus::kNoRedirect,
- ReportingDisposition::kSuppressReporting));
- EXPECT_TRUE(policy->AllowRequest(
- mojom::RequestContextType::IMPORT, url, String(), integrity_metadata,
- kParserInserted, ResourceRequest::RedirectStatus::kNoRedirect,
- ReportingDisposition::kSuppressReporting));
- EXPECT_TRUE(policy->AllowRequest(
- mojom::RequestContextType::STYLE, url, String(), integrity_metadata,
- kParserInserted, ResourceRequest::RedirectStatus::kNoRedirect,
- ReportingDisposition::kSuppressReporting));
- EXPECT_TRUE(policy->AllowRequest(mojom::RequestContextType::SERVICE_WORKER,
+ EXPECT_TRUE(policy->AllowRequest(mojom::RequestContextType::SCRIPT,
+ network::mojom::RequestDestination::kScript,
url, String(), integrity_metadata,
kParserInserted,
ResourceRequest::RedirectStatus::kNoRedirect,
ReportingDisposition::kSuppressReporting));
- EXPECT_TRUE(policy->AllowRequest(mojom::RequestContextType::SHARED_WORKER,
+ EXPECT_TRUE(policy->AllowRequest(mojom::RequestContextType::IMPORT,
+ network::mojom::RequestDestination::kEmpty,
+ url, String(), integrity_metadata,
+ kParserInserted,
+ ResourceRequest::RedirectStatus::kNoRedirect,
+ ReportingDisposition::kSuppressReporting));
+ EXPECT_TRUE(policy->AllowRequest(mojom::RequestContextType::STYLE,
+ network::mojom::RequestDestination::kStyle,
+ url, String(), integrity_metadata,
+ kParserInserted,
+ ResourceRequest::RedirectStatus::kNoRedirect,
+ ReportingDisposition::kSuppressReporting));
+ EXPECT_TRUE(
+ policy->AllowRequest(mojom::RequestContextType::SERVICE_WORKER,
+ network::mojom::RequestDestination::kServiceWorker,
+ url, String(), integrity_metadata, kParserInserted,
+ ResourceRequest::RedirectStatus::kNoRedirect,
+ ReportingDisposition::kSuppressReporting));
+ EXPECT_TRUE(
+ policy->AllowRequest(mojom::RequestContextType::SHARED_WORKER,
+ network::mojom::RequestDestination::kSharedWorker,
+ url, String(), integrity_metadata, kParserInserted,
+ ResourceRequest::RedirectStatus::kNoRedirect,
+ ReportingDisposition::kSuppressReporting));
+ EXPECT_TRUE(policy->AllowRequest(mojom::RequestContextType::WORKER,
+ network::mojom::RequestDestination::kWorker,
+ url, String(), integrity_metadata,
+ kParserInserted,
+ ResourceRequest::RedirectStatus::kNoRedirect,
+ ReportingDisposition::kSuppressReporting));
+ EXPECT_TRUE(policy->AllowRequest(mojom::RequestContextType::IMAGE,
+ network::mojom::RequestDestination::kImage,
url, String(), integrity_metadata,
kParserInserted,
ResourceRequest::RedirectStatus::kNoRedirect,
ReportingDisposition::kSuppressReporting));
- EXPECT_TRUE(policy->AllowRequest(
- mojom::RequestContextType::WORKER, url, String(), integrity_metadata,
- kParserInserted, ResourceRequest::RedirectStatus::kNoRedirect,
- ReportingDisposition::kSuppressReporting));
- EXPECT_TRUE(policy->AllowRequest(
- mojom::RequestContextType::IMAGE, url, String(), integrity_metadata,
- kParserInserted, ResourceRequest::RedirectStatus::kNoRedirect,
- ReportingDisposition::kSuppressReporting));
// Content-Security-Policy-Report-Only is not supported in meta element,
// so nothing should be blocked
policy = MakeGarbageCollected<ContentSecurityPolicy>();
@@ -611,36 +712,48 @@ TEST_F(ContentSecurityPolicyTest, RequireSRIForInMetaPresentIntegrity) {
policy->DidReceiveHeader("require-sri-for script style",
ContentSecurityPolicyType::kReport,
ContentSecurityPolicySource::kMeta);
- EXPECT_TRUE(policy->AllowRequest(
- mojom::RequestContextType::SCRIPT, url, String(), integrity_metadata,
- kParserInserted, ResourceRequest::RedirectStatus::kNoRedirect,
- ReportingDisposition::kSuppressReporting));
- EXPECT_TRUE(policy->AllowRequest(
- mojom::RequestContextType::IMPORT, url, String(), integrity_metadata,
- kParserInserted, ResourceRequest::RedirectStatus::kNoRedirect,
- ReportingDisposition::kSuppressReporting));
- EXPECT_TRUE(policy->AllowRequest(
- mojom::RequestContextType::STYLE, url, String(), integrity_metadata,
- kParserInserted, ResourceRequest::RedirectStatus::kNoRedirect,
- ReportingDisposition::kSuppressReporting));
- EXPECT_TRUE(policy->AllowRequest(mojom::RequestContextType::SERVICE_WORKER,
+ EXPECT_TRUE(policy->AllowRequest(mojom::RequestContextType::SCRIPT,
+ network::mojom::RequestDestination::kScript,
url, String(), integrity_metadata,
kParserInserted,
ResourceRequest::RedirectStatus::kNoRedirect,
ReportingDisposition::kSuppressReporting));
- EXPECT_TRUE(policy->AllowRequest(mojom::RequestContextType::SHARED_WORKER,
+ EXPECT_TRUE(policy->AllowRequest(mojom::RequestContextType::IMPORT,
+ network::mojom::RequestDestination::kEmpty,
+ url, String(), integrity_metadata,
+ kParserInserted,
+ ResourceRequest::RedirectStatus::kNoRedirect,
+ ReportingDisposition::kSuppressReporting));
+ EXPECT_TRUE(policy->AllowRequest(mojom::RequestContextType::STYLE,
+ network::mojom::RequestDestination::kStyle,
+ url, String(), integrity_metadata,
+ kParserInserted,
+ ResourceRequest::RedirectStatus::kNoRedirect,
+ ReportingDisposition::kSuppressReporting));
+ EXPECT_TRUE(
+ policy->AllowRequest(mojom::RequestContextType::SERVICE_WORKER,
+ network::mojom::RequestDestination::kServiceWorker,
+ url, String(), integrity_metadata, kParserInserted,
+ ResourceRequest::RedirectStatus::kNoRedirect,
+ ReportingDisposition::kSuppressReporting));
+ EXPECT_TRUE(
+ policy->AllowRequest(mojom::RequestContextType::SHARED_WORKER,
+ network::mojom::RequestDestination::kSharedWorker,
+ url, String(), integrity_metadata, kParserInserted,
+ ResourceRequest::RedirectStatus::kNoRedirect,
+ ReportingDisposition::kSuppressReporting));
+ EXPECT_TRUE(policy->AllowRequest(mojom::RequestContextType::WORKER,
+ network::mojom::RequestDestination::kWorker,
+ url, String(), integrity_metadata,
+ kParserInserted,
+ ResourceRequest::RedirectStatus::kNoRedirect,
+ ReportingDisposition::kSuppressReporting));
+ EXPECT_TRUE(policy->AllowRequest(mojom::RequestContextType::IMAGE,
+ network::mojom::RequestDestination::kImage,
url, String(), integrity_metadata,
kParserInserted,
ResourceRequest::RedirectStatus::kNoRedirect,
ReportingDisposition::kSuppressReporting));
- EXPECT_TRUE(policy->AllowRequest(
- mojom::RequestContextType::WORKER, url, String(), integrity_metadata,
- kParserInserted, ResourceRequest::RedirectStatus::kNoRedirect,
- ReportingDisposition::kSuppressReporting));
- EXPECT_TRUE(policy->AllowRequest(
- mojom::RequestContextType::IMAGE, url, String(), integrity_metadata,
- kParserInserted, ResourceRequest::RedirectStatus::kNoRedirect,
- ReportingDisposition::kSuppressReporting));
}
TEST_F(ContentSecurityPolicyTest, NonceSinglePolicy) {
@@ -1059,30 +1172,34 @@ TEST_F(ContentSecurityPolicyTest, RequestsAllowedWhenBypassingCSP) {
ContentSecurityPolicySource::kHTTP);
EXPECT_TRUE(csp->AllowRequest(mojom::RequestContextType::OBJECT,
+ network::mojom::RequestDestination::kEmpty,
KURL(base, "https://example.com/"), String(),
IntegrityMetadataSet(), kParserInserted,
ResourceRequest::RedirectStatus::kNoRedirect,
ReportingDisposition::kSuppressReporting));
EXPECT_FALSE(csp->AllowRequest(
- mojom::RequestContextType::OBJECT, KURL(base, "https://not-example.com/"),
- String(), IntegrityMetadataSet(), kParserInserted,
- ResourceRequest::RedirectStatus::kNoRedirect,
+ mojom::RequestContextType::OBJECT,
+ network::mojom::RequestDestination::kEmpty,
+ KURL(base, "https://not-example.com/"), String(), IntegrityMetadataSet(),
+ kParserInserted, ResourceRequest::RedirectStatus::kNoRedirect,
ReportingDisposition::kSuppressReporting));
// Register "https" as bypassing CSP, which should now bypass it entirely
SchemeRegistry::RegisterURLSchemeAsBypassingContentSecurityPolicy("https");
EXPECT_TRUE(csp->AllowRequest(mojom::RequestContextType::OBJECT,
+ network::mojom::RequestDestination::kEmpty,
KURL(base, "https://example.com/"), String(),
IntegrityMetadataSet(), kParserInserted,
ResourceRequest::RedirectStatus::kNoRedirect,
ReportingDisposition::kSuppressReporting));
EXPECT_TRUE(csp->AllowRequest(
- mojom::RequestContextType::OBJECT, KURL(base, "https://not-example.com/"),
- String(), IntegrityMetadataSet(), kParserInserted,
- ResourceRequest::RedirectStatus::kNoRedirect,
+ mojom::RequestContextType::OBJECT,
+ network::mojom::RequestDestination::kEmpty,
+ KURL(base, "https://not-example.com/"), String(), IntegrityMetadataSet(),
+ kParserInserted, ResourceRequest::RedirectStatus::kNoRedirect,
ReportingDisposition::kSuppressReporting));
SchemeRegistry::RemoveURLSchemeRegisteredAsBypassingContentSecurityPolicy(
@@ -1101,6 +1218,7 @@ TEST_F(ContentSecurityPolicyTest, FilesystemAllowedWhenBypassingCSP) {
EXPECT_FALSE(
csp->AllowRequest(mojom::RequestContextType::OBJECT,
+ network::mojom::RequestDestination::kEmpty,
KURL(base, "filesystem:https://example.com/file.txt"),
String(), IntegrityMetadataSet(), kParserInserted,
ResourceRequest::RedirectStatus::kNoRedirect,
@@ -1108,6 +1226,7 @@ TEST_F(ContentSecurityPolicyTest, FilesystemAllowedWhenBypassingCSP) {
EXPECT_FALSE(csp->AllowRequest(
mojom::RequestContextType::OBJECT,
+ network::mojom::RequestDestination::kEmpty,
KURL(base, "filesystem:https://not-example.com/file.txt"), String(),
IntegrityMetadataSet(), kParserInserted,
ResourceRequest::RedirectStatus::kNoRedirect,
@@ -1118,6 +1237,7 @@ TEST_F(ContentSecurityPolicyTest, FilesystemAllowedWhenBypassingCSP) {
EXPECT_TRUE(
csp->AllowRequest(mojom::RequestContextType::OBJECT,
+ network::mojom::RequestDestination::kEmpty,
KURL(base, "filesystem:https://example.com/file.txt"),
String(), IntegrityMetadataSet(), kParserInserted,
ResourceRequest::RedirectStatus::kNoRedirect,
@@ -1125,6 +1245,7 @@ TEST_F(ContentSecurityPolicyTest, FilesystemAllowedWhenBypassingCSP) {
EXPECT_TRUE(csp->AllowRequest(
mojom::RequestContextType::OBJECT,
+ network::mojom::RequestDestination::kEmpty,
KURL(base, "filesystem:https://not-example.com/file.txt"), String(),
IntegrityMetadataSet(), kParserInserted,
ResourceRequest::RedirectStatus::kNoRedirect,
@@ -1147,11 +1268,13 @@ TEST_F(ContentSecurityPolicyTest, BlobAllowedWhenBypassingCSP) {
EXPECT_FALSE(csp->AllowRequest(
mojom::RequestContextType::OBJECT,
+ network::mojom::RequestDestination::kEmpty,
KURL(base, "blob:https://example.com/"), String(), IntegrityMetadataSet(),
kParserInserted, ResourceRequest::RedirectStatus::kNoRedirect,
ReportingDisposition::kSuppressReporting));
EXPECT_FALSE(csp->AllowRequest(mojom::RequestContextType::OBJECT,
+ network::mojom::RequestDestination::kEmpty,
KURL(base, "blob:https://not-example.com/"),
String(), IntegrityMetadataSet(),
kParserInserted,
@@ -1163,11 +1286,13 @@ TEST_F(ContentSecurityPolicyTest, BlobAllowedWhenBypassingCSP) {
EXPECT_TRUE(csp->AllowRequest(
mojom::RequestContextType::OBJECT,
+ network::mojom::RequestDestination::kEmpty,
KURL(base, "blob:https://example.com/"), String(), IntegrityMetadataSet(),
kParserInserted, ResourceRequest::RedirectStatus::kNoRedirect,
ReportingDisposition::kSuppressReporting));
EXPECT_TRUE(csp->AllowRequest(mojom::RequestContextType::OBJECT,
+ network::mojom::RequestDestination::kEmpty,
KURL(base, "blob:https://not-example.com/"),
String(), IntegrityMetadataSet(),
kParserInserted,
@@ -1646,9 +1771,11 @@ TEST_F(ContentSecurityPolicyTest, EmptyCSPIsNoOp) {
EXPECT_TRUE(csp->AllowAncestors(document->GetFrame(), example_url));
EXPECT_FALSE(csp->IsFrameAncestorsEnforced());
EXPECT_TRUE(csp->AllowRequestWithoutIntegrity(
- mojom::RequestContextType::SCRIPT, example_url));
- EXPECT_TRUE(csp->AllowRequest(mojom::RequestContextType::SCRIPT, example_url,
- nonce, IntegrityMetadataSet(),
+ mojom::RequestContextType::SCRIPT,
+ network::mojom::RequestDestination::kScript, example_url));
+ EXPECT_TRUE(csp->AllowRequest(mojom::RequestContextType::SCRIPT,
+ network::mojom::RequestDestination::kScript,
+ example_url, nonce, IntegrityMetadataSet(),
kParserInserted));
EXPECT_FALSE(csp->IsActive());
EXPECT_FALSE(csp->IsActiveForConnections());
@@ -1657,7 +1784,8 @@ TEST_F(ContentSecurityPolicyTest, EmptyCSPIsNoOp) {
csp->GetInsecureRequestPolicy());
EXPECT_FALSE(csp->HasHeaderDeliveredPolicy());
EXPECT_FALSE(csp->SupportsWasmEval());
- EXPECT_EQ(mojom::blink::WebSandboxFlags::kNone, csp->GetSandboxMask());
+ EXPECT_EQ(network::mojom::blink::WebSandboxFlags::kNone,
+ csp->GetSandboxMask());
EXPECT_FALSE(csp->HasPolicyFromSource(ContentSecurityPolicySource::kHTTP));
}
@@ -1673,7 +1801,8 @@ TEST_F(ContentSecurityPolicyTest, OpaqueOriginBeforeBind) {
csp->DidReceiveHeader("default-src 'self';",
ContentSecurityPolicyType::kEnforce,
ContentSecurityPolicySource::kMeta);
- EXPECT_TRUE(csp->AllowRequest(mojom::RequestContextType::SUBRESOURCE, url,
+ EXPECT_TRUE(csp->AllowRequest(mojom::RequestContextType::SUBRESOURCE,
+ network::mojom::RequestDestination::kEmpty, url,
String(), IntegrityMetadataSet(),
kParserInserted,
ResourceRequest::RedirectStatus::kNoRedirect,
diff --git a/chromium/third_party/blink/renderer/core/frame/csp/csp_directive_list.cc b/chromium/third_party/blink/renderer/core/frame/csp/csp_directive_list.cc
index faa75575624..93b36d543ab 100644
--- a/chromium/third_party/blink/renderer/core/frame/csp/csp_directive_list.cc
+++ b/chromium/third_party/blink/renderer/core/frame/csp/csp_directive_list.cc
@@ -8,6 +8,7 @@
#include <utility>
#include "services/network/public/cpp/features.h"
+#include "services/network/public/cpp/web_sandbox_flags.h"
#include "services/network/public/mojom/content_security_policy.mojom-shared.h"
#include "third_party/blink/renderer/bindings/core/v8/source_location.h"
#include "third_party/blink/renderer/core/dom/document.h"
@@ -15,12 +16,15 @@
#include "third_party/blink/renderer/core/execution_context/security_context.h"
#include "third_party/blink/renderer/core/frame/deprecation.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
+#include "third_party/blink/renderer/core/frame/sandbox_flags.h"
#include "third_party/blink/renderer/core/html/html_script_element.h"
#include "third_party/blink/renderer/core/inspector/console_message.h"
+#include "third_party/blink/renderer/core/loader/mixed_content_checker.h"
#include "third_party/blink/renderer/platform/crypto.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
#include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
#include "third_party/blink/renderer/platform/network/content_security_policy_parsers.h"
+#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
#include "third_party/blink/renderer/platform/wtf/text/base64.h"
#include "third_party/blink/renderer/platform/wtf/text/parsing_utilities.h"
@@ -170,13 +174,6 @@ CSPDirectiveList* CSPDirectiveList::Create(ContentSecurityPolicy* policy,
directives->SetEvalDisabledErrorMessage(message);
}
- if (directives->IsReportOnly() &&
- source != ContentSecurityPolicySource::kMeta &&
- directives->ReportEndpoints().IsEmpty()) {
- policy->ReportMissingReportURI(
- String(begin, static_cast<wtf_size_t>(end - begin)));
- }
-
return directives;
}
@@ -383,7 +380,8 @@ bool CSPDirectiveList::CheckAncestors(SourceListDirective* directive,
}
bool CSPDirectiveList::CheckRequestWithoutIntegrity(
- mojom::RequestContextType context) const {
+ mojom::RequestContextType context,
+ network::mojom::RequestDestination request_destination) const {
if (require_sri_for_ == RequireSRIForToken::kNone)
return true;
// SRI specification
@@ -395,7 +393,13 @@ bool CSPDirectiveList::CheckRequestWithoutIntegrity(
context == mojom::RequestContextType::IMPORT ||
context == mojom::RequestContextType::SERVICE_WORKER ||
context == mojom::RequestContextType::SHARED_WORKER ||
- context == mojom::RequestContextType::WORKER)) {
+ context == mojom::RequestContextType::WORKER ||
+ request_destination == network::mojom::RequestDestination::kScript ||
+ request_destination ==
+ network::mojom::RequestDestination::kServiceWorker ||
+ request_destination ==
+ network::mojom::RequestDestination::kSharedWorker ||
+ request_destination == network::mojom::RequestDestination::kWorker)) {
return false;
}
if ((require_sri_for_ & RequireSRIForToken::kStyle) &&
@@ -406,9 +410,10 @@ bool CSPDirectiveList::CheckRequestWithoutIntegrity(
bool CSPDirectiveList::CheckRequestWithoutIntegrityAndReportViolation(
mojom::RequestContextType context,
+ network::mojom::RequestDestination request_destination,
const KURL& url,
ResourceRequest::RedirectStatus redirect_status) const {
- if (CheckRequestWithoutIntegrity(context))
+ if (CheckRequestWithoutIntegrity(context, request_destination))
return true;
String resource_type;
switch (context) {
@@ -446,13 +451,16 @@ bool CSPDirectiveList::CheckRequestWithoutIntegrityAndReportViolation(
bool CSPDirectiveList::AllowRequestWithoutIntegrity(
mojom::RequestContextType context,
+ network::mojom::RequestDestination request_destination,
const KURL& url,
ResourceRequest::RedirectStatus redirect_status,
ReportingDisposition reporting_disposition) const {
- if (reporting_disposition == ReportingDisposition::kReport)
- return CheckRequestWithoutIntegrityAndReportViolation(context, url,
- redirect_status);
- return DenyIfEnforcingPolicy() || CheckRequestWithoutIntegrity(context);
+ if (reporting_disposition == ReportingDisposition::kReport) {
+ return CheckRequestWithoutIntegrityAndReportViolation(
+ context, request_destination, url, redirect_status);
+ }
+ return DenyIfEnforcingPolicy() ||
+ CheckRequestWithoutIntegrity(context, request_destination);
}
bool CSPDirectiveList::CheckMediaType(MediaListDirective* directive,
@@ -1118,6 +1126,12 @@ void CSPDirectiveList::ParseReportTo(const String& name, const String& value) {
}
ParseAndAppendReportEndpoints(value);
+
+ if (report_endpoints_.size() > 1) {
+ // The directive "report-to" only accepts one endpoint.
+ report_endpoints_.Shrink(1);
+ policy_->ReportMultipleReportToEndpoints();
+ }
}
void CSPDirectiveList::ParseReportURI(const String& name, const String& value) {
@@ -1138,6 +1152,30 @@ void CSPDirectiveList::ParseReportURI(const String& name, const String& value) {
}
ParseAndAppendReportEndpoints(value);
+
+ // Ignore right away report-uri endpoints which would be blocked later when
+ // reporting because of Mixed Content and report a warning.
+ if (!policy_->GetSelfSource()) {
+ return;
+ }
+ report_endpoints_.erase(
+ std::remove_if(report_endpoints_.begin(), report_endpoints_.end(),
+ [this](const String& endpoint) {
+ KURL parsed_endpoint = KURL(endpoint);
+ if (!parsed_endpoint.IsValid()) {
+ // endpoint is not absolute, so it cannot violate
+ // MixedContent
+ return false;
+ }
+ if (MixedContentChecker::IsMixedContent(
+ policy_->GetSelfSource()->GetScheme(),
+ parsed_endpoint)) {
+ policy_->ReportMixedContentReportURI(endpoint);
+ return true;
+ }
+ return false;
+ }),
+ report_endpoints_.end());
}
// For "report-uri" directive, this method corresponds to:
@@ -1147,10 +1185,9 @@ void CSPDirectiveList::ParseReportURI(const String& name, const String& value) {
// For "report-to" directive, the spec says |value| is a single token
// but we use the same logic as "report-uri" and thus we split |value| by
-// ASCII whitespaces.
+// ASCII whitespaces. The tokens after the first one are discarded in
+// CSPDirectiveList::ParseReportTo.
// https://w3c.github.io/webappsec-csp/#directive-report-to
-//
-// TODO(https://crbug.com/916265): Fix this inconsistency.
void CSPDirectiveList::ParseAndAppendReportEndpoints(const String& value) {
Vector<UChar> characters;
value.AppendTo(characters);
@@ -1230,14 +1267,21 @@ void CSPDirectiveList::ApplySandboxPolicy(const String& name,
policy_->ReportDuplicateDirective(name);
return;
}
+
+ using network::mojom::blink::WebSandboxFlags;
+ WebSandboxFlags ignored_flags =
+ !RuntimeEnabledFeatures::StorageAccessAPIEnabled()
+ ? WebSandboxFlags::kStorageAccessByUserActivation
+ : WebSandboxFlags::kNone;
+
has_sandbox_policy_ = true;
- String invalid_tokens;
- SpaceSplitString policy_tokens =
- SpaceSplitString(AtomicString(sandbox_policy));
- policy_->EnforceSandboxFlags(
- ParseSandboxPolicy(policy_tokens, invalid_tokens));
- if (!invalid_tokens.IsNull())
- policy_->ReportInvalidSandboxFlags(invalid_tokens);
+ network::WebSandboxFlagsParsingResult parsed =
+ network::ParseWebSandboxPolicy(sandbox_policy.Utf8(), ignored_flags);
+ policy_->EnforceSandboxFlags(parsed.flags);
+ if (!parsed.error_message.empty()) {
+ policy_->ReportInvalidSandboxFlags(
+ WebString::FromUTF8(parsed.error_message));
+ }
}
void CSPDirectiveList::AddTrustedTypes(const String& name,
@@ -1627,13 +1671,7 @@ CSPDirectiveList::ExposeForNavigationalChecks() const {
navigate_to_->ExposeForNavigationalChecks());
}
- if (upgrade_insecure_requests_) {
- auto empty_source_list = network::mojom::blink::CSPSourceList::New(
- WTF::Vector<network::mojom::blink::CSPSourcePtr>(), false, false,
- false);
- policy->directives.Set(CSPDirectiveName::UpgradeInsecureRequests,
- std::move(empty_source_list));
- }
+ policy->upgrade_insecure_requests = upgrade_insecure_requests_;
return policy;
}
diff --git a/chromium/third_party/blink/renderer/core/frame/csp/csp_directive_list.h b/chromium/third_party/blink/renderer/core/frame/csp/csp_directive_list.h
index 6bf18836d1d..0b176a4f801 100644
--- a/chromium/third_party/blink/renderer/core/frame/csp/csp_directive_list.h
+++ b/chromium/third_party/blink/renderer/core/frame/csp/csp_directive_list.h
@@ -99,6 +99,7 @@ class CORE_EXPORT CSPDirectiveList final
bool AllowDynamicWorker() const;
bool AllowRequestWithoutIntegrity(mojom::RequestContextType,
+ network::mojom::RequestDestination,
const KURL&,
ResourceRequest::RedirectStatus,
ReportingDisposition) const;
@@ -265,7 +266,8 @@ class CORE_EXPORT CSPDirectiveList final
const String& type,
const String& type_attribute) const;
bool CheckAncestors(SourceListDirective*, LocalFrame*) const;
- bool CheckRequestWithoutIntegrity(mojom::RequestContextType) const;
+ bool CheckRequestWithoutIntegrity(mojom::RequestContextType,
+ network::mojom::RequestDestination) const;
void SetEvalDisabledErrorMessage(const String& error_message) {
eval_disabled_error_message_ = error_message;
@@ -303,6 +305,7 @@ class CORE_EXPORT CSPDirectiveList final
const KURL&) const;
bool CheckRequestWithoutIntegrityAndReportViolation(
mojom::RequestContextType,
+ network::mojom::RequestDestination,
const KURL&,
ResourceRequest::RedirectStatus) const;
diff --git a/chromium/third_party/blink/renderer/core/frame/csp/csp_directive_list_test.cc b/chromium/third_party/blink/renderer/core/frame/csp/csp_directive_list_test.cc
index 67855995a13..73efdbb4fc1 100644
--- a/chromium/third_party/blink/renderer/core/frame/csp/csp_directive_list_test.cc
+++ b/chromium/third_party/blink/renderer/core/frame/csp/csp_directive_list_test.cc
@@ -446,101 +446,141 @@ TEST_F(CSPDirectiveListTest, allowRequestWithoutIntegrity) {
const char* list;
const char* url;
const mojom::RequestContextType context;
+ const network::mojom::RequestDestination request_destination;
bool expected;
} cases[] = {
{"require-sri-for script", "https://example.com/file",
- mojom::RequestContextType::SCRIPT, false},
+ mojom::RequestContextType::SCRIPT,
+ network::mojom::RequestDestination::kScript, false},
// Extra WSP
{"require-sri-for script script ", "https://example.com/file",
- mojom::RequestContextType::SCRIPT, false},
+ mojom::RequestContextType::SCRIPT,
+ network::mojom::RequestDestination::kScript, false},
{"require-sri-for style script", "https://example.com/file",
- mojom::RequestContextType::STYLE, false},
+ mojom::RequestContextType::STYLE,
+ network::mojom::RequestDestination::kStyle, false},
{"require-sri-for style script", "https://example.com/file",
- mojom::RequestContextType::SCRIPT, false},
+ mojom::RequestContextType::SCRIPT,
+ network::mojom::RequestDestination::kScript, false},
{"require-sri-for style script", "https://example.com/file",
- mojom::RequestContextType::IMPORT, false},
+ mojom::RequestContextType::IMPORT,
+ network::mojom::RequestDestination::kEmpty, false},
{"require-sri-for style script", "https://example.com/file",
- mojom::RequestContextType::IMAGE, true},
+ mojom::RequestContextType::IMAGE,
+ network::mojom::RequestDestination::kImage, true},
{"require-sri-for script", "https://example.com/file",
- mojom::RequestContextType::AUDIO, true},
+ mojom::RequestContextType::AUDIO,
+ network::mojom::RequestDestination::kAudio, true},
{"require-sri-for script", "https://example.com/file",
- mojom::RequestContextType::SCRIPT, false},
+ mojom::RequestContextType::SCRIPT,
+ network::mojom::RequestDestination::kScript, false},
{"require-sri-for script", "https://example.com/file",
- mojom::RequestContextType::IMPORT, false},
+ mojom::RequestContextType::IMPORT,
+ network::mojom::RequestDestination::kEmpty, false},
{"require-sri-for script", "https://example.com/file",
- mojom::RequestContextType::SERVICE_WORKER, false},
+ mojom::RequestContextType::SERVICE_WORKER,
+ network::mojom::RequestDestination::kServiceWorker, false},
{"require-sri-for script", "https://example.com/file",
- mojom::RequestContextType::SHARED_WORKER, false},
+ mojom::RequestContextType::SHARED_WORKER,
+ network::mojom::RequestDestination::kSharedWorker, false},
{"require-sri-for script", "https://example.com/file",
- mojom::RequestContextType::WORKER, false},
+ mojom::RequestContextType::WORKER,
+ network::mojom::RequestDestination::kWorker, false},
{"require-sri-for script", "https://example.com/file",
- mojom::RequestContextType::STYLE, true},
+ mojom::RequestContextType::STYLE,
+ network::mojom::RequestDestination::kStyle, true},
{"require-sri-for style", "https://example.com/file",
- mojom::RequestContextType::AUDIO, true},
+ mojom::RequestContextType::AUDIO,
+ network::mojom::RequestDestination::kAudio, true},
{"require-sri-for style", "https://example.com/file",
- mojom::RequestContextType::SCRIPT, true},
+ mojom::RequestContextType::SCRIPT,
+ network::mojom::RequestDestination::kScript, true},
{"require-sri-for style", "https://example.com/file",
- mojom::RequestContextType::IMPORT, true},
+ mojom::RequestContextType::IMPORT,
+ network::mojom::RequestDestination::kEmpty, true},
{"require-sri-for style", "https://example.com/file",
- mojom::RequestContextType::SERVICE_WORKER, true},
+ mojom::RequestContextType::SERVICE_WORKER,
+ network::mojom::RequestDestination::kServiceWorker, true},
{"require-sri-for style", "https://example.com/file",
- mojom::RequestContextType::SHARED_WORKER, true},
+ mojom::RequestContextType::SHARED_WORKER,
+ network::mojom::RequestDestination::kSharedWorker, true},
{"require-sri-for style", "https://example.com/file",
- mojom::RequestContextType::WORKER, true},
+ mojom::RequestContextType::WORKER,
+ network::mojom::RequestDestination::kWorker, true},
{"require-sri-for style", "https://example.com/file",
- mojom::RequestContextType::STYLE, false},
+ mojom::RequestContextType::STYLE,
+ network::mojom::RequestDestination::kStyle, false},
// Multiple tokens
{"require-sri-for script style", "https://example.com/file",
- mojom::RequestContextType::STYLE, false},
+ mojom::RequestContextType::STYLE,
+ network::mojom::RequestDestination::kStyle, false},
{"require-sri-for script style", "https://example.com/file",
- mojom::RequestContextType::SCRIPT, false},
+ mojom::RequestContextType::SCRIPT,
+ network::mojom::RequestDestination::kScript, false},
{"require-sri-for script style", "https://example.com/file",
- mojom::RequestContextType::IMPORT, false},
+ mojom::RequestContextType::IMPORT,
+ network::mojom::RequestDestination::kEmpty, false},
{"require-sri-for script style", "https://example.com/file",
- mojom::RequestContextType::IMAGE, true},
+ mojom::RequestContextType::IMAGE,
+ network::mojom::RequestDestination::kImage, true},
// Matching is case-insensitive
{"require-sri-for Script", "https://example.com/file",
- mojom::RequestContextType::SCRIPT, false},
+ mojom::RequestContextType::SCRIPT,
+ network::mojom::RequestDestination::kScript, false},
// Unknown tokens do not affect result
{"require-sri-for blabla12 as", "https://example.com/file",
- mojom::RequestContextType::SCRIPT, true},
+ mojom::RequestContextType::SCRIPT,
+ network::mojom::RequestDestination::kScript, true},
{"require-sri-for blabla12 as script", "https://example.com/file",
- mojom::RequestContextType::SCRIPT, false},
+ mojom::RequestContextType::SCRIPT,
+ network::mojom::RequestDestination::kScript, false},
{"require-sri-for script style img", "https://example.com/file",
- mojom::RequestContextType::SCRIPT, false},
+ mojom::RequestContextType::SCRIPT,
+ network::mojom::RequestDestination::kScript, false},
{"require-sri-for script style img", "https://example.com/file",
- mojom::RequestContextType::IMPORT, false},
+ mojom::RequestContextType::IMPORT,
+ network::mojom::RequestDestination::kEmpty, false},
{"require-sri-for script style img", "https://example.com/file",
- mojom::RequestContextType::STYLE, false},
+ mojom::RequestContextType::STYLE,
+ network::mojom::RequestDestination::kStyle, false},
{"require-sri-for script style img", "https://example.com/file",
- mojom::RequestContextType::IMAGE, true},
+ mojom::RequestContextType::IMAGE,
+ network::mojom::RequestDestination::kImage, true},
// Empty token list has no effect
{"require-sri-for ", "https://example.com/file",
- mojom::RequestContextType::SCRIPT, true},
+ mojom::RequestContextType::SCRIPT,
+ network::mojom::RequestDestination::kScript, true},
{"require-sri-for ", "https://example.com/file",
- mojom::RequestContextType::IMPORT, true},
+ mojom::RequestContextType::IMPORT,
+ network::mojom::RequestDestination::kEmpty, true},
{"require-sri-for ", "https://example.com/file",
- mojom::RequestContextType::STYLE, true},
+ mojom::RequestContextType::STYLE,
+ network::mojom::RequestDestination::kStyle, true},
{"require-sri-for ", "https://example.com/file",
- mojom::RequestContextType::SERVICE_WORKER, true},
+ mojom::RequestContextType::SERVICE_WORKER,
+ network::mojom::RequestDestination::kServiceWorker, true},
{"require-sri-for ", "https://example.com/file",
- mojom::RequestContextType::SHARED_WORKER, true},
+ mojom::RequestContextType::SHARED_WORKER,
+ network::mojom::RequestDestination::kSharedWorker, true},
{"require-sri-for ", "https://example.com/file",
- mojom::RequestContextType::WORKER, true},
+ mojom::RequestContextType::WORKER,
+ network::mojom::RequestDestination::kWorker, true},
// Order does not matter
{"require-sri-for a b script", "https://example.com/file",
- mojom::RequestContextType::SCRIPT, false},
+ mojom::RequestContextType::SCRIPT,
+ network::mojom::RequestDestination::kScript, false},
{"require-sri-for a script b", "https://example.com/file",
- mojom::RequestContextType::SCRIPT, false},
+ mojom::RequestContextType::SCRIPT,
+ network::mojom::RequestDestination::kScript, false},
};
for (const auto& test : cases) {
@@ -549,16 +589,17 @@ TEST_F(CSPDirectiveListTest, allowRequestWithoutIntegrity) {
Member<CSPDirectiveList> directive_list =
CreateList(test.list, ContentSecurityPolicyType::kReport);
EXPECT_EQ(true, directive_list->AllowRequestWithoutIntegrity(
- test.context, resource,
+ test.context, test.request_destination, resource,
ResourceRequest::RedirectStatus::kNoRedirect,
ReportingDisposition::kSuppressReporting));
// Enforce
directive_list = CreateList(test.list, ContentSecurityPolicyType::kEnforce);
- EXPECT_EQ(test.expected, directive_list->AllowRequestWithoutIntegrity(
- test.context, resource,
- ResourceRequest::RedirectStatus::kNoRedirect,
- ReportingDisposition::kSuppressReporting));
+ EXPECT_EQ(test.expected,
+ directive_list->AllowRequestWithoutIntegrity(
+ test.context, test.request_destination, resource,
+ ResourceRequest::RedirectStatus::kNoRedirect,
+ ReportingDisposition::kSuppressReporting));
}
}
@@ -1198,6 +1239,12 @@ TEST_F(CSPDirectiveListTest, ReportEndpointsProperlyParsed) {
ContentSecurityPolicySource::kHTTP,
{"https://example.com", "https://example2.com"},
false},
+ {"script-src 'self'; report-uri https://example.com "
+ "http://example2.com /relative/path",
+ // Mixed Content report-uri endpoint is ignored.
+ ContentSecurityPolicySource::kHTTP,
+ {"https://example.com", "/relative/path"},
+ false},
{"script-src 'self'; report-uri https://example.com",
ContentSecurityPolicySource::kMeta,
{},
@@ -1215,6 +1262,11 @@ TEST_F(CSPDirectiveListTest, ReportEndpointsProperlyParsed) {
ContentSecurityPolicySource::kMeta,
{"group"},
true},
+ {"script-src 'self'; report-to group group2",
+ ContentSecurityPolicySource::kHTTP,
+ // Only the first report-to endpoint is used. The other ones are ignored.
+ {"group"},
+ true},
{"script-src 'self'; report-to group; report-to group2;",
ContentSecurityPolicySource::kHTTP,
{"group"},
diff --git a/chromium/third_party/blink/renderer/core/frame/csp/csp_violation_report_body.h b/chromium/third_party/blink/renderer/core/frame/csp/csp_violation_report_body.h
index b0b2393b5c5..3511ff48ca7 100644
--- a/chromium/third_party/blink/renderer/core/frame/csp/csp_violation_report_body.h
+++ b/chromium/third_party/blink/renderer/core/frame/csp/csp_violation_report_body.h
@@ -16,11 +16,11 @@ class CORE_EXPORT CSPViolationReportBody : public LocationReportBody {
DEFINE_WRAPPERTYPEINFO();
public:
- CSPViolationReportBody(const SecurityPolicyViolationEventInit& violation_data)
- : LocationReportBody(
- SourceLocation::Capture(violation_data.sourceFile(),
- violation_data.lineNumber(),
- violation_data.columnNumber())),
+ explicit CSPViolationReportBody(
+ const SecurityPolicyViolationEventInit& violation_data)
+ : LocationReportBody(violation_data.sourceFile(),
+ violation_data.lineNumber(),
+ violation_data.columnNumber()),
document_url_(violation_data.documentURI()),
referrer_(violation_data.referrer()),
blocked_url_(violation_data.blockedURI()),
diff --git a/chromium/third_party/blink/renderer/core/frame/csp/execution_context_csp_delegate.cc b/chromium/third_party/blink/renderer/core/frame/csp/execution_context_csp_delegate.cc
index 151bb266e1b..8e61fb6093c 100644
--- a/chromium/third_party/blink/renderer/core/frame/csp/execution_context_csp_delegate.cc
+++ b/chromium/third_party/blink/renderer/core/frame/csp/execution_context_csp_delegate.cc
@@ -4,6 +4,8 @@
#include "third_party/blink/renderer/core/frame/csp/execution_context_csp_delegate.h"
+#include "services/network/public/cpp/web_sandbox_flags.h"
+#include "services/network/public/mojom/web_sandbox_flags.mojom-blink.h"
#include "third_party/blink/public/common/security_context/insecure_request_policy.h"
#include "third_party/blink/public/mojom/security_context/insecure_request_policy.mojom-blink.h"
#include "third_party/blink/renderer/bindings/core/v8/source_location.h"
@@ -41,15 +43,12 @@ const SecurityOrigin* ExecutionContextCSPDelegate::GetSecurityOrigin() {
return execution_context_->GetSecurityOrigin();
}
-SecureContextMode ExecutionContextCSPDelegate::GetSecureContextMode() {
- return GetSecurityContext().GetSecureContextMode();
-}
-
const KURL& ExecutionContextCSPDelegate::Url() const {
return execution_context_->Url();
}
-void ExecutionContextCSPDelegate::SetSandboxFlags(SandboxFlags mask) {
+void ExecutionContextCSPDelegate::SetSandboxFlags(
+ network::mojom::blink::WebSandboxFlags mask) {
// Ideally sandbox flags are determined at construction time since
// sandbox flags influence the security origin and that influences
// the Agent that is assigned for the ExecutionContext. Changing
@@ -67,7 +66,8 @@ void ExecutionContextCSPDelegate::SetSandboxFlags(SandboxFlags mask) {
// already been set on the security context. Meta tags can't set them
// and we should have already constructed the document with the correct
// sandbox flags from CSP already.
- mojom::blink::WebSandboxFlags flags = GetSecurityContext().GetSandboxFlags();
+ network::mojom::blink::WebSandboxFlags flags =
+ GetSecurityContext().GetSandboxFlags();
CHECK_EQ(flags | mask, flags);
}
@@ -180,7 +180,7 @@ void ExecutionContextCSPDelegate::PostViolationReport(
auto* body = MakeGarbageCollected<CSPViolationReportBody>(violation_data);
Report* observed_report = MakeGarbageCollected<Report>(
ReportType::kCSPViolation, Url().GetString(), body);
- ReportingContext::From(document->ToExecutionContext())
+ ReportingContext::From(execution_context_.Get())
->QueueReport(observed_report,
use_reporting_api ? report_endpoints : Vector<String>());
@@ -229,11 +229,11 @@ void ExecutionContextCSPDelegate::ReportBlockedScriptExecutionToInspector(
void ExecutionContextCSPDelegate::DidAddContentSecurityPolicies(
WTF::Vector<network::mojom::blink::ContentSecurityPolicyPtr> policies) {
- Document* document = GetDocument();
- if (!document)
+ auto* window = DynamicTo<LocalDOMWindow>(execution_context_.Get());
+ if (!window)
return;
- LocalFrame* frame = document->GetFrame();
+ LocalFrame* frame = window->GetFrame();
if (!frame)
return;
diff --git a/chromium/third_party/blink/renderer/core/frame/csp/execution_context_csp_delegate.h b/chromium/third_party/blink/renderer/core/frame/csp/execution_context_csp_delegate.h
index 426ee795c37..221dcd6038f 100644
--- a/chromium/third_party/blink/renderer/core/frame/csp/execution_context_csp_delegate.h
+++ b/chromium/third_party/blink/renderer/core/frame/csp/execution_context_csp_delegate.h
@@ -26,9 +26,8 @@ class ExecutionContextCSPDelegate final
// ContentSecurityPolicyDelegate overrides:
const SecurityOrigin* GetSecurityOrigin() override;
- SecureContextMode GetSecureContextMode() override;
const KURL& Url() const override;
- void SetSandboxFlags(SandboxFlags) override;
+ void SetSandboxFlags(network::mojom::blink::WebSandboxFlags) override;
void SetRequireTrustedTypes() override;
void AddInsecureRequestPolicy(mojom::blink::InsecureRequestPolicy) override;
std::unique_ptr<SourceLocation> GetSourceLocation() override;
diff --git a/chromium/third_party/blink/renderer/core/frame/csp/navigation_initiator_impl.cc b/chromium/third_party/blink/renderer/core/frame/csp/navigation_initiator_impl.cc
index bce1d06fba9..c9bdc143404 100644
--- a/chromium/third_party/blink/renderer/core/frame/csp/navigation_initiator_impl.cc
+++ b/chromium/third_party/blink/renderer/core/frame/csp/navigation_initiator_impl.cc
@@ -14,7 +14,7 @@
namespace blink {
NavigationInitiatorImpl::NavigationInitiatorImpl(Document& document)
- : navigation_initiator_receivers_(document.GetExecutionContext()),
+ : navigation_initiator_receivers_(this, document.GetExecutionContext()),
document_(document) {
DCHECK(document.GetExecutionContext());
}
@@ -50,8 +50,7 @@ void NavigationInitiatorImpl::SendViolationReport(
void NavigationInitiatorImpl::BindReceiver(
mojo::PendingReceiver<mojom::blink::NavigationInitiator> receiver) {
navigation_initiator_receivers_.Add(
- this, std::move(receiver),
- document_->GetTaskRunner(TaskType::kNetworking));
+ std::move(receiver), document_->GetTaskRunner(TaskType::kNetworking));
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/frame/csp/navigation_initiator_impl.h b/chromium/third_party/blink/renderer/core/frame/csp/navigation_initiator_impl.h
index 7a9e2f7c8f5..5516abd9505 100644
--- a/chromium/third_party/blink/renderer/core/frame/csp/navigation_initiator_impl.h
+++ b/chromium/third_party/blink/renderer/core/frame/csp/navigation_initiator_impl.h
@@ -35,6 +35,7 @@ class NavigationInitiatorImpl
// document. Used to report CSP violations that result from CSP blocking
// navigation requests that were initiated by the owner document.
HeapMojoReceiverSet<mojom::blink::NavigationInitiator,
+ NavigationInitiatorImpl,
HeapMojoWrapperMode::kWithoutContextObserver>
navigation_initiator_receivers_;
diff --git a/chromium/third_party/blink/renderer/core/frame/dactyloscoper.cc b/chromium/third_party/blink/renderer/core/frame/dactyloscoper.cc
index 380a735ecf8..b5c9d54e2ab 100644
--- a/chromium/third_party/blink/renderer/core/frame/dactyloscoper.cc
+++ b/chromium/third_party/blink/renderer/core/frame/dactyloscoper.cc
@@ -4,7 +4,8 @@
#include "third_party/blink/renderer/core/frame/dactyloscoper.h"
-#include "third_party/blink/renderer/core/dom/document.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/loader/document_loader.h"
namespace blink {
@@ -21,9 +22,9 @@ void Dactyloscoper::Record(ExecutionContext* context, WebFeature feature) {
// TODO: Workers.
if (!context)
return;
- if (auto* document = Document::DynamicFrom(context)) {
- if (DocumentLoader* loader = document->Loader())
- loader->GetDactyloscoper().Record(feature);
+ if (auto* window = DynamicTo<LocalDOMWindow>(context)) {
+ if (auto* frame = window->GetFrame())
+ frame->Loader().GetDocumentLoader()->GetDactyloscoper().Record(feature);
}
}
diff --git a/chromium/third_party/blink/renderer/core/frame/deprecation.cc b/chromium/third_party/blink/renderer/core/frame/deprecation.cc
index 62e4ed0ee68..8e50dac623d 100644
--- a/chromium/third_party/blink/renderer/core/frame/deprecation.cc
+++ b/chromium/third_party/blink/renderer/core/frame/deprecation.cc
@@ -4,7 +4,6 @@
#include "third_party/blink/renderer/core/frame/deprecation.h"
-#include <bitset>
#include "base/time/time.h"
#include "build/build_config.h"
#include "third_party/blink/public/mojom/feature_policy/feature_policy.mojom-blink.h"
@@ -14,6 +13,7 @@
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/frame/deprecation_report_body.h"
#include "third_party/blink/renderer/core/frame/frame_console.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/local_frame_client.h"
#include "third_party/blink/renderer/core/frame/report.h"
@@ -26,7 +26,7 @@
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/wtf/date_math.h"
-using blink::WebFeature;
+namespace blink {
namespace {
@@ -63,6 +63,7 @@ enum Milestone {
kM82 = 82,
kM83 = 83,
kM84 = 84,
+ kM85 = 85,
};
// Returns estimated milestone dates as milliseconds since January 1, 1970.
@@ -110,7 +111,11 @@ base::Time::Exploded MilestoneDate(Milestone milestone) {
case kM84:
// This release is not yet scheduled, so this date is a guess.
// https://groups.google.com/a/chromium.org/d/msg/chromium-dev/N1NxbSVOZas/ySlEKDKkBgAJ
- return {2020, 6, 0, 29, 4};
+ return {2020, 7, 0, 14, 4};
+ case kM85:
+ // This release is not yet scheduled, so this date is a guess.
+ // https://groups.google.com/a/chromium.org/d/msg/chromium-dev/N1NxbSVOZas/ySlEKDKkBgAJ
+ return {2020, 8, 0, 25, 4};
}
NOTREACHED();
@@ -302,12 +307,12 @@ DeprecationInfo GetDeprecationInfo(WebFeature feature) {
case WebFeature::kApplicationCacheAPISecureOrigin:
return {
- "ApplicationCacheAPISecureOrigin", kM82,
- WillBeRemoved("Application Cache API use", kM82, "6192449487634432")};
+ "ApplicationCacheAPISecureOrigin", kM85,
+ WillBeRemoved("Application Cache API use", kM85, "6192449487634432")};
case WebFeature::kApplicationCacheManifestSelectSecureOrigin:
- return {"ApplicationCacheAPISecureOrigin", kM82,
- WillBeRemoved("Application Cache API manifest selection", kM82,
+ return {"ApplicationCacheAPISecureOrigin", kM85,
+ WillBeRemoved("Application Cache API manifest selection", kM85,
"6192449487634432")};
case WebFeature::kNotificationInsecureOrigin:
@@ -527,18 +532,69 @@ DeprecationInfo GetDeprecationInfo(WebFeature feature) {
"details.",
MilestoneString(kM84).Ascii().c_str())};
+ case WebFeature::kV8RTCRtpSender_CreateEncodedAudioStreams_Method:
+ return {"V8RTCRtpSender_CreateEncodedAudioStreams_Method", kM85,
+ ReplacedWillBeRemoved("RTCRtpSender.createEncodedAudioStreams",
+ "RTCRtpSender.createEncodedStreams", kM85,
+ "6321945865879552")};
+
+ case WebFeature::kV8RTCRtpSender_CreateEncodedVideoStreams_Method:
+ return {"V8RTCRtpSender_CreateEncodedVideoStreams_Method", kM85,
+ ReplacedWillBeRemoved("RTCRtpSender.createEncodedVideoStreams",
+ "RTCRtpSender.createEncodedStreams", kM85,
+ "6321945865879552")};
+
+ case WebFeature::kV8RTCRtpReceiver_CreateEncodedAudioStreams_Method:
+ return {"V8RTCRtpReceiver_CreateEncodedAudioStreams_Method", kM85,
+ ReplacedWillBeRemoved("RTCRtpReceiver.createEncodedAudioStreams",
+ "RTCRtpReceiver.createEncodedStreams", kM85,
+ "6321945865879552")};
+
+ case WebFeature::kV8RTCRtpReceiver_CreateEncodedVideoStreams_Method:
+ return {"V8RTCRtpReceiver_CreateEncodedVideoStreams_Method", kM85,
+ ReplacedWillBeRemoved("RTCRtpReceiver.createEncodedVideoStreams",
+ "RTCRtpReceiver.createEncodedStreams", kM85,
+ "6321945865879552")};
+
+ case WebFeature::kForceEncodedAudioInsertableStreams:
+ return {"ForceEncodedAudioInsertableStreams", kM85,
+ ReplacedWillBeRemoved(
+ "RTCConfiguration.forceEncodedAudioInsertableStreams",
+ "RTCConfiguration.encodedInsertableStreams", kM85,
+ "6321945865879552")};
+
+ case WebFeature::kForceEncodedVideoInsertableStreams:
+ return {"ForceEncodedVideoInsertableStreams", kM85,
+ ReplacedWillBeRemoved(
+ "RTCConfiguration.forceEncodedVideoInsertableStreams",
+ "RTCConfiguration.encodedInsertableStreams", kM85,
+ "6321945865879552")};
+
// Features that aren't deprecated don't have a deprecation message.
default:
return {"NotDeprecated", kUnknown, ""};
}
}
-} // anonymous namespace
+Report* CreateReportInternal(const KURL& context_url,
+ const DeprecationInfo& info) {
+ base::Optional<base::Time> optional_removal_date;
+ if (info.anticipated_removal != kUnknown) {
+ base::Time removal_date;
+ bool result = base::Time::FromUTCExploded(
+ MilestoneDate(info.anticipated_removal), &removal_date);
+ DCHECK(result);
+ optional_removal_date = removal_date;
+ }
+ DeprecationReportBody* body = MakeGarbageCollected<DeprecationReportBody>(
+ info.id, optional_removal_date, info.message);
+ return MakeGarbageCollected<Report>(ReportType::kDeprecation, context_url,
+ body);
+}
-namespace blink {
+} // anonymous namespace
-Deprecation::Deprecation() : mute_count_(0) {
-}
+Deprecation::Deprecation() : mute_count_(0) {}
void Deprecation::ClearSuppression() {
css_property_deprecation_bits_.reset();
@@ -614,7 +670,7 @@ void Deprecation::CountDeprecation(Document* document, WebFeature feature) {
if (!document)
return;
- Deprecation::CountDeprecation(document->ToExecutionContext(), feature);
+ Deprecation::CountDeprecation(document->GetExecutionContext(), feature);
}
void Deprecation::CountDeprecation(DocumentLoader* loader, WebFeature feature) {
@@ -661,7 +717,10 @@ void Deprecation::CountDeprecationCrossOriginIframe(const Document& document,
}
void Deprecation::GenerateReport(const LocalFrame* frame, WebFeature feature) {
- DeprecationInfo info = GetDeprecationInfo(feature);
+ if (!frame || !frame->Client())
+ return;
+
+ const DeprecationInfo info = GetDeprecationInfo(feature);
// Send the deprecation message to the console as a warning.
DCHECK(!info.message.IsEmpty());
@@ -670,28 +729,17 @@ void Deprecation::GenerateReport(const LocalFrame* frame, WebFeature feature) {
mojom::ConsoleMessageLevel::kWarning, info.message);
frame->Console().AddMessage(console_message);
- if (!frame || !frame->Client())
- return;
-
- Document* document = frame->GetDocument();
-
- // Construct the deprecation report.
- base::Optional<base::Time> optional_removal_date;
- if (info.anticipated_removal != kUnknown) {
- base::Time removal_date;
- bool result = base::Time::FromUTCExploded(
- MilestoneDate(info.anticipated_removal), &removal_date);
- DCHECK(result);
- optional_removal_date = removal_date;
- }
- DeprecationReportBody* body = MakeGarbageCollected<DeprecationReportBody>(
- info.id, optional_removal_date, info.message);
- Report* report = MakeGarbageCollected<Report>(
- ReportType::kDeprecation, document->Url().GetString(), body);
+ auto* window = frame->DomWindow();
+ Report* report = CreateReportInternal(window->Url(), info);
// Send the deprecation report to the Reporting API and any
// ReportingObservers.
- ReportingContext::From(document->ToExecutionContext())->QueueReport(report);
+ ReportingContext::From(window)->QueueReport(report);
+}
+
+// static
+Report* Deprecation::CreateReport(const KURL& context_url, WebFeature feature) {
+ return CreateReportInternal(context_url, GetDeprecationInfo(feature));
}
// static
diff --git a/chromium/third_party/blink/renderer/core/frame/deprecation.h b/chromium/third_party/blink/renderer/core/frame/deprecation.h
index eaf82b6c67b..50c2b489c78 100644
--- a/chromium/third_party/blink/renderer/core/frame/deprecation.h
+++ b/chromium/third_party/blink/renderer/core/frame/deprecation.h
@@ -6,6 +6,7 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_DEPRECATION_H_
#include <bitset>
+
#include "base/macros.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/css/css_property_names.h"
@@ -20,7 +21,9 @@ enum class FeaturePolicyFeature;
class Document;
class DocumentLoader;
class ExecutionContext;
+class KURL;
class LocalFrame;
+class Report;
class CORE_EXPORT Deprecation final {
DISALLOW_NEW();
@@ -56,6 +59,8 @@ class CORE_EXPORT Deprecation final {
static String DeprecationMessage(WebFeature);
+ static Report* CreateReport(const KURL& context_url, WebFeature);
+
// Note: this is only public for tests.
bool IsSuppressed(CSSPropertyID unresolved_property);
diff --git a/chromium/third_party/blink/renderer/core/frame/device_single_window_event_controller.cc b/chromium/third_party/blink/renderer/core/frame/device_single_window_event_controller.cc
index 325ef998a3d..d6f4996103c 100644
--- a/chromium/third_party/blink/renderer/core/frame/device_single_window_event_controller.cc
+++ b/chromium/third_party/blink/renderer/core/frame/device_single_window_event_controller.cc
@@ -4,7 +4,6 @@
#include "third_party/blink/renderer/core/frame/device_single_window_event_controller.h"
-#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/events/event.h"
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
@@ -12,11 +11,9 @@
namespace blink {
DeviceSingleWindowEventController::DeviceSingleWindowEventController(
- Document& document)
- : PlatformEventController(&document),
- needs_checking_null_events_(true),
- document_(document) {
- document.domWindow()->RegisterEventListenerObserver(this);
+ LocalDOMWindow& window)
+ : PlatformEventController(window), needs_checking_null_events_(true) {
+ window.RegisterEventListenerObserver(this);
}
DeviceSingleWindowEventController::~DeviceSingleWindowEventController() =
@@ -27,11 +24,10 @@ void DeviceSingleWindowEventController::DidUpdateData() {
}
void DeviceSingleWindowEventController::DispatchDeviceEvent(Event* event) {
- if (!GetDocument().domWindow() || GetDocument().IsContextPaused() ||
- GetDocument().IsContextDestroyed())
+ if (GetWindow().IsContextPaused() || GetWindow().IsContextDestroyed())
return;
- GetDocument().domWindow()->DispatchEvent(*event);
+ GetWindow().DispatchEvent(*event);
if (needs_checking_null_events_) {
if (IsNullEvent(event))
@@ -72,20 +68,18 @@ void DeviceSingleWindowEventController::DidRemoveAllEventListeners(
bool DeviceSingleWindowEventController::IsSameSecurityOriginAsMainFrame()
const {
- if (!GetDocument().GetFrame() || !GetDocument().GetPage())
+ LocalFrame* frame = GetWindow().GetFrame();
+ if (!frame)
return false;
- if (GetDocument().GetFrame()->IsMainFrame())
+ if (frame->IsMainFrame())
return true;
- const SecurityOrigin* main_security_origin = GetDocument()
- .GetPage()
- ->MainFrame()
- ->GetSecurityContext()
- ->GetSecurityOrigin();
+ const SecurityOrigin* main_security_origin =
+ frame->GetPage()->MainFrame()->GetSecurityContext()->GetSecurityOrigin();
if (main_security_origin &&
- GetDocument().GetSecurityOrigin()->CanAccess(main_security_origin))
+ GetWindow().GetSecurityOrigin()->CanAccess(main_security_origin))
return true;
return false;
@@ -93,16 +87,15 @@ bool DeviceSingleWindowEventController::IsSameSecurityOriginAsMainFrame()
bool DeviceSingleWindowEventController::CheckPolicyFeatures(
const Vector<mojom::blink::FeaturePolicyFeature>& features) const {
- const Document& document = GetDocument();
+ const LocalDOMWindow& window = GetWindow();
return std::all_of(features.begin(), features.end(),
- [&document](mojom::blink::FeaturePolicyFeature feature) {
- return document.IsFeatureEnabled(
+ [&window](mojom::blink::FeaturePolicyFeature feature) {
+ return window.IsFeatureEnabled(
feature, ReportOptions::kReportOnFailure);
});
}
void DeviceSingleWindowEventController::Trace(Visitor* visitor) {
- visitor->Trace(document_);
PlatformEventController::Trace(visitor);
}
diff --git a/chromium/third_party/blink/renderer/core/frame/device_single_window_event_controller.h b/chromium/third_party/blink/renderer/core/frame/device_single_window_event_controller.h
index b32550afba1..990e573e107 100644
--- a/chromium/third_party/blink/renderer/core/frame/device_single_window_event_controller.h
+++ b/chromium/third_party/blink/renderer/core/frame/device_single_window_event_controller.h
@@ -12,7 +12,6 @@
namespace blink {
-class Document;
class Event;
class CORE_EXPORT DeviceSingleWindowEventController
@@ -32,9 +31,8 @@ class CORE_EXPORT DeviceSingleWindowEventController
void DidRemoveAllEventListeners(LocalDOMWindow*) override;
protected:
- explicit DeviceSingleWindowEventController(Document&);
+ explicit DeviceSingleWindowEventController(LocalDOMWindow&);
- Document& GetDocument() const { return *document_; }
bool IsSameSecurityOriginAsMainFrame() const;
bool CheckPolicyFeatures(
const Vector<mojom::blink::FeaturePolicyFeature>& features) const;
@@ -47,7 +45,6 @@ class CORE_EXPORT DeviceSingleWindowEventController
private:
bool needs_checking_null_events_;
- Member<Document> document_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/frame/document_policy_violation_report_body.h b/chromium/third_party/blink/renderer/core/frame/document_policy_violation_report_body.h
index 12d84653edf..e6364be65cb 100644
--- a/chromium/third_party/blink/renderer/core/frame/document_policy_violation_report_body.h
+++ b/chromium/third_party/blink/renderer/core/frame/document_policy_violation_report_body.h
@@ -16,11 +16,6 @@ class CORE_EXPORT DocumentPolicyViolationReportBody
DEFINE_WRAPPERTYPEINFO();
public:
- DocumentPolicyViolationReportBody(const String& feature_id,
- const String& message,
- const String& disposition)
- : feature_id_(feature_id), message_(message), disposition_(disposition) {}
-
DocumentPolicyViolationReportBody(
const String& feature_id,
const String& message,
@@ -29,12 +24,16 @@ class CORE_EXPORT DocumentPolicyViolationReportBody
const String& resource_url)
: LocationReportBody(resource_url),
feature_id_(feature_id),
- message_(message),
+ message_("Document policy violation: " +
+ (message.IsEmpty()
+ ? feature_id + " is not allowed in this document."
+ : message)),
disposition_(disposition) {}
const String& featureId() const { return feature_id_; }
const String& disposition() const { return disposition_; }
const String& message() const { return message_; }
+
void BuildJSONValue(V8ObjectBuilder& builder) const override;
~DocumentPolicyViolationReportBody() override = default;
diff --git a/chromium/third_party/blink/renderer/core/frame/dom_timer_test.cc b/chromium/third_party/blink/renderer/core/frame/dom_timer_test.cc
index 9f982ed49e4..d174fb71d52 100644
--- a/chromium/third_party/blink/renderer/core/frame/dom_timer_test.cc
+++ b/chromium/third_party/blink/renderer/core/frame/dom_timer_test.cc
@@ -51,9 +51,7 @@ class DOMTimerTest : public RenderingTest {
auto* mock_clock = test_task_runner->GetMockClock();
auto* mock_tick_clock = test_task_runner->GetMockTickClock();
auto now_ticks = test_task_runner->NowTicks();
- unified_clock_ = std::make_unique<Performance::UnifiedClock>(
- mock_clock, mock_tick_clock);
- window_performance->SetClocksForTesting(unified_clock_.get());
+ window_performance->SetClocksForTesting(mock_clock, mock_tick_clock);
window_performance->ResetTimeOriginForTesting(now_ticks);
GetDocument().GetSettings()->SetScriptEnabled(true);
auto* loader = GetDocument().Loader();
@@ -88,9 +86,6 @@ class DOMTimerTest : public RenderingTest {
script, KURL(), SanitizeScriptErrors::kSanitize);
platform()->RunUntilIdle();
}
-
- private:
- std::unique_ptr<Performance::UnifiedClock> unified_clock_;
};
const char* const kSetTimeout0ScriptText =
diff --git a/chromium/third_party/blink/renderer/core/frame/dom_window.cc b/chromium/third_party/blink/renderer/core/frame/dom_window.cc
index 0bf6a7d15ad..f0981e2ce1b 100644
--- a/chromium/third_party/blink/renderer/core/frame/dom_window.cc
+++ b/chromium/third_party/blink/renderer/core/frame/dom_window.cc
@@ -6,6 +6,7 @@
#include <memory>
+#include "services/network/public/mojom/web_sandbox_flags.mojom-blink.h"
#include "third_party/blink/renderer/bindings/core/v8/serialization/post_message_helper.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_window_post_message_options.h"
#include "third_party/blink/renderer/bindings/core/v8/window_proxy_manager.h"
@@ -245,26 +246,27 @@ String DOMWindow::CrossDomainAccessErrorMessage(
KURL target_url = local_dom_window
? local_dom_window->document()->Url()
: KURL(NullURL(), target_origin->ToString());
- if (GetFrame()->GetSecurityContext()->IsSandboxed(
- mojom::blink::WebSandboxFlags::kOrigin) ||
- accessing_window->document()->IsSandboxed(
- mojom::blink::WebSandboxFlags::kOrigin)) {
+ using SandboxFlags = network::mojom::blink::WebSandboxFlags;
+ if (GetFrame()->GetSecurityContext()->IsSandboxed(SandboxFlags::kOrigin) ||
+ accessing_window->document()->IsSandboxed(SandboxFlags::kOrigin)) {
message = "Blocked a frame at \"" +
SecurityOrigin::Create(active_url)->ToString() +
"\" from accessing a frame at \"" +
SecurityOrigin::Create(target_url)->ToString() + "\". ";
- if (GetFrame()->GetSecurityContext()->IsSandboxed(
- mojom::blink::WebSandboxFlags::kOrigin) &&
- accessing_window->document()->IsSandboxed(
- mojom::blink::WebSandboxFlags::kOrigin))
+
+ if (GetFrame()->GetSecurityContext()->IsSandboxed(SandboxFlags::kOrigin) &&
+ accessing_window->document()->IsSandboxed(SandboxFlags::kOrigin)) {
return "Sandbox access violation: " + message +
" Both frames are sandboxed and lack the \"allow-same-origin\" "
"flag.";
- if (GetFrame()->GetSecurityContext()->IsSandboxed(
- mojom::blink::WebSandboxFlags::kOrigin))
+ }
+
+ if (GetFrame()->GetSecurityContext()->IsSandboxed(SandboxFlags::kOrigin)) {
return "Sandbox access violation: " + message +
" The frame being accessed is sandboxed and lacks the "
"\"allow-same-origin\" flag.";
+ }
+
return "Sandbox access violation: " + message +
" The frame requesting access is sandboxed and lacks the "
"\"allow-same-origin\" flag.";
@@ -374,19 +376,15 @@ void DOMWindow::focus(v8::Isolate* isolate) {
// https://html.spec.whatwg.org/C/#dom-window-focus
// https://html.spec.whatwg.org/C/#focusing-steps
LocalDOMWindow* incumbent_window = IncumbentDOMWindow(isolate);
- ExecutionContext* incumbent_execution_context =
- incumbent_window->GetExecutionContext();
// TODO(mustaq): Use of |allow_focus| and consuming the activation here seems
// suspicious (https://crbug.com/959815).
- bool allow_focus = incumbent_execution_context->IsWindowInteractionAllowed();
+ bool allow_focus = incumbent_window->IsWindowInteractionAllowed();
if (allow_focus) {
- incumbent_execution_context->ConsumeWindowInteraction();
+ incumbent_window->ConsumeWindowInteraction();
} else {
DCHECK(IsMainThread());
- allow_focus =
- opener() && (opener() != this) &&
- (Document::From(incumbent_execution_context)->domWindow() == opener());
+ allow_focus = opener() && opener() != this && incumbent_window == opener();
}
// If we're a top level window, bring the window to the front.
diff --git a/chromium/third_party/blink/renderer/core/frame/event_handler_registry.cc b/chromium/third_party/blink/renderer/core/frame/event_handler_registry.cc
index b331361c7da..08d723da0be 100644
--- a/chromium/third_party/blink/renderer/core/frame/event_handler_registry.cc
+++ b/chromium/third_party/blink/renderer/core/frame/event_handler_registry.cc
@@ -248,6 +248,11 @@ void EventHandlerRegistry::NotifyHandlersChanged(
bool has_active_handlers) {
LocalFrame* frame = GetLocalFrameForTarget(target);
+ // TODO(keishi): Added for crbug.com/1090687. Change to CHECK once bug is
+ // fixed.
+ if (!GetPage())
+ return;
+
switch (handler_class) {
case kScrollEvent:
GetPage()->GetChromeClient().SetHasScrollEventHandlers(
@@ -324,6 +329,10 @@ void EventHandlerRegistry::NotifyHandlersChanged(
void EventHandlerRegistry::NotifyDidAddOrRemoveEventHandlerTarget(
LocalFrame* frame,
EventHandlerClass handler_class) {
+ // TODO(keishi): Added for crbug.com/1090687. Change to CHECK once bug is
+ // fixed.
+ if (!GetPage())
+ return;
ScrollingCoordinator* scrolling_coordinator =
GetPage()->GetScrollingCoordinator();
if (scrolling_coordinator &&
@@ -341,7 +350,9 @@ void EventHandlerRegistry::Trace(Visitor* visitor) {
EventHandlerRegistry, &EventHandlerRegistry::ProcessCustomWeakness>(this);
}
-void EventHandlerRegistry::ProcessCustomWeakness(const WeakCallbackInfo& info) {
+void EventHandlerRegistry::ProcessCustomWeakness(const LivenessBroker& info) {
+ // We use Vector<UntracedMember<>> here to avoid BlinkGC allocation in a
+ // custom weak callback.
Vector<UntracedMember<EventTarget>> dead_targets;
for (int i = 0; i < kEventHandlerClassCount; ++i) {
EventHandlerClass handler_class = static_cast<EventHandlerClass>(i);
@@ -366,7 +377,7 @@ void EventHandlerRegistry::DocumentDetached(Document& document) {
handler_class_index < kEventHandlerClassCount; ++handler_class_index) {
EventHandlerClass handler_class =
static_cast<EventHandlerClass>(handler_class_index);
- Vector<UntracedMember<EventTarget>> targets_to_remove;
+ HeapVector<Member<EventTarget>> targets_to_remove;
const EventTargetSet* targets = &targets_[handler_class];
for (const auto& event_target : *targets) {
if (Node* node = event_target.key->ToNode()) {
diff --git a/chromium/third_party/blink/renderer/core/frame/event_handler_registry.h b/chromium/third_party/blink/renderer/core/frame/event_handler_registry.h
index ad606b7719d..d41ca26df6d 100644
--- a/chromium/third_party/blink/renderer/core/frame/event_handler_registry.h
+++ b/chromium/third_party/blink/renderer/core/frame/event_handler_registry.h
@@ -16,6 +16,7 @@ class Document;
class EventTarget;
class LocalFrame;
+// We use UntracedMember<> here to do custom weak processing.
typedef HashCountedSet<UntracedMember<EventTarget>> EventTargetSet;
// Registry for keeping track of event handlers. Note that only handlers on
@@ -129,7 +130,7 @@ class CORE_EXPORT EventHandlerRegistry final
Page* GetPage() const;
- void ProcessCustomWeakness(const WeakCallbackInfo&);
+ void ProcessCustomWeakness(const LivenessBroker&);
Member<LocalFrame> frame_;
EventTargetSet targets_[kEventHandlerClassCount];
diff --git a/chromium/third_party/blink/renderer/core/frame/feature_policy_violation_report_body.h b/chromium/third_party/blink/renderer/core/frame/feature_policy_violation_report_body.h
index 3e8fa482cbb..7b810fa1f40 100644
--- a/chromium/third_party/blink/renderer/core/frame/feature_policy_violation_report_body.h
+++ b/chromium/third_party/blink/renderer/core/frame/feature_policy_violation_report_body.h
@@ -18,22 +18,17 @@ class CORE_EXPORT FeaturePolicyViolationReportBody : public LocationReportBody {
FeaturePolicyViolationReportBody(const String& feature_id,
const String& message,
const String& disposition)
- : feature_id_(feature_id), message_(message), disposition_(disposition) {}
-
- FeaturePolicyViolationReportBody(
- const String& feature_id,
- const String& message,
- const String& disposition,
- // url of the resource that violate the feature policy.
- const String& resource_url)
- : LocationReportBody(resource_url),
- feature_id_(feature_id),
- message_(message),
+ : feature_id_(feature_id),
+ message_("Feature policy violation: " +
+ (message.IsEmpty()
+ ? feature_id + " is not allowed in this document."
+ : message)),
disposition_(disposition) {}
const String& featureId() const { return feature_id_; }
const String& disposition() const { return disposition_; }
const String& message() const { return message_; }
+
void BuildJSONValue(V8ObjectBuilder& builder) const override;
~FeaturePolicyViolationReportBody() override = default;
diff --git a/chromium/third_party/blink/renderer/core/frame/find_in_page.cc b/chromium/third_party/blink/renderer/core/frame/find_in_page.cc
index f020300af2d..8f65b9cb858 100644
--- a/chromium/third_party/blink/renderer/core/frame/find_in_page.cc
+++ b/chromium/third_party/blink/renderer/core/frame/find_in_page.cc
@@ -37,6 +37,7 @@
#include "third_party/blink/public/web/web_plugin.h"
#include "third_party/blink/public/web/web_plugin_document.h"
#include "third_party/blink/public/web/web_widget_client.h"
+#include "third_party/blink/renderer/core/display_lock/display_lock_document_state.h"
#include "third_party/blink/renderer/core/editing/finder/text_finder.h"
#include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
@@ -176,8 +177,10 @@ bool FindInPage::FindInternal(int identifier,
// Unlikely, but just in case we try to find-in-page on a detached frame.
DCHECK(frame_->GetFrame()->GetPage());
- auto forced_activatable_locks =
- frame_->GetFrame()->GetDocument()->GetScopedForceActivatableLocks();
+ auto forced_activatable_locks = frame_->GetFrame()
+ ->GetDocument()
+ ->GetDisplayLockDocumentState()
+ .GetScopedForceActivatableLocks();
// Up-to-date, clean tree is required for finding text in page, since it
// relies on TextIterator to look over the text.
diff --git a/chromium/third_party/blink/renderer/core/frame/fragment_directive.idl b/chromium/third_party/blink/renderer/core/frame/fragment_directive.idl
index 3f91db948fd..ecf07ad5bf8 100644
--- a/chromium/third_party/blink/renderer/core/frame/fragment_directive.idl
+++ b/chromium/third_party/blink/renderer/core/frame/fragment_directive.idl
@@ -3,6 +3,8 @@
// found in the LICENSE file.
// https://github.com/WICG/ScrollToTextFragment
-[RuntimeEnabled=TextFragmentIdentifiers]
-interface FragmentDirective {
+[
+ Exposed=Window,
+ RuntimeEnabled=TextFragmentIdentifiers
+] interface FragmentDirective {
};
diff --git a/chromium/third_party/blink/renderer/core/frame/frame.cc b/chromium/third_party/blink/renderer/core/frame/frame.cc
index 4f85a218063..e7f1f74c95a 100644
--- a/chromium/third_party/blink/renderer/core/frame/frame.cc
+++ b/chromium/third_party/blink/renderer/core/frame/frame.cc
@@ -308,6 +308,7 @@ const std::string& Frame::ToTraceValue() {
Frame::Frame(FrameClient* client,
Page& page,
FrameOwner* owner,
+ const base::UnguessableToken& frame_token,
WindowProxyManager* window_proxy_manager,
WindowAgentFactory* inheriting_agent_factory)
: tree_node_(this),
@@ -321,7 +322,8 @@ Frame::Frame(FrameClient* client,
? inheriting_agent_factory
: MakeGarbageCollected<WindowAgentFactory>()),
is_loading_(false),
- devtools_frame_token_(client->GetDevToolsFrameToken()) {
+ devtools_frame_token_(client->GetDevToolsFrameToken()),
+ frame_token_(frame_token) {
InstanceCounters::IncrementCounter(InstanceCounters::kFrameCounter);
}
diff --git a/chromium/third_party/blink/renderer/core/frame/frame.h b/chromium/third_party/blink/renderer/core/frame/frame.h
index d36fb54eb17..bcf52f149d9 100644
--- a/chromium/third_party/blink/renderer/core/frame/frame.h
+++ b/chromium/third_party/blink/renderer/core/frame/frame.h
@@ -271,6 +271,11 @@ class CORE_EXPORT Frame : public GarbageCollected<Frame> {
return *window_agent_factory_;
}
+ // This identifier represents the stable identifier between a
+ // LocalFrame <--> RenderFrameHostImpl or a
+ // RemoteFrame <--> RenderFrameProxyHost in the browser process.
+ const base::UnguessableToken& GetFrameToken() const { return frame_token_; }
+
bool GetVisibleToHitTesting() const { return visible_to_hit_testing_; }
void UpdateVisibleToHitTesting();
@@ -293,6 +298,7 @@ class CORE_EXPORT Frame : public GarbageCollected<Frame> {
Frame(FrameClient*,
Page&,
FrameOwner*,
+ const base::UnguessableToken& frame_token,
WindowProxyManager*,
WindowAgentFactory* inheriting_agent_factory);
@@ -377,6 +383,19 @@ class CORE_EXPORT Frame : public GarbageCollected<Frame> {
// navigation. This is used in autoplay.
bool had_sticky_user_activation_before_nav_ = false;
+ // This identifier represents the stable identifier between a
+ // LocalFrame <--> RenderFrameHostImpl or a
+ // RemoteFrame <--> RenderFrameProxyHost in the browser process.
+ // Note that this identifier is unique per render process and
+ // browser relationship. ie. If this is a LocalFrame, RemoteFrames that
+ // represent this frame node in other processes will *not* have the same
+ // identifier. Similarly, if this is a RemoteFrame, the LocalFrame and
+ // other RemoteFrames that represent this frame node in other processes
+ // will *not* have the same identifier. This is different than the
+ // |devtools_frame_token_| in which all representations of this frame node
+ // have the same value in all processes.
+ base::UnguessableToken frame_token_;
+
// This task is used for the async step in form submission when a form is
// targeting this frame. http://html.spec.whatwg.org/C/#plan-to-navigate
// The reason it is stored here is so that it can handle both LocalFrames and
diff --git a/chromium/third_party/blink/renderer/core/frame/frame_console.cc b/chromium/third_party/blink/renderer/core/frame/frame_console.cc
index 25d8991f8dd..9c14e3a9bd1 100644
--- a/chromium/third_party/blink/renderer/core/frame/frame_console.cc
+++ b/chromium/third_party/blink/renderer/core/frame/frame_console.cc
@@ -31,6 +31,7 @@
#include <memory>
#include "third_party/blink/renderer/bindings/core/v8/source_location.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/inspector/console_message.h"
#include "third_party/blink/renderer/core/inspector/console_message_storage.h"
@@ -57,11 +58,10 @@ void FrameConsole::AddMessage(ConsoleMessage* console_message,
bool FrameConsole::AddMessageToStorage(ConsoleMessage* console_message,
bool discard_duplicates) {
- if (!frame_->GetDocument() || !frame_->GetPage())
+ if (!frame_->DomWindow())
return false;
return frame_->GetPage()->GetConsoleMessageStorage().AddConsoleMessage(
- frame_->GetDocument()->ToExecutionContext(), console_message,
- discard_duplicates);
+ frame_->DomWindow(), console_message, discard_duplicates);
}
void FrameConsole::ReportMessageToClient(mojom::ConsoleMessageSource source,
@@ -118,8 +118,10 @@ void FrameConsole::ReportResourceResponseReceived(
void FrameConsole::DidFailLoading(DocumentLoader* loader,
uint64_t request_identifier,
const ResourceError& error) {
- if (error.IsCancellation()) // Report failures only.
+ // Report failures only.
+ if (error.IsCancellation() || error.IsTrustTokenCacheHit())
return;
+
StringBuilder message;
message.Append("Failed to load resource");
if (!error.LocalizedDescription().IsEmpty()) {
diff --git a/chromium/third_party/blink/renderer/core/frame/frame_overlay.cc b/chromium/third_party/blink/renderer/core/frame/frame_overlay.cc
index 058f16d4b5c..79834d7f276 100644
--- a/chromium/third_party/blink/renderer/core/frame/frame_overlay.cc
+++ b/chromium/third_party/blink/renderer/core/frame/frame_overlay.cc
@@ -75,7 +75,9 @@ void FrameOverlay::UpdatePrePaint() {
}
DCHECK(parent_layer);
- if (layer_->Parent() != parent_layer)
+ if (layer_->Parent() != parent_layer ||
+ // Keep the layer the last child of parent to make it topmost.
+ parent_layer->Children().back() != layer_.get())
parent_layer->AddChild(layer_.get());
layer_->SetLayerState(DefaultPropertyTreeState(), IntPoint());
layer_->SetSize(gfx::Size(Size()));
diff --git a/chromium/third_party/blink/renderer/core/frame/frame_overlay_test.cc b/chromium/third_party/blink/renderer/core/frame/frame_overlay_test.cc
index 62132d741d5..19d9efcc421 100644
--- a/chromium/third_party/blink/renderer/core/frame/frame_overlay_test.cc
+++ b/chromium/third_party/blink/renderer/core/frame/frame_overlay_test.cc
@@ -14,8 +14,10 @@
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
#include "third_party/blink/renderer/core/frame/visual_viewport.h"
#include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
+#include "third_party/blink/renderer/core/layout/layout_view.h"
#include "third_party/blink/renderer/platform/graphics/color.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/drawing_recorder.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_controller.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_controller_test.h"
@@ -162,6 +164,40 @@ TEST_P(FrameOverlayTest, DeviceEmulationScale) {
}
}
+TEST_P(FrameOverlayTest, LayerOrder) {
+ // This test doesn't apply in CompositeAfterPaint.
+ if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
+ return;
+
+ auto frame_overlay1 = CreateSolidYellowOverlay();
+ auto frame_overlay2 = CreateSolidYellowOverlay();
+ frame_overlay1->UpdatePrePaint();
+ frame_overlay2->UpdatePrePaint();
+
+ auto* parent_layer = GetWebView()
+ ->MainFrameImpl()
+ ->GetFrameView()
+ ->GetLayoutView()
+ ->Compositor()
+ ->PaintRootGraphicsLayer();
+ ASSERT_EQ(3u, parent_layer->Children().size());
+ EXPECT_EQ(parent_layer, frame_overlay1->GetGraphicsLayer()->Parent());
+ EXPECT_EQ(parent_layer->Children()[1], frame_overlay1->GetGraphicsLayer());
+ EXPECT_EQ(parent_layer, frame_overlay2->GetGraphicsLayer()->Parent());
+ EXPECT_EQ(parent_layer->Children()[2], frame_overlay2->GetGraphicsLayer());
+
+ auto extra_layer = std::make_unique<GraphicsLayer>(parent_layer->Client());
+ parent_layer->AddChild(extra_layer.get());
+
+ frame_overlay1->UpdatePrePaint();
+ frame_overlay2->UpdatePrePaint();
+ ASSERT_EQ(4u, parent_layer->Children().size());
+ EXPECT_EQ(parent_layer, frame_overlay1->GetGraphicsLayer()->Parent());
+ EXPECT_EQ(parent_layer->Children()[2], frame_overlay1->GetGraphicsLayer());
+ EXPECT_EQ(parent_layer, frame_overlay2->GetGraphicsLayer()->Parent());
+ EXPECT_EQ(parent_layer->Children()[3], frame_overlay2->GetGraphicsLayer());
+}
+
TEST_P(FrameOverlayTest, VisualRect) {
std::unique_ptr<FrameOverlay> frame_overlay = CreateSolidYellowOverlay();
frame_overlay->UpdatePrePaint();
diff --git a/chromium/third_party/blink/renderer/core/frame/frame_serializer.cc b/chromium/third_party/blink/renderer/core/frame/frame_serializer.cc
index eabf1e156b3..9b434d7397d 100644
--- a/chromium/third_party/blink/renderer/core/frame/frame_serializer.cc
+++ b/chromium/third_party/blink/renderer/core/frame/frame_serializer.cc
@@ -620,19 +620,8 @@ void FrameSerializer::RetrieveResourcesForCSSValue(const CSSValue& css_value,
if (font_face_src_value->IsLocal())
return;
- if (document.ImportsController()) {
- if (Document* context_document = document.ContextDocument()) {
- // For @imports from HTML imported Documents, we use the
- // context document for getting origin and ResourceFetcher to use the
- // main Document's origin, while using the element document for
- // CompleteURL() to use imported Documents' base URLs.
- AddFontToResources(font_face_src_value->Fetch(
- context_document->ToExecutionContext(), nullptr));
- }
- } else {
- AddFontToResources(
- font_face_src_value->Fetch(document.ToExecutionContext(), nullptr));
- }
+ AddFontToResources(
+ font_face_src_value->Fetch(document.GetExecutionContext(), nullptr));
} else if (const auto* css_value_list = DynamicTo<CSSValueList>(css_value)) {
for (unsigned i = 0; i < css_value_list->length(); i++)
RetrieveResourcesForCSSValue(css_value_list->Item(i), document);
diff --git a/chromium/third_party/blink/renderer/core/frame/frame_serializer_test.cc b/chromium/third_party/blink/renderer/core/frame/frame_serializer_test.cc
index 9ba3b657096..00c020825e2 100644
--- a/chromium/third_party/blink/renderer/core/frame/frame_serializer_test.cc
+++ b/chromium/third_party/blink/renderer/core/frame/frame_serializer_test.cc
@@ -100,7 +100,7 @@ class FrameSerializerTest : public testing::Test,
response.SetHttpStatusCode(status_code);
platform_->GetURLLoaderMockFactory()->RegisterErrorURL(
- KURL(base_url_, file), response, error);
+ KURL(base_url_, file), response, WebURLError(error));
}
void RegisterRewriteURL(const char* from_url, const char* to_url) {
diff --git a/chromium/third_party/blink/renderer/core/frame/frame_test_helpers.cc b/chromium/third_party/blink/renderer/core/frame/frame_test_helpers.cc
index e3a9ffc405a..1800471a1a3 100644
--- a/chromium/third_party/blink/renderer/core/frame/frame_test_helpers.cc
+++ b/chromium/third_party/blink/renderer/core/frame/frame_test_helpers.cc
@@ -40,9 +40,11 @@
#include "cc/trees/layer_tree_host.h"
#include "cc/trees/layer_tree_settings.h"
#include "cc/trees/render_frame_metadata_observer.h"
+#include "mojo/public/cpp/bindings/pending_associated_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
#include "third_party/blink/public/common/frame/frame_policy.h"
+#include "third_party/blink/public/mojom/frame/tree_scope_type.mojom-blink.h"
#include "third_party/blink/public/platform/interface_registry.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/web_data.h"
@@ -54,7 +56,6 @@
#include "third_party/blink/public/web/web_frame_widget.h"
#include "third_party/blink/public/web/web_navigation_params.h"
#include "third_party/blink/public/web/web_settings.h"
-#include "third_party/blink/public/web/web_tree_scope_type.h"
#include "third_party/blink/public/web/web_view_client.h"
#include "third_party/blink/renderer/core/exported/web_remote_frame_impl.h"
#include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
@@ -115,6 +116,15 @@ T* CreateDefaultClientIfNeeded(T* client, std::unique_ptr<T>& owned_client) {
} // namespace
+cc::LayerTreeSettings GetSynchronousSingleThreadLayerTreeSettings() {
+ cc::LayerTreeSettings settings;
+ // Use synchronous compositing so that the MessageLoop becomes idle and the
+ // test makes progress.
+ settings.single_thread_proxy_scheduler = false;
+ settings.use_layer_lists = true;
+ return settings;
+}
+
void LoadFrameDontWait(WebLocalFrame* frame, const WebURL& url) {
auto* impl = To<WebLocalFrameImpl>(frame);
if (url.ProtocolIs("javascript")) {
@@ -206,24 +216,24 @@ WebMouseEvent CreateMouseEvent(WebInputEvent::Type type,
}
WebLocalFrameImpl* CreateLocalChild(WebLocalFrame& parent,
- WebTreeScopeType scope,
+ mojom::blink::TreeScopeType scope,
TestWebFrameClient* client) {
std::unique_ptr<TestWebFrameClient> owned_client;
client = CreateDefaultClientIfNeeded(client, owned_client);
- auto* frame =
- To<WebLocalFrameImpl>(parent.CreateLocalChild(scope, client, nullptr));
+ auto* frame = To<WebLocalFrameImpl>(parent.CreateLocalChild(
+ scope, client, nullptr, base::UnguessableToken::Create()));
client->Bind(frame, std::move(owned_client));
return frame;
}
WebLocalFrameImpl* CreateLocalChild(
WebLocalFrame& parent,
- WebTreeScopeType scope,
+ mojom::blink::TreeScopeType scope,
std::unique_ptr<TestWebFrameClient> self_owned) {
DCHECK(self_owned);
TestWebFrameClient* client = self_owned.get();
- auto* frame =
- To<WebLocalFrameImpl>(parent.CreateLocalChild(scope, client, nullptr));
+ auto* frame = To<WebLocalFrameImpl>(parent.CreateLocalChild(
+ scope, client, nullptr, base::UnguessableToken::Create()));
client->Bind(frame, std::move(self_owned));
return frame;
}
@@ -233,37 +243,54 @@ WebLocalFrameImpl* CreateProvisional(WebRemoteFrame& old_frame,
std::unique_ptr<TestWebFrameClient> owned_client;
client = CreateDefaultClientIfNeeded(client, owned_client);
auto* frame = To<WebLocalFrameImpl>(WebLocalFrame::CreateProvisional(
- client, nullptr, &old_frame, FramePolicy(),
- WebFrame::ToCoreFrame(old_frame)->Tree().GetName()));
+ client, nullptr, base::UnguessableToken::Create(), &old_frame,
+ FramePolicy(), WebFrame::ToCoreFrame(old_frame)->Tree().GetName()));
client->Bind(frame, std::move(owned_client));
std::unique_ptr<TestWebWidgetClient> widget_client;
+
+ mojo::AssociatedRemote<mojom::blink::FrameWidget> frame_widget_remote;
+ mojo::PendingAssociatedReceiver<mojom::blink::FrameWidget>
+ frame_widget_receiver =
+ frame_widget_remote
+ .BindNewEndpointAndPassDedicatedReceiverForTesting();
+
+ mojo::AssociatedRemote<mojom::blink::FrameWidgetHost> frame_widget_host;
+ mojo::PendingAssociatedReceiver<mojom::blink::FrameWidgetHost>
+ frame_widget_host_receiver =
+ frame_widget_host.BindNewEndpointAndPassDedicatedReceiverForTesting();
+
// Create a local root, if necessary.
if (!frame->Parent()) {
widget_client = std::make_unique<TestWebWidgetClient>();
// TODO(dcheng): The main frame widget currently has a special case.
// Eliminate this once WebView is no longer a WebWidget.
WebFrameWidget* frame_widget = WebFrameWidget::CreateForMainFrame(
- widget_client.get(), frame,
- CrossVariantMojoAssociatedRemote<mojom::FrameWidgetHostInterfaceBase>(),
- CrossVariantMojoAssociatedReceiver<mojom::FrameWidgetInterfaceBase>(),
+ widget_client.get(), frame, frame_widget_host.Unbind(),
+ std::move(frame_widget_receiver),
CrossVariantMojoAssociatedRemote<mojom::WidgetHostInterfaceBase>(),
CrossVariantMojoAssociatedReceiver<mojom::WidgetInterfaceBase>());
widget_client->SetFrameWidget(frame_widget);
// The WebWidget requires the compositor to be set before it is used.
- frame_widget->SetCompositorHosts(widget_client->layer_tree_host(),
- widget_client->animation_host());
+ widget_client->set_layer_tree_host(frame_widget->InitializeCompositing(
+ widget_client->task_graph_runner(),
+ GetSynchronousSingleThreadLayerTreeSettings(),
+ std::make_unique<cc::TestUkmRecorderFactory>()));
+ frame_widget->SetCompositorVisible(true);
} else if (frame->Parent()->IsWebRemoteFrame()) {
widget_client = std::make_unique<TestWebWidgetClient>();
+
WebFrameWidget* frame_widget = WebFrameWidget::CreateForChildLocalRoot(
- widget_client.get(), frame,
- CrossVariantMojoAssociatedRemote<mojom::FrameWidgetHostInterfaceBase>(),
- CrossVariantMojoAssociatedReceiver<mojom::FrameWidgetInterfaceBase>(),
+ widget_client.get(), frame, frame_widget_host.Unbind(),
+ std::move(frame_widget_receiver),
CrossVariantMojoAssociatedRemote<mojom::WidgetHostInterfaceBase>(),
CrossVariantMojoAssociatedReceiver<mojom::WidgetInterfaceBase>());
widget_client->SetFrameWidget(frame_widget);
// The WebWidget requires the compositor to be set before it is used.
- frame_widget->SetCompositorHosts(widget_client->layer_tree_host(),
- widget_client->animation_host());
+ widget_client->set_layer_tree_host(frame_widget->InitializeCompositing(
+ widget_client->task_graph_runner(),
+ GetSynchronousSingleThreadLayerTreeSettings(),
+ std::make_unique<cc::TestUkmRecorderFactory>()));
+ frame_widget->SetCompositorVisible(true);
frame_widget->Resize(WebSize());
}
if (widget_client)
@@ -275,9 +302,10 @@ WebRemoteFrameImpl* CreateRemote(TestWebRemoteFrameClient* client) {
std::unique_ptr<TestWebRemoteFrameClient> owned_client;
client = CreateDefaultClientIfNeeded(client, owned_client);
auto* frame = MakeGarbageCollected<WebRemoteFrameImpl>(
- WebTreeScopeType::kDocument, client,
+ mojom::blink::TreeScopeType::kDocument, client,
InterfaceRegistry::GetEmptyInterfaceRegistry(),
- client->GetAssociatedInterfaceProvider());
+ client->GetAssociatedInterfaceProvider(),
+ base::UnguessableToken::Create());
client->Bind(frame, std::move(owned_client));
return frame;
}
@@ -291,23 +319,39 @@ WebLocalFrameImpl* CreateLocalChild(WebRemoteFrame& parent,
std::unique_ptr<TestWebFrameClient> owned_client;
client = CreateDefaultClientIfNeeded(client, owned_client);
auto* frame = To<WebLocalFrameImpl>(parent.CreateLocalChild(
- WebTreeScopeType::kDocument, name, FramePolicy(), client, nullptr,
- previous_sibling, properties, FrameOwnerElementType::kIframe, nullptr));
+ mojom::blink::TreeScopeType::kDocument, name, FramePolicy(), client,
+ nullptr, previous_sibling, properties,
+ mojom::blink::FrameOwnerElementType::kIframe,
+ base::UnguessableToken::Create(), nullptr));
client->Bind(frame, std::move(owned_client));
std::unique_ptr<TestWebWidgetClient> owned_widget_client;
widget_client =
CreateDefaultClientIfNeeded(widget_client, owned_widget_client);
+
+ mojo::AssociatedRemote<mojom::blink::FrameWidget> frame_widget_remote;
+ mojo::PendingAssociatedReceiver<mojom::blink::FrameWidget>
+ frame_widget_receiver =
+ frame_widget_remote
+ .BindNewEndpointAndPassDedicatedReceiverForTesting();
+
+ mojo::AssociatedRemote<mojom::blink::FrameWidgetHost> frame_widget_host;
+ mojo::PendingAssociatedReceiver<mojom::blink::FrameWidgetHost>
+ frame_widget_host_receiver =
+ frame_widget_host.BindNewEndpointAndPassDedicatedReceiverForTesting();
+
WebFrameWidget* frame_widget = WebFrameWidget::CreateForChildLocalRoot(
- widget_client, frame,
- CrossVariantMojoAssociatedRemote<mojom::FrameWidgetHostInterfaceBase>(),
- CrossVariantMojoAssociatedReceiver<mojom::FrameWidgetInterfaceBase>(),
+ widget_client, frame, frame_widget_host.Unbind(),
+ std::move(frame_widget_receiver),
CrossVariantMojoAssociatedRemote<mojom::WidgetHostInterfaceBase>(),
CrossVariantMojoAssociatedReceiver<mojom::WidgetInterfaceBase>());
// The WebWidget requires the compositor to be set before it is used.
- frame_widget->SetCompositorHosts(widget_client->layer_tree_host(),
- widget_client->animation_host());
widget_client->SetFrameWidget(frame_widget);
+ widget_client->set_layer_tree_host(frame_widget->InitializeCompositing(
+ widget_client->task_graph_runner(),
+ GetSynchronousSingleThreadLayerTreeSettings(),
+ std::make_unique<cc::TestUkmRecorderFactory>()));
+ frame_widget->SetCompositorVisible(true);
// Set an initial size for subframes.
if (frame->Parent())
frame_widget->Resize(WebSize());
@@ -323,10 +367,11 @@ WebRemoteFrameImpl* CreateRemoteChild(
std::unique_ptr<TestWebRemoteFrameClient> owned_client;
client = CreateDefaultClientIfNeeded(client, owned_client);
auto* frame = To<WebRemoteFrameImpl>(parent.CreateRemoteChild(
- WebTreeScopeType::kDocument, name, FramePolicy(),
- FrameOwnerElementType::kIframe, client,
+ mojom::blink::TreeScopeType::kDocument, name, FramePolicy(),
+ mojom::blink::FrameOwnerElementType::kIframe, client,
InterfaceRegistry::GetEmptyInterfaceRegistry(),
- client->GetAssociatedInterfaceProvider(), nullptr));
+ client->GetAssociatedInterfaceProvider(),
+ base::UnguessableToken::Create(), nullptr));
client->Bind(frame, std::move(owned_client));
if (!security_origin)
security_origin = SecurityOrigin::CreateUniqueOpaque();
@@ -358,24 +403,39 @@ WebViewImpl* WebViewHelper::InitializeWithOpener(
std::unique_ptr<TestWebFrameClient> owned_web_frame_client;
web_frame_client =
CreateDefaultClientIfNeeded(web_frame_client, owned_web_frame_client);
- WebLocalFrame* frame = WebLocalFrame::CreateMainFrame(
- web_view_, web_frame_client, nullptr, opener);
+ WebLocalFrame* frame =
+ WebLocalFrame::CreateMainFrame(web_view_, web_frame_client, nullptr,
+ base::UnguessableToken::Create(), opener);
web_frame_client->Bind(frame, std::move(owned_web_frame_client));
test_web_widget_client_ = CreateDefaultClientIfNeeded(
web_widget_client, owned_test_web_widget_client_);
+
+ mojo::AssociatedRemote<mojom::blink::FrameWidget> frame_widget;
+ mojo::PendingAssociatedReceiver<mojom::blink::FrameWidget>
+ frame_widget_receiver =
+ frame_widget.BindNewEndpointAndPassDedicatedReceiverForTesting();
+
+ mojo::AssociatedRemote<mojom::blink::FrameWidgetHost> frame_widget_host;
+ mojo::PendingAssociatedReceiver<mojom::blink::FrameWidgetHost>
+ frame_widget_host_receiver =
+ frame_widget_host.BindNewEndpointAndPassDedicatedReceiverForTesting();
+
// TODO(dcheng): The main frame widget currently has a special case.
// Eliminate this once WebView is no longer a WebWidget.
WebFrameWidget* widget = blink::WebFrameWidget::CreateForMainFrame(
- test_web_widget_client_, frame,
- CrossVariantMojoAssociatedRemote<mojom::FrameWidgetHostInterfaceBase>(),
- CrossVariantMojoAssociatedReceiver<mojom::FrameWidgetInterfaceBase>(),
+ test_web_widget_client_, frame, frame_widget_host.Unbind(),
+ std::move(frame_widget_receiver),
CrossVariantMojoAssociatedRemote<mojom::WidgetHostInterfaceBase>(),
CrossVariantMojoAssociatedReceiver<mojom::WidgetInterfaceBase>());
// The WebWidget requires the compositor to be set before it is used.
- widget->SetCompositorHosts(test_web_widget_client_->layer_tree_host(),
- test_web_widget_client_->animation_host());
test_web_widget_client_->SetFrameWidget(widget);
+ test_web_widget_client_->set_layer_tree_host(widget->InitializeCompositing(
+ test_web_widget_client_->task_graph_runner(),
+ GetSynchronousSingleThreadLayerTreeSettings(),
+ std::make_unique<cc::TestUkmRecorderFactory>()));
+ widget->SetCompositorVisible(true);
+
// We inform the WebView when it has a local main frame attached once the
// WebFrame it fully set up and the WebWidgetClient is initialized (which is
// the case by this point).
@@ -445,7 +505,8 @@ WebViewImpl* WebViewHelper::InitializeRemoteWithOpener(
WebRemoteFrameImpl* frame = WebRemoteFrameImpl::CreateMainFrame(
web_view_, web_remote_frame_client,
InterfaceRegistry::GetEmptyInterfaceRegistry(),
- web_remote_frame_client->GetAssociatedInterfaceProvider(), opener);
+ web_remote_frame_client->GetAssociatedInterfaceProvider(),
+ base::UnguessableToken::Create(), opener);
web_remote_frame_client->Bind(frame,
std::move(owned_web_remote_frame_client));
if (!security_origin)
@@ -495,11 +556,10 @@ void WebViewHelper::InitializeWebView(TestWebViewClient* web_view_client,
class WebView* opener) {
test_web_view_client_ =
CreateDefaultClientIfNeeded(web_view_client, owned_test_web_view_client_);
- web_view_ = static_cast<WebViewImpl*>(
- WebView::Create(test_web_view_client_,
- /*is_hidden=*/false,
- /*compositing_enabled=*/true, opener,
- mojo::ScopedInterfaceEndpointHandle()));
+ web_view_ = static_cast<WebViewImpl*>(WebView::Create(
+ test_web_view_client_,
+ /*is_hidden=*/false,
+ /*compositing_enabled=*/true, opener, mojo::NullAssociatedReceiver()));
// This property must be set at initialization time, it is not supported to be
// changed afterward, and does nothing.
web_view_->GetSettings()->SetViewportEnabled(viewport_enabled_);
@@ -557,12 +617,12 @@ void TestWebFrameClient::FrameDetached(DetachType type) {
WebLocalFrame* TestWebFrameClient::CreateChildFrame(
WebLocalFrame* parent,
- WebTreeScopeType scope,
+ mojom::blink::TreeScopeType scope,
const WebString& name,
const WebString& fallback_name,
const FramePolicy&,
const WebFrameOwnerProperties& frame_owner_properties,
- FrameOwnerElementType owner_type) {
+ mojom::blink::FrameOwnerElementType owner_type) {
return CreateLocalChild(*parent, scope);
}
@@ -649,28 +709,7 @@ void TestWebRemoteFrameClient::FrameDetached(DetachType type) {
self_owned_.reset();
}
-content::LayerTreeView* LayerTreeViewFactory::Initialize(
- content::LayerTreeViewDelegate* specified_delegate) {
- cc::LayerTreeSettings settings;
- // Use synchronous compositing so that the MessageLoop becomes idle and the
- // test makes progress.
- settings.single_thread_proxy_scheduler = false;
- settings.use_layer_lists = true;
-
- layer_tree_view_ = std::make_unique<content::LayerTreeView>(
- specified_delegate, Thread::Current()->GetTaskRunner(),
- /*compositor_thread=*/nullptr, &test_task_graph_runner_,
- &fake_thread_scheduler_);
- layer_tree_view_->Initialize(settings,
- std::make_unique<cc::TestUkmRecorderFactory>());
- layer_tree_view_->SetVisible(true);
- return layer_tree_view_.get();
-}
-
-TestWebWidgetClient::TestWebWidgetClient() {
- layer_tree_view_ = layer_tree_view_factory_.Initialize(this);
- animation_host_ = layer_tree_view_->animation_host();
-}
+TestWebWidgetClient::TestWebWidgetClient() = default;
void TestWebWidgetClient::SetFrameWidget(WebFrameWidget* widget) {
frame_widget_ = widget;
@@ -719,23 +758,6 @@ viz::FrameSinkId TestWebWidgetClient::GetFrameSinkId() {
return viz::FrameSinkId();
}
-void TestWebWidgetClient::BeginMainFrame(base::TimeTicks frame_time) {
- frame_widget_->BeginFrame(frame_time);
-}
-
-void TestWebWidgetClient::DidBeginMainFrame() {
- frame_widget_->DidBeginFrame();
-}
-
-void TestWebWidgetClient::UpdateVisualState() {
- frame_widget_->UpdateVisualState();
-}
-
-void TestWebWidgetClient::ApplyViewportChanges(
- const ApplyViewportChangesArgs& args) {
- frame_widget_->ApplyViewportChanges(args);
-}
-
void TestWebWidgetClient::RequestNewLayerTreeFrameSink(
LayerTreeFrameSinkCallback callback) {
// Make a valid LayerTreeFrameSink so the compositor will generate begin main
@@ -752,7 +774,7 @@ WebView* TestWebViewClient::CreateView(WebLocalFrame* opener,
const WebWindowFeatures&,
const WebString& name,
WebNavigationPolicy,
- mojom::blink::WebSandboxFlags,
+ network::mojom::blink::WebSandboxFlags,
const FeaturePolicy::FeatureState&,
const SessionStorageNamespaceId&) {
auto webview_helper = std::make_unique<WebViewHelper>();
diff --git a/chromium/third_party/blink/renderer/core/frame/frame_test_helpers.h b/chromium/third_party/blink/renderer/core/frame/frame_test_helpers.h
index 35504d96582..dc312fbf279 100644
--- a/chromium/third_party/blink/renderer/core/frame/frame_test_helpers.h
+++ b/chromium/third_party/blink/renderer/core/frame/frame_test_helpers.h
@@ -40,11 +40,10 @@
#include "base/memory/weak_ptr.h"
#include "cc/test/test_task_graph_runner.h"
#include "cc/trees/layer_tree_host.h"
-#include "content/renderer/compositor/layer_tree_view.h"
-#include "content/test/stub_layer_tree_view_delegate.h"
-#include "third_party/blink/public/common/frame/frame_owner_element_type.h"
#include "third_party/blink/public/common/input/web_mouse_event.h"
#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink-forward.h"
+#include "third_party/blink/public/mojom/frame/frame_owner_element_type.mojom-blink.h"
+#include "third_party/blink/public/mojom/frame/tree_scope_type.mojom-blink.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/scheduler/test/web_fake_thread_scheduler.h"
#include "third_party/blink/public/platform/web_string.h"
@@ -87,10 +86,6 @@ namespace base {
class TickClock;
}
-namespace cc {
-class AnimationHost;
-}
-
namespace blink {
class WebFrame;
class WebLocalFrameImpl;
@@ -105,6 +100,8 @@ class TestWebWidgetClient;
class TestWebViewClient;
class WebViewHelper;
+cc::LayerTreeSettings GetSynchronousSingleThreadLayerTreeSettings();
+
// Loads a url into the specified WebLocalFrame for testing purposes.
void LoadFrameDontWait(WebLocalFrame*, const WebURL& url);
// Same as above, but also pumps any pending resource requests,
@@ -143,14 +140,14 @@ WebMouseEvent CreateMouseEvent(WebInputEvent::Type,
// Helper for creating a local child frame of a local parent frame.
WebLocalFrameImpl* CreateLocalChild(WebLocalFrame& parent,
- WebTreeScopeType,
+ blink::mojom::blink::TreeScopeType,
TestWebFrameClient* = nullptr);
// Similar, but unlike the overload which takes the client as a raw pointer,
// ownership of the TestWebFrameClient is transferred to the test framework.
// TestWebFrameClient may not be null.
WebLocalFrameImpl* CreateLocalChild(WebLocalFrame& parent,
- WebTreeScopeType,
+ blink::mojom::blink::TreeScopeType,
std::unique_ptr<TestWebFrameClient>);
// Helper for creating a provisional local frame that can replace a remote
@@ -179,21 +176,6 @@ WebRemoteFrameImpl* CreateRemoteChild(WebRemoteFrame& parent,
scoped_refptr<SecurityOrigin> = nullptr,
TestWebRemoteFrameClient* = nullptr);
-// A class that constructs and owns a LayerTreeView for blink
-// unit tests.
-class LayerTreeViewFactory {
- DISALLOW_NEW();
-
- public:
- // Use this to specify a delegate instead of using a stub.
- content::LayerTreeView* Initialize(content::LayerTreeViewDelegate*);
-
- private:
- cc::TestTaskGraphRunner test_task_graph_runner_;
- blink::scheduler::WebFakeThreadScheduler fake_thread_scheduler_;
- std::unique_ptr<content::LayerTreeView> layer_tree_view_;
-};
-
struct InjectedScrollGestureData {
gfx::Vector2dF delta;
ScrollGranularity granularity;
@@ -201,8 +183,7 @@ struct InjectedScrollGestureData {
WebInputEvent::Type type;
};
-class TestWebWidgetClient : public WebWidgetClient,
- public content::StubLayerTreeViewDelegate {
+class TestWebWidgetClient : public WebWidgetClient {
public:
TestWebWidgetClient();
~TestWebWidgetClient() override = default;
@@ -211,27 +192,8 @@ class TestWebWidgetClient : public WebWidgetClient,
// before usage of this class occurs.
void SetFrameWidget(WebFrameWidget* widget);
- // WebWidgetClient implementation.
- void ScheduleAnimation() override { animation_scheduled_ = true; }
- void SetPageScaleStateAndLimits(float page_scale_factor,
- bool is_pinch_gesture_active,
- float minimum,
- float maximum) override;
- void InjectGestureScrollEvent(WebGestureDevice device,
- const gfx::Vector2dF& delta,
- ScrollGranularity granularity,
- cc::ElementId scrollable_area_element_id,
- WebInputEvent::Type injected_type) override;
- void DidMeaningfulLayout(WebMeaningfulLayout) override;
- viz::FrameSinkId GetFrameSinkId() override;
-
- cc::LayerTreeHost* layer_tree_host() {
- return layer_tree_view_->layer_tree_host();
- }
- const cc::LayerTreeHost* layer_tree_host() const {
- return layer_tree_view_->layer_tree_host();
- }
- cc::AnimationHost* animation_host() { return animation_host_; }
+ cc::LayerTreeHost* layer_tree_host() { return layer_tree_host_; }
+ const cc::LayerTreeHost* layer_tree_host() const { return layer_tree_host_; }
bool AnimationScheduled() const { return animation_scheduled_; }
void ClearAnimationScheduled() { animation_scheduled_ = false; }
@@ -252,20 +214,34 @@ class TestWebWidgetClient : public WebWidgetClient,
return injected_scroll_gesture_data_;
}
+ cc::TaskGraphRunner* task_graph_runner() { return &test_task_graph_runner_; }
+
+ void set_layer_tree_host(cc::LayerTreeHost* layer_tree_host) {
+ layer_tree_host_ = layer_tree_host;
+ }
+
protected:
- // LayerTreeViewDelegate implementation.
- void BeginMainFrame(base::TimeTicks frame_time) override;
- void DidBeginMainFrame() override;
- void UpdateVisualState() override;
- void ApplyViewportChanges(const ApplyViewportChangesArgs& args) override;
+ // WebWidgetClient overrides;
+ void ScheduleAnimation() override { animation_scheduled_ = true; }
+ void SetPageScaleStateAndLimits(float page_scale_factor,
+ bool is_pinch_gesture_active,
+ float minimum,
+ float maximum) override;
+ void InjectGestureScrollEvent(WebGestureDevice device,
+ const gfx::Vector2dF& delta,
+ ScrollGranularity granularity,
+ cc::ElementId scrollable_area_element_id,
+ WebInputEvent::Type injected_type) override;
+ void DidMeaningfulLayout(WebMeaningfulLayout) override;
+ viz::FrameSinkId GetFrameSinkId() override;
void RequestNewLayerTreeFrameSink(
LayerTreeFrameSinkCallback callback) override;
private:
WebFrameWidget* frame_widget_ = nullptr;
- content::LayerTreeView* layer_tree_view_ = nullptr;
- cc::AnimationHost* animation_host_ = nullptr;
- LayerTreeViewFactory layer_tree_view_factory_;
+ cc::LayerTreeHost* layer_tree_host_ = nullptr;
+ cc::TestTaskGraphRunner test_task_graph_runner_;
+ blink::scheduler::WebFakeThreadScheduler fake_thread_scheduler_;
Vector<InjectedScrollGestureData> injected_scroll_gesture_data_;
bool animation_scheduled_ = false;
int visually_non_empty_layout_count_ = 0;
@@ -288,12 +264,11 @@ class TestWebViewClient : public WebViewClient {
const WebWindowFeatures&,
const WebString& name,
WebNavigationPolicy,
- mojom::blink::WebSandboxFlags,
+ network::mojom::blink::WebSandboxFlags,
const FeaturePolicy::FeatureState&,
const SessionStorageNamespaceId&) override;
private:
- LayerTreeViewFactory layer_tree_view_factory_;
WTF::Vector<std::unique_ptr<WebViewHelper>> child_web_views_;
};
@@ -424,12 +399,12 @@ class TestWebFrameClient : public WebLocalFrameClient {
// WebLocalFrameClient:
void FrameDetached(DetachType) override;
WebLocalFrame* CreateChildFrame(WebLocalFrame* parent,
- WebTreeScopeType,
+ blink::mojom::blink::TreeScopeType,
const WebString& name,
const WebString& fallback_name,
const FramePolicy&,
const WebFrameOwnerProperties&,
- FrameOwnerElementType) override;
+ mojom::blink::FrameOwnerElementType) override;
void DidStartLoading() override;
void DidStopLoading() override;
std::unique_ptr<blink::WebURLLoaderFactory> CreateURLLoaderFactory()
diff --git a/chromium/third_party/blink/renderer/core/frame/history.cc b/chromium/third_party/blink/renderer/core/frame/history.cc
index 8a9110005b6..e21cc0f38a8 100644
--- a/chromium/third_party/blink/renderer/core/frame/history.cc
+++ b/chromium/third_party/blink/renderer/core/frame/history.cc
@@ -25,9 +25,13 @@
#include "third_party/blink/renderer/core/frame/history.h"
+#include "third_party/blink/public/common/privacy_budget/identifiability_metric_builder.h"
+#include "third_party/blink/public/common/privacy_budget/identifiability_metrics.h"
+#include "third_party/blink/public/mojom/web_feature/web_feature.mojom-shared.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/frame/frame_console.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/local_frame_client.h"
#include "third_party/blink/renderer/core/frame/settings.h"
@@ -61,11 +65,11 @@ bool EqualIgnoringQueryAndFragment(const KURL& a, const KURL& b) {
} // namespace
History::History(LocalFrame* frame)
- : DOMWindowClient(frame), last_state_object_requested_(nullptr) {}
+ : ExecutionContextClient(frame), last_state_object_requested_(nullptr) {}
void History::Trace(Visitor* visitor) {
ScriptWrappable::Trace(visitor);
- DOMWindowClient::Trace(visitor);
+ ExecutionContextClient::Trace(visitor);
}
unsigned History::length(ExceptionState& exception_state) const {
@@ -75,22 +79,52 @@ unsigned History::length(ExceptionState& exception_state) const {
"fully active");
return 0;
}
- return GetFrame()->Client()->BackForwardLength();
+
+ unsigned result = GetFrame()->Client()->BackForwardLength();
+ Document* document = DomWindow()->document();
+ IdentifiabilityMetricBuilder(document->UkmSourceID())
+ .SetWebfeature(WebFeature::kHistoryLength,
+ IdentifiabilityDigestHelper(result))
+ .Record(document->UkmRecorder());
+ return result;
}
-ScriptValue History::state(v8::Isolate* isolate,
+ScriptValue History::state(ScriptState* script_state,
ExceptionState& exception_state) {
+ v8::Isolate* isolate = script_state->GetIsolate();
+ static const V8PrivateProperty::SymbolKey kHistoryStatePrivateProperty;
+ auto private_prop =
+ V8PrivateProperty::GetSymbol(isolate, kHistoryStatePrivateProperty);
+ v8::Local<v8::Object> v8_history = ToV8(this, script_state).As<v8::Object>();
+ v8::Local<v8::Value> v8_state;
+
+ // Returns the same V8 value unless the history gets updated. This
+ // implementation is mostly the same as the one of [CachedAttribute], but
+ // it's placed in this function rather than in Blink-V8 bindings layer so
+ // that PopStateEvent.state can also access the same V8 value.
+ scoped_refptr<SerializedScriptValue> current_state = StateInternal();
+ if (last_state_object_requested_ == current_state) {
+ if (!private_prop.GetOrUndefined(v8_history).ToLocal(&v8_state))
+ return ScriptValue::CreateNull(isolate);
+ if (!v8_state->IsUndefined())
+ return ScriptValue(isolate, v8_state);
+ }
+
if (!GetFrame()) {
exception_state.ThrowSecurityError(
- "May not use a History object associated with a Document that is not "
- "fully active");
- return ScriptValue::CreateNull(isolate);
+ "May not use a History object associated with a Document that is "
+ "not fully active");
+ v8_state = v8::Null(isolate);
+ } else if (!current_state) {
+ v8_state = v8::Null(isolate);
+ } else {
+ ScriptState::EscapableScope target_context_scope(script_state);
+ v8_state = target_context_scope.Escape(current_state->Deserialize(isolate));
}
- last_state_object_requested_ = StateInternal();
- if (!last_state_object_requested_)
- return ScriptValue::CreateNull(isolate);
- return ScriptValue(isolate,
- last_state_object_requested_->Deserialize(isolate));
+
+ last_state_object_requested_ = current_state;
+ private_prop.Set(v8_history, v8_state);
+ return ScriptValue(isolate, v8_state);
}
SerializedScriptValue* History::StateInternal() const {
@@ -156,10 +190,6 @@ HistoryScrollRestorationType History::ScrollRestorationInternal() const {
return history_item->ScrollRestorationType();
}
-bool History::stateChanged() const {
- return last_state_object_requested_ != StateInternal();
-}
-
bool History::IsSameAsCurrentState(SerializedScriptValue* state) const {
return state == StateInternal();
}
@@ -184,14 +214,13 @@ void History::go(ScriptState* script_state,
}
DCHECK(IsMainThread());
- Document* active_document =
- Document::From(ExecutionContext::From(script_state));
- if (!active_document)
+ auto* active_window = LocalDOMWindow::From(script_state);
+ if (!active_window)
return;
- if (!active_document->GetFrame() ||
- !active_document->GetFrame()->CanNavigate(*GetFrame()) ||
- !active_document->GetFrame()->IsNavigationAllowed() ||
+ if (!active_window->GetFrame() ||
+ !active_window->GetFrame()->CanNavigate(*GetFrame()) ||
+ !active_window->GetFrame()->IsNavigationAllowed() ||
!GetFrame()->IsNavigationAllowed()) {
return;
}
diff --git a/chromium/third_party/blink/renderer/core/frame/history.h b/chromium/third_party/blink/renderer/core/frame/history.h
index a08a0f66f40..8621718a727 100644
--- a/chromium/third_party/blink/renderer/core/frame/history.h
+++ b/chromium/third_party/blink/renderer/core/frame/history.h
@@ -45,7 +45,7 @@ class ScriptState;
// This class corresponds to the History interface.
class CORE_EXPORT History final : public ScriptWrappable,
- public DOMWindowClient {
+ public ExecutionContextClient {
DEFINE_WRAPPERTYPEINFO();
USING_GARBAGE_COLLECTED_MIXIN(History);
@@ -53,7 +53,7 @@ class CORE_EXPORT History final : public ScriptWrappable,
explicit History(LocalFrame*);
unsigned length(ExceptionState&) const;
- ScriptValue state(v8::Isolate*, ExceptionState&);
+ ScriptValue state(ScriptState*, ExceptionState&);
void back(ScriptState*, ExceptionState&);
void forward(ScriptState*, ExceptionState&);
@@ -74,7 +74,6 @@ class CORE_EXPORT History final : public ScriptWrappable,
void setScrollRestoration(const String& value, ExceptionState&);
String scrollRestoration(ExceptionState&);
- bool stateChanged() const;
bool IsSameAsCurrentState(SerializedScriptValue*) const;
void Trace(Visitor*) override;
diff --git a/chromium/third_party/blink/renderer/core/frame/history.idl b/chromium/third_party/blink/renderer/core/frame/history.idl
index a2b8ebd6d6a..7bf5beeb13e 100644
--- a/chromium/third_party/blink/renderer/core/frame/history.idl
+++ b/chromium/third_party/blink/renderer/core/frame/history.idl
@@ -32,7 +32,7 @@ enum ScrollRestoration {"auto", "manual"};
] interface History {
[MeasureAs=HistoryLength, RaisesException] readonly attribute unsigned long length;
[Measure, RaisesException] attribute ScrollRestoration scrollRestoration;
- [CachedAttribute=stateChanged, CallWith=Isolate, RaisesException] readonly attribute any state;
+ [CallWith=ScriptState, RaisesException] readonly attribute any state;
[CallWith=ScriptState, RaisesException] void go(optional long delta = 0);
[CallWith=ScriptState, RaisesException] void back();
[CallWith=ScriptState, RaisesException] void forward();
diff --git a/chromium/third_party/blink/renderer/core/frame/intervention.cc b/chromium/third_party/blink/renderer/core/frame/intervention.cc
index e7737916d6b..3cd1a539d59 100644
--- a/chromium/third_party/blink/renderer/core/frame/intervention.cc
+++ b/chromium/third_party/blink/renderer/core/frame/intervention.cc
@@ -8,6 +8,7 @@
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/core/frame/frame_console.h"
#include "third_party/blink/renderer/core/frame/intervention_report_body.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/local_frame_client.h"
#include "third_party/blink/renderer/core/frame/report.h"
@@ -21,27 +22,24 @@ namespace blink {
void Intervention::GenerateReport(const LocalFrame* frame,
const String& id,
const String& message) {
- if (!frame)
+ if (!frame || !frame->Client())
return;
// Send the message to the console.
- Document* document = frame->GetDocument();
- document->AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>(
+ auto* window = frame->DomWindow();
+ window->AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>(
mojom::ConsoleMessageSource::kIntervention,
mojom::ConsoleMessageLevel::kError, message));
- if (!frame->Client())
- return;
-
// Construct the intervention report.
InterventionReportBody* body =
MakeGarbageCollected<InterventionReportBody>(id, message);
Report* report = MakeGarbageCollected<Report>(
- ReportType::kIntervention, document->Url().GetString(), body);
+ ReportType::kIntervention, window->document()->Url().GetString(), body);
// Send the intervention report to the Reporting API and any
// ReportingObservers.
- ReportingContext::From(document->ToExecutionContext())->QueueReport(report);
+ ReportingContext::From(window)->QueueReport(report);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/frame/is_input_pending_options.cc b/chromium/third_party/blink/renderer/core/frame/is_input_pending_options.cc
new file mode 100644
index 00000000000..b091c57fbc2
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/frame/is_input_pending_options.cc
@@ -0,0 +1,20 @@
+// 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/core/frame/is_input_pending_options.h"
+
+#include "third_party/blink/renderer/bindings/core/v8/v8_is_input_pending_options_init.h"
+
+namespace blink {
+
+IsInputPendingOptions* IsInputPendingOptions::Create(
+ const IsInputPendingOptionsInit* options_init) {
+ return MakeGarbageCollected<IsInputPendingOptions>(
+ options_init->includeContinuous());
+}
+
+IsInputPendingOptions::IsInputPendingOptions(bool include_continuous)
+ : include_continuous_(include_continuous) {}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/frame/is_input_pending_options.h b/chromium/third_party/blink/renderer/core/frame/is_input_pending_options.h
new file mode 100644
index 00000000000..f7036d83b1e
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/frame/is_input_pending_options.h
@@ -0,0 +1,34 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_IS_INPUT_PENDING_OPTIONS_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_IS_INPUT_PENDING_OPTIONS_H_
+
+#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+
+namespace blink {
+
+class IsInputPendingOptionsInit;
+
+class IsInputPendingOptions : public ScriptWrappable {
+ DEFINE_WRAPPERTYPEINFO();
+
+ public:
+ static IsInputPendingOptions* Create(
+ const IsInputPendingOptionsInit* options_init);
+
+ explicit IsInputPendingOptions(bool include_continuous);
+
+ bool includeContinuous() const { return include_continuous_; }
+ void setIncludeContinuous(bool include_continuous) {
+ include_continuous_ = include_continuous;
+ }
+
+ private:
+ bool include_continuous_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_IS_INPUT_PENDING_OPTIONS_H_
diff --git a/chromium/third_party/blink/renderer/core/frame/is_input_pending_options.idl b/chromium/third_party/blink/renderer/core/frame/is_input_pending_options.idl
new file mode 100644
index 00000000000..48423d12b50
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/frame/is_input_pending_options.idl
@@ -0,0 +1,12 @@
+// 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.
+
+// https://github.com/WICG/is-input-pending
+[
+ Exposed=Window,
+ RuntimeEnabled=ExperimentalIsInputPending
+] interface IsInputPendingOptions {
+ constructor(optional IsInputPendingOptionsInit options = {});
+ attribute boolean includeContinuous;
+};
diff --git a/chromium/third_party/blink/renderer/core/frame/is_input_pending_options_init.idl b/chromium/third_party/blink/renderer/core/frame/is_input_pending_options_init.idl
new file mode 100644
index 00000000000..a818a1791e7
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/frame/is_input_pending_options_init.idl
@@ -0,0 +1,8 @@
+// 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.
+
+// https://github.com/WICG/is-input-pending
+dictionary IsInputPendingOptionsInit {
+ boolean includeContinuous = false;
+};
diff --git a/chromium/third_party/blink/renderer/core/frame/local_dom_window.cc b/chromium/third_party/blink/renderer/core/frame/local_dom_window.cc
index 558e2a8b2da..41cbe27f5e2 100644
--- a/chromium/third_party/blink/renderer/core/frame/local_dom_window.cc
+++ b/chromium/third_party/blink/renderer/core/frame/local_dom_window.cc
@@ -30,7 +30,9 @@
#include <utility>
#include "cc/input/snap_selection_strategy.h"
+#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
+#include "third_party/blink/public/mojom/feature_policy/policy_disposition.mojom-blink.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/public/platform/web_screen_info.h"
@@ -60,6 +62,9 @@
#include "third_party/blink/renderer/core/dom/scripted_idle_task_controller.h"
#include "third_party/blink/renderer/core/editing/editor.h"
#include "third_party/blink/renderer/core/editing/frame_selection.h"
+#include "third_party/blink/renderer/core/editing/ime/input_method_controller.h"
+#include "third_party/blink/renderer/core/editing/spellcheck/spell_checker.h"
+#include "third_party/blink/renderer/core/editing/suggestion/text_suggestion_controller.h"
#include "third_party/blink/renderer/core/events/hash_change_event.h"
#include "third_party/blink/renderer/core/events/message_event.h"
#include "third_party/blink/renderer/core/events/pop_state_event.h"
@@ -68,16 +73,19 @@
#include "third_party/blink/renderer/core/execution_context/window_agent.h"
#include "third_party/blink/renderer/core/frame/bar_prop.h"
#include "third_party/blink/renderer/core/frame/csp/content_security_policy.h"
+#include "third_party/blink/renderer/core/frame/document_policy_violation_report_body.h"
#include "third_party/blink/renderer/core/frame/dom_visual_viewport.h"
#include "third_party/blink/renderer/core/frame/event_handler_registry.h"
#include "third_party/blink/renderer/core/frame/external.h"
+#include "third_party/blink/renderer/core/frame/feature_policy_violation_report_body.h"
#include "third_party/blink/renderer/core/frame/frame_console.h"
#include "third_party/blink/renderer/core/frame/history.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/local_frame_client.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
#include "third_party/blink/renderer/core/frame/navigator.h"
-#include "third_party/blink/renderer/core/frame/sandbox_flags.h"
+#include "third_party/blink/renderer/core/frame/report.h"
+#include "third_party/blink/renderer/core/frame/reporting_context.h"
#include "third_party/blink/renderer/core/frame/screen.h"
#include "third_party/blink/renderer/core/frame/settings.h"
#include "third_party/blink/renderer/core/frame/viewport_data.h"
@@ -226,7 +234,12 @@ LocalDOMWindow::LocalDOMWindow(LocalFrame& frame)
unused_preloads_timer_(frame.GetTaskRunner(TaskType::kInternalDefault),
this,
&LocalDOMWindow::WarnUnusedPreloads),
- should_print_when_finished_loading_(false) {}
+ should_print_when_finished_loading_(false),
+ input_method_controller_(
+ MakeGarbageCollected<InputMethodController>(*this, frame)),
+ spell_checker_(MakeGarbageCollected<SpellChecker>(*this)),
+ text_suggestion_controller_(
+ MakeGarbageCollected<TextSuggestionController>(*this)) {}
void LocalDOMWindow::ClearDocument() {
if (!document_)
@@ -254,18 +267,18 @@ TrustedTypePolicyFactory* LocalDOMWindow::trustedTypes() const {
return trusted_types_.Get();
}
-Document* LocalDOMWindow::CreateDocument(const DocumentInit& init,
- bool force_xhtml) {
- Document* document = nullptr;
- if (force_xhtml) {
- // This is a hack for XSLTProcessor. See
- // XSLTProcessor::createDocumentFromSource().
- document = MakeGarbageCollected<Document>(init);
- } else {
- document = DOMImplementation::createDocument(init);
- }
-
- return document;
+bool LocalDOMWindow::IsCrossSiteSubframe() const {
+ if (!GetFrame())
+ return false;
+ // It'd be nice to avoid the url::Origin temporaries, but that would require
+ // exposing the net internal helper.
+ // TODO: If the helper gets exposed, we could do this without any new
+ // allocations using StringUTF8Adaptor.
+ auto* top_origin =
+ GetFrame()->Tree().Top().GetSecurityContext()->GetSecurityOrigin();
+ return !net::registry_controlled_domains::SameDomainOrHost(
+ top_origin->ToUrlOrigin(), GetSecurityOrigin()->ToUrlOrigin(),
+ net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
}
LocalDOMWindow* LocalDOMWindow::From(const ScriptState* script_state) {
@@ -303,11 +316,13 @@ void LocalDOMWindow::DisableEval(const String& error_message) {
}
String LocalDOMWindow::UserAgent() const {
- return document()->UserAgent();
+ return GetFrame() ? GetFrame()->Loader().UserAgent() : String();
}
HttpsState LocalDOMWindow::GetHttpsState() const {
- return document()->GetHttpsState();
+ // TODO(https://crbug.com/880986): Implement Document's HTTPS state in more
+ // spec-conformant way.
+ return CalculateHttpsState(GetSecurityOrigin());
}
ResourceFetcher* LocalDOMWindow::Fetcher() const {
@@ -350,7 +365,7 @@ network::mojom::ReferrerPolicy LocalDOMWindow::GetReferrerPolicy() const {
}
CoreProbeSink* LocalDOMWindow::GetProbeSink() {
- return document()->GetProbeSink();
+ return probe::ToCoreProbeSink(GetFrame());
}
BrowserInterfaceBrokerProxy& LocalDOMWindow::GetBrowserInterfaceBroker() {
@@ -370,21 +385,61 @@ FrameOrWorkerScheduler* LocalDOMWindow::GetScheduler() {
scoped_refptr<base::SingleThreadTaskRunner> LocalDOMWindow::GetTaskRunner(
TaskType type) {
- return document()->GetTaskRunner(type);
+ if (GetFrame())
+ return GetFrame()->GetTaskRunner(type);
+ // In most cases, the ExecutionContext will get us to a relevant Frame. In
+ // some cases, though, there isn't a good candidate (most commonly when either
+ // the passed-in document or the ExecutionContext used to be attached to a
+ // Frame but has since been detached).
+ return Thread::Current()->GetTaskRunner();
}
void LocalDOMWindow::CountPotentialFeaturePolicyViolation(
mojom::blink::FeaturePolicyFeature feature) const {
- document()->CountPotentialFeaturePolicyViolation(feature);
+ wtf_size_t index = static_cast<wtf_size_t>(feature);
+ if (potentially_violated_features_.size() == 0) {
+ potentially_violated_features_.resize(
+ static_cast<wtf_size_t>(mojom::blink::FeaturePolicyFeature::kMaxValue) +
+ 1);
+ } else if (potentially_violated_features_[index]) {
+ return;
+ }
+ potentially_violated_features_[index] = true;
+ UMA_HISTOGRAM_ENUMERATION("Blink.UseCounter.FeaturePolicy.PotentialViolation",
+ feature);
}
void LocalDOMWindow::ReportFeaturePolicyViolation(
mojom::blink::FeaturePolicyFeature feature,
mojom::blink::PolicyDisposition disposition,
- const String& message,
- const String& source_file) const {
- document()->ReportFeaturePolicyViolation(feature, disposition, message,
- source_file);
+ const String& message) const {
+ if (!RuntimeEnabledFeatures::FeaturePolicyReportingEnabled(this))
+ return;
+ if (!GetFrame())
+ return;
+
+ // Construct the feature policy violation report.
+ const String& feature_name = GetNameForFeature(feature);
+ const String& disp_str =
+ (disposition == mojom::blink::PolicyDisposition::kReport ? "report"
+ : "enforce");
+
+ FeaturePolicyViolationReportBody* body =
+ MakeGarbageCollected<FeaturePolicyViolationReportBody>(feature_name,
+ message, disp_str);
+
+ Report* report = MakeGarbageCollected<Report>(
+ ReportType::kFeaturePolicyViolation, Url().GetString(), body);
+
+ // Send the feature policy violation report to any ReportingObservers.
+ ReportingContext::From(this)->QueueReport(report);
+
+ // TODO(iclelland): Report something different in report-only mode
+ if (disposition == mojom::blink::PolicyDisposition::kEnforce) {
+ GetFrame()->Console().AddMessage(MakeGarbageCollected<ConsoleMessage>(
+ mojom::blink::ConsoleMessageSource::kViolation,
+ mojom::blink::ConsoleMessageLevel::kError, body->message()));
+ }
}
void LocalDOMWindow::ReportDocumentPolicyViolation(
@@ -392,8 +447,46 @@ void LocalDOMWindow::ReportDocumentPolicyViolation(
mojom::blink::PolicyDisposition disposition,
const String& message,
const String& source_file) const {
- document()->ReportDocumentPolicyViolation(feature, disposition, message,
- source_file);
+ if (!GetFrame())
+ return;
+
+ // Construct the document policy violation report.
+ const String& feature_name =
+ GetDocumentPolicyFeatureInfoMap().at(feature).feature_name.c_str();
+ bool is_report_only = disposition == mojom::blink::PolicyDisposition::kReport;
+ const String& disp_str = is_report_only ? "report" : "enforce";
+ const DocumentPolicy* relevant_document_policy =
+ is_report_only ? GetSecurityContext().GetReportOnlyDocumentPolicy()
+ : GetSecurityContext().GetDocumentPolicy();
+
+ DocumentPolicyViolationReportBody* body =
+ MakeGarbageCollected<DocumentPolicyViolationReportBody>(
+ feature_name, message, disp_str, source_file);
+
+ Report* report = MakeGarbageCollected<Report>(
+ ReportType::kDocumentPolicyViolation, Url().GetString(), body);
+
+ // Send the document policy violation report to any ReportingObservers.
+ const base::Optional<std::string> endpoint =
+ relevant_document_policy->GetFeatureEndpoint(feature);
+
+ if (is_report_only) {
+ UMA_HISTOGRAM_ENUMERATION("Blink.UseCounter.DocumentPolicy.ReportOnly",
+ feature);
+ } else {
+ UMA_HISTOGRAM_ENUMERATION("Blink.UseCounter.DocumentPolicy.Enforced",
+ feature);
+ }
+
+ ReportingContext::From(this)->QueueReport(
+ report, endpoint ? Vector<String>{endpoint->c_str()} : Vector<String>{});
+
+ // TODO(iclelland): Report something different in report-only mode
+ if (!is_report_only) {
+ GetFrame()->Console().AddMessage(MakeGarbageCollected<ConsoleMessage>(
+ mojom::blink::ConsoleMessageSource::kViolation,
+ mojom::blink::ConsoleMessageLevel::kError, body->message()));
+ }
}
static void RunAddConsoleMessageTask(mojom::ConsoleMessageSource source,
@@ -443,6 +536,13 @@ void LocalDOMWindow::AddConsoleMessageImpl(ConsoleMessage* console_message,
GetFrame()->Console().AddMessage(console_message, discard_duplicates);
}
+void LocalDOMWindow::AddInspectorIssue(
+ mojom::blink::InspectorIssueInfoPtr info) {
+ if (GetFrame()) {
+ GetFrame()->AddInspectorIssue(std::move(info));
+ }
+}
+
void LocalDOMWindow::CountUse(mojom::WebFeature feature) {
if (!GetFrame())
return;
@@ -454,13 +554,12 @@ void LocalDOMWindow::CountDeprecation(mojom::WebFeature feature) {
document()->CountDeprecation(feature);
}
-Document* LocalDOMWindow::InstallNewDocument(const DocumentInit& init,
- bool force_xhtml) {
+Document* LocalDOMWindow::InstallNewDocument(const DocumentInit& init) {
DCHECK_EQ(init.GetFrame(), GetFrame());
ClearDocument();
- document_ = CreateDocument(init, force_xhtml);
+ document_ = DOMImplementation::createDocument(init);
document_->Initialize();
// The CSP delegate doesn't have access to all of the state it needs until
@@ -757,8 +856,7 @@ FrameConsole* LocalDOMWindow::GetFrameConsole() const {
}
ApplicationCache* LocalDOMWindow::applicationCache() const {
- DCHECK(RuntimeEnabledFeatures::AppCacheEnabled(
- document()->ToExecutionContext()));
+ DCHECK(RuntimeEnabledFeatures::AppCacheEnabled(this));
if (!IsCurrentlyDisplayedInFrame())
return nullptr;
if (!isSecureContext()) {
@@ -784,15 +882,14 @@ void LocalDOMWindow::SchedulePostMessage(
// is problematic; consider imposing a limit or other restriction if this
// surfaces often as a problem (see crbug.com/587012).
std::unique_ptr<SourceLocation> location =
- SourceLocation::Capture(source->ToExecutionContext());
+ SourceLocation::Capture(source->GetExecutionContext());
document_->GetTaskRunner(TaskType::kPostedMessage)
->PostTask(FROM_HERE,
WTF::Bind(&LocalDOMWindow::DispatchPostMessage,
WrapPersistent(this), WrapPersistent(event),
std::move(target), std::move(location),
- source->ToExecutionContext()->GetAgentClusterID()));
- probe::AsyncTaskScheduled(document()->ToExecutionContext(), "postMessage",
- event->async_task_id());
+ source->GetExecutionContext()->GetAgentClusterID()));
+ probe::AsyncTaskScheduled(this, "postMessage", event->async_task_id());
}
void LocalDOMWindow::DispatchPostMessage(
@@ -800,12 +897,11 @@ void LocalDOMWindow::DispatchPostMessage(
scoped_refptr<const SecurityOrigin> intended_target_origin,
std::unique_ptr<SourceLocation> location,
const base::UnguessableToken& source_agent_cluster_id) {
- probe::AsyncTask async_task(document()->ToExecutionContext(),
- event->async_task_id());
+ probe::AsyncTask async_task(this, event->async_task_id());
if (!IsCurrentlyDisplayedInFrame())
return;
- event->EntangleMessagePorts(document()->ToExecutionContext());
+ event->EntangleMessagePorts(this);
DispatchMessageEventWithOriginCheck(intended_target_origin.get(), event,
std::move(location),
@@ -858,8 +954,7 @@ void LocalDOMWindow::DispatchMessageEventWithOriginCheck(
}
}
if (event->IsLockedToAgentCluster()) {
- if (!document()->ToExecutionContext()->IsSameAgentCluster(
- source_agent_cluster_id)) {
+ if (!IsSameAgentCluster(source_agent_cluster_id)) {
UseCounter::Count(
document(),
WebFeature::kMessageEventSharedArrayBufferDifferentAgentCluster);
@@ -935,7 +1030,8 @@ void LocalDOMWindow::alert(ScriptState* script_state, const String& message) {
if (!GetFrame())
return;
- if (document()->IsSandboxed(mojom::blink::WebSandboxFlags::kModals)) {
+ if (document()->IsSandboxed(
+ network::mojom::blink::WebSandboxFlags::kModals)) {
UseCounter::Count(document(), WebFeature::kDialogInSandboxedContext);
GetFrameConsole()->AddMessage(MakeGarbageCollected<ConsoleMessage>(
mojom::ConsoleMessageSource::kSecurity,
@@ -968,7 +1064,8 @@ bool LocalDOMWindow::confirm(ScriptState* script_state, const String& message) {
if (!GetFrame())
return false;
- if (document()->IsSandboxed(mojom::blink::WebSandboxFlags::kModals)) {
+ if (document()->IsSandboxed(
+ network::mojom::blink::WebSandboxFlags::kModals)) {
UseCounter::Count(document(), WebFeature::kDialogInSandboxedContext);
GetFrameConsole()->AddMessage(MakeGarbageCollected<ConsoleMessage>(
mojom::ConsoleMessageSource::kSecurity,
@@ -1003,7 +1100,8 @@ String LocalDOMWindow::prompt(ScriptState* script_state,
if (!GetFrame())
return String();
- if (document()->IsSandboxed(mojom::blink::WebSandboxFlags::kModals)) {
+ if (document()->IsSandboxed(
+ network::mojom::blink::WebSandboxFlags::kModals)) {
UseCounter::Count(document(), WebFeature::kDialogInSandboxedContext);
GetFrameConsole()->AddMessage(MakeGarbageCollected<ConsoleMessage>(
mojom::ConsoleMessageSource::kSecurity,
@@ -1854,6 +1952,9 @@ void LocalDOMWindow::Trace(Visitor* visitor) {
visitor->Trace(visualViewport_);
visitor->Trace(event_listener_observers_);
visitor->Trace(trusted_types_);
+ visitor->Trace(input_method_controller_);
+ visitor->Trace(spell_checker_);
+ visitor->Trace(text_suggestion_controller_);
DOMWindow::Trace(visitor);
ExecutionContext::Trace(visitor);
Supplementable<LocalDOMWindow>::Trace(visitor);
diff --git a/chromium/third_party/blink/renderer/core/frame/local_dom_window.h b/chromium/third_party/blink/renderer/core/frame/local_dom_window.h
index 7494c6d34a6..bdc61595261 100644
--- a/chromium/third_party/blink/renderer/core/frame/local_dom_window.h
+++ b/chromium/third_party/blink/renderer/core/frame/local_dom_window.h
@@ -97,8 +97,6 @@ class CORE_EXPORT LocalDOMWindow final : public DOMWindow,
virtual void DidRemoveAllEventListeners(LocalDOMWindow*) = 0;
};
- static Document* CreateDocument(const DocumentInit&, bool force_xhtml);
-
static LocalDOMWindow* From(const ScriptState*);
explicit LocalDOMWindow(LocalFrame&);
@@ -119,10 +117,6 @@ class CORE_EXPORT LocalDOMWindow final : public DOMWindow,
const KURL& BaseURL() const final;
KURL CompleteURL(const String&) const final;
void DisableEval(const String& error_message) final;
- LocalDOMWindow* ExecutingWindow() const final {
- // TODO(crbug.com/1029822): This const_cast is gross.
- return const_cast<LocalDOMWindow*>(this);
- }
String UserAgent() const final;
HttpsState GetHttpsState() const final;
ResourceFetcher* Fetcher() const final;
@@ -130,6 +124,7 @@ class CORE_EXPORT LocalDOMWindow final : public DOMWindow,
const SecurityContext& GetSecurityContext() const final;
bool CanExecuteScripts(ReasonForCallingCanExecuteScripts) final;
void ExceptionThrown(ErrorEvent*) final;
+ void AddInspectorIssue(mojom::blink::InspectorIssueInfoPtr) final;
EventTarget* ErrorEventTarget() final { return this; }
String OutgoingReferrer() const final;
network::mojom::ReferrerPolicy GetReferrerPolicy() const final;
@@ -145,10 +140,7 @@ class CORE_EXPORT LocalDOMWindow final : public DOMWindow,
void ReportFeaturePolicyViolation(
mojom::blink::FeaturePolicyFeature,
mojom::blink::PolicyDisposition,
- const String& message = g_empty_string,
- // If source_file is set to empty string,
- // current JS file would be used as source_file instead.
- const String& source_file = g_empty_string) const final;
+ const String& message = g_empty_string) const final;
void ReportDocumentPolicyViolation(
mojom::blink::DocumentPolicyFeature,
mojom::blink::PolicyDisposition,
@@ -163,7 +155,7 @@ class CORE_EXPORT LocalDOMWindow final : public DOMWindow,
void CountUse(mojom::WebFeature feature) final;
void CountDeprecation(mojom::WebFeature feature) final;
- Document* InstallNewDocument(const DocumentInit&, bool force_xhtml);
+ Document* InstallNewDocument(const DocumentInit&);
// EventTarget overrides:
ExecutionContext* GetExecutionContext() const override;
@@ -361,6 +353,10 @@ class CORE_EXPORT LocalDOMWindow final : public DOMWindow,
TrustedTypePolicyFactory* trustedTypes() const;
+ // Returns true if this window is cross-site to the main frame. Defaults to
+ // false in a detached window.
+ bool IsCrossSiteSubframe() const;
+
void DispatchPersistedPageshowEvent(base::TimeTicks navigation_start);
void DispatchPagehideEvent(PageTransitionEventPersistence persistence) {
@@ -369,6 +365,14 @@ class CORE_EXPORT LocalDOMWindow final : public DOMWindow,
document_.Get());
}
+ InputMethodController& GetInputMethodController() const {
+ return *input_method_controller_;
+ }
+ TextSuggestionController& GetTextSuggestionController() const {
+ return *text_suggestion_controller_;
+ }
+ SpellChecker& GetSpellChecker() const { return *spell_checker_; }
+
protected:
// EventTarget overrides.
void AddedEventListener(const AtomicString& event_type,
@@ -442,6 +446,15 @@ class CORE_EXPORT LocalDOMWindow final : public DOMWindow,
// TODO(altimin): We should be able to remove it after we complete
// frame:document lifetime refactoring.
std::unique_ptr<FrameOrWorkerScheduler> detached_scheduler_;
+
+ Member<InputMethodController> input_method_controller_;
+ Member<SpellChecker> spell_checker_;
+ Member<TextSuggestionController> text_suggestion_controller_;
+
+ // Tracks which features have already been potentially violated in this
+ // document. This helps to count them only once per page load.
+ // We don't use std::bitset to avoid to include feature_policy.mojom-blink.h.
+ mutable Vector<bool> potentially_violated_features_;
};
template <>
diff --git a/chromium/third_party/blink/renderer/core/frame/local_frame.cc b/chromium/third_party/blink/renderer/core/frame/local_frame.cc
index 3c78d008993..923913ab9dd 100644
--- a/chromium/third_party/blink/renderer/core/frame/local_frame.cc
+++ b/chromium/third_party/blink/renderer/core/frame/local_frame.cc
@@ -51,6 +51,7 @@
#include "third_party/blink/public/mojom/frame/frame_owner_properties.mojom-blink.h"
#include "third_party/blink/public/mojom/frame/lifecycle.mojom-blink.h"
#include "third_party/blink/public/mojom/frame/media_player_action.mojom-blink.h"
+#include "third_party/blink/public/mojom/frame/reporting_observer.mojom-blink.h"
#include "third_party/blink/public/mojom/scroll/scrollbar_mode.mojom-blink.h"
#include "third_party/blink/public/platform/interface_registry.h"
#include "third_party/blink/public/platform/scheduler/web_resource_loading_task_runner_handle.h"
@@ -99,11 +100,13 @@
#include "third_party/blink/renderer/core/frame/page_scale_constraints_set.h"
#include "third_party/blink/renderer/core/frame/performance_monitor.h"
#include "third_party/blink/renderer/core/frame/picture_in_picture_controller.h"
+#include "third_party/blink/renderer/core/frame/remote_frame.h"
#include "third_party/blink/renderer/core/frame/remote_frame_owner.h"
#include "third_party/blink/renderer/core/frame/report.h"
#include "third_party/blink/renderer/core/frame/reporting_context.h"
#include "third_party/blink/renderer/core/frame/root_frame_viewport.h"
#include "third_party/blink/renderer/core/frame/settings.h"
+#include "third_party/blink/renderer/core/frame/user_activation.h"
#include "third_party/blink/renderer/core/frame/visual_viewport.h"
#include "third_party/blink/renderer/core/frame/web_frame_widget_base.h"
#include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
@@ -114,7 +117,7 @@
#include "third_party/blink/renderer/core/html/plugin_document.h"
#include "third_party/blink/renderer/core/input/event_handler.h"
#include "third_party/blink/renderer/core/inspector/console_message.h"
-#include "third_party/blink/renderer/core/inspector/inspector_issue.h"
+#include "third_party/blink/renderer/core/inspector/inspector_issue_storage.h"
#include "third_party/blink/renderer/core/inspector/inspector_task_runner.h"
#include "third_party/blink/renderer/core/inspector/inspector_trace_events.h"
#include "third_party/blink/renderer/core/intersection_observer/intersection_observer_controller.h"
@@ -125,6 +128,7 @@
#include "third_party/blink/renderer/core/loader/document_loader.h"
#include "third_party/blink/renderer/core/loader/frame_load_request.h"
#include "third_party/blink/renderer/core/loader/idleness_detector.h"
+#include "third_party/blink/renderer/core/messaging/message_port.h"
#include "third_party/blink/renderer/core/page/chrome_client.h"
#include "third_party/blink/renderer/core/page/drag_controller.h"
#include "third_party/blink/renderer/core/page/focus_controller.h"
@@ -156,9 +160,15 @@
#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/frame_scheduler.h"
+#include "third_party/blink/renderer/platform/wtf/casting.h"
#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
#include "ui/gfx/geometry/point.h"
+#if defined(OS_MACOSX)
+#include "third_party/blink/renderer/core/editing/ephemeral_range.h"
+#include "ui/gfx/range/range.h"
+#endif
+
namespace blink {
namespace {
@@ -176,6 +186,14 @@ inline float ParentTextZoomFactor(LocalFrame* frame) {
return parent_local_frame ? parent_local_frame->TextZoomFactor() : 1;
}
+#if defined(OS_MACOSX)
+uint32_t GetCurrentCursorPositionInFrame(LocalFrame* local_frame) {
+ blink::WebRange range =
+ WebLocalFrameImpl::FromFrame(local_frame)->SelectionRange();
+ return range.IsNull() ? 0U : static_cast<uint32_t>(range.StartOffset());
+}
+#endif
+
// Convert a data url to a message pipe handle that corresponds to a remote
// blob, so that it can be passed across processes.
mojo::ScopedMessagePipeHandle DataURLToMessagePipeHandle(
@@ -202,6 +220,13 @@ HitTestResult HitTestResultForRootFramePos(
return result;
}
+RemoteFrame* SourceFrameForOptionalToken(
+ const base::Optional<base::UnguessableToken>& source_frame_token) {
+ if (!source_frame_token)
+ return nullptr;
+ return RemoteFrame::FromFrameToken(source_frame_token.value());
+}
+
class WebBundleGenerationDelegate
: public WebFrameSerializer::MHTMLPartsGenerationDelegate {
STACK_ALLOCATED();
@@ -358,12 +383,9 @@ void LocalFrame::Trace(Visitor* visitor) {
visitor->Trace(page_popup_owner_);
visitor->Trace(script_controller_);
visitor->Trace(editor_);
- visitor->Trace(spell_checker_);
visitor->Trace(selection_);
visitor->Trace(event_handler_);
visitor->Trace(console_);
- visitor->Trace(input_method_controller_);
- visitor->Trace(text_suggestion_controller_);
visitor->Trace(smooth_scroll_sequencer_);
visitor->Trace(content_capture_manager_);
visitor->Trace(system_clipboard_);
@@ -573,9 +595,6 @@ void LocalFrame::DidAttachDocument() {
// even after the frame reattaches.
GetEventHandler().Clear();
Selection().DidAttachDocument(document);
- GetInputMethodController().DidAttachDocument(document);
- GetSpellChecker().DidAttachDocument(document);
- GetTextSuggestionController().DidAttachDocument(document);
if (IsCrossOriginToParentFrame() && !first_url_cross_origin_to_parent_) {
first_url_cross_origin_to_parent_ = GetDocument()->Url().GetString();
}
@@ -902,6 +921,16 @@ void LocalFrame::DeviceScaleFactorChanged() {
}
}
+void LocalFrame::MediaQueryAffectingValueChangedForLocalSubtree(
+ MediaValueChange value) {
+ GetDocument()->MediaQueryAffectingValueChanged(value);
+ for (Frame* child = Tree().FirstChild(); child;
+ child = child->Tree().NextSibling()) {
+ if (auto* child_local_frame = DynamicTo<LocalFrame>(child))
+ child_local_frame->MediaQueryAffectingValueChangedForLocalSubtree(value);
+ }
+}
+
double LocalFrame::DevicePixelRatio() const {
if (!page_)
return 0;
@@ -987,12 +1016,14 @@ bool LocalFrame::ShouldThrottleRendering() const {
LocalFrame::LocalFrame(LocalFrameClient* client,
Page& page,
FrameOwner* owner,
+ const base::UnguessableToken& frame_token,
WindowAgentFactory* inheriting_agent_factory,
InterfaceRegistry* interface_registry,
const base::TickClock* clock)
: Frame(client,
page,
owner,
+ frame_token,
MakeGarbageCollected<LocalWindowProxyManager>(*this),
inheriting_agent_factory),
frame_scheduler_(page.GetPageScheduler()->CreateFrameScheduler(
@@ -1005,14 +1036,9 @@ LocalFrame::LocalFrame(LocalFrameClient* client,
*this,
*static_cast<LocalWindowProxyManager*>(GetWindowProxyManager()))),
editor_(MakeGarbageCollected<Editor>(*this)),
- spell_checker_(MakeGarbageCollected<SpellChecker>(*this)),
selection_(MakeGarbageCollected<FrameSelection>(*this)),
event_handler_(MakeGarbageCollected<EventHandler>(*this)),
console_(MakeGarbageCollected<FrameConsole>(*this)),
- input_method_controller_(
- MakeGarbageCollected<InputMethodController>(*this)),
- text_suggestion_controller_(
- MakeGarbageCollected<TextSuggestionController>(*this)),
navigation_disable_count_(0),
page_zoom_factor_(ParentPageZoomFactor(this)),
text_zoom_factor_(ParentTextZoomFactor(this)),
@@ -1054,6 +1080,12 @@ LocalFrame::LocalFrame(LocalFrameClient* client,
Initialize();
probe::FrameAttachedToParent(this);
+#if defined(OS_MACOSX)
+ // It should be bound before accessing TextInputHost which is the interface to
+ // respond to GetCharacterIndexAtPoint.
+ GetBrowserInterfaceBroker().GetInterface(
+ text_input_host_.BindNewPipeAndPassReceiver());
+#endif
}
FrameScheduler* LocalFrame::GetFrameScheduler() {
@@ -1127,7 +1159,7 @@ bool LocalFrame::CanNavigate(const Frame& target_frame,
}
if (GetSecurityContext()->IsSandboxed(
- mojom::blink::WebSandboxFlags::kNavigation)) {
+ network::mojom::blink::WebSandboxFlags::kNavigation)) {
if (!target_frame.Tree().IsDescendantOf(this) &&
!target_frame.IsMainFrame()) {
PrintNavigationErrorMessage(
@@ -1142,10 +1174,10 @@ bool LocalFrame::CanNavigate(const Frame& target_frame,
// 'allow-popups' flag is specified, or if the
if (target_frame.IsMainFrame() && target_frame != Tree().Top() &&
GetSecurityContext()->IsSandboxed(
- mojom::blink::WebSandboxFlags::
+ network::mojom::blink::WebSandboxFlags::
kPropagatesToAuxiliaryBrowsingContexts) &&
(GetSecurityContext()->IsSandboxed(
- mojom::blink::WebSandboxFlags::kPopups) ||
+ network::mojom::blink::WebSandboxFlags::kPopups) ||
target_frame.Client()->Opener() != this)) {
PrintNavigationErrorMessage(
target_frame,
@@ -1159,9 +1191,10 @@ bool LocalFrame::CanNavigate(const Frame& target_frame,
// allow-top-navigation-by-user-activation will also skips origin checks.
if (target_frame == Tree().Top()) {
if (GetSecurityContext()->IsSandboxed(
- mojom::blink::WebSandboxFlags::kTopNavigation) &&
+ network::mojom::blink::WebSandboxFlags::kTopNavigation) &&
GetSecurityContext()->IsSandboxed(
- mojom::blink::WebSandboxFlags::kTopNavigationByUserActivation)) {
+ network::mojom::blink::WebSandboxFlags::
+ kTopNavigationByUserActivation)) {
PrintNavigationErrorMessage(
target_frame,
"The frame attempting navigation of the top-level window is "
@@ -1171,9 +1204,10 @@ bool LocalFrame::CanNavigate(const Frame& target_frame,
}
if (GetSecurityContext()->IsSandboxed(
- mojom::blink::WebSandboxFlags::kTopNavigation) &&
+ network::mojom::blink::WebSandboxFlags::kTopNavigation) &&
!GetSecurityContext()->IsSandboxed(
- mojom::blink::WebSandboxFlags::kTopNavigationByUserActivation) &&
+ network::mojom::blink::WebSandboxFlags::
+ kTopNavigationByUserActivation) &&
!LocalFrame::HasTransientUserActivation(this)) {
// With only 'allow-top-navigation-by-user-activation' (but not
// 'allow-top-navigation'), top navigation requires a user gesture.
@@ -1563,8 +1597,7 @@ void LocalFrame::ForceSynchronousDocumentInstall(
DomWindow()->InstallNewDocument(
DocumentInit::Create()
.WithDocumentLoader(loader_.GetDocumentLoader())
- .WithTypeFrom(mime_type),
- false);
+ .WithTypeFrom(mime_type));
loader_.StateMachine()->AdvanceTo(
FrameLoaderStateMachine::kCommittedFirstRealLoad);
@@ -1859,15 +1892,14 @@ void LocalFrame::DidResume() {
void LocalFrame::PauseContext() {
GetDocument()->Fetcher()->SetDefersLoading(true);
- GetDocument()->ToExecutionContext()->SetLifecycleState(lifecycle_state_);
+ DomWindow()->SetLifecycleState(lifecycle_state_);
Loader().SetDefersLoading(true);
GetFrameScheduler()->SetPaused(true);
}
void LocalFrame::UnpauseContext() {
GetDocument()->Fetcher()->SetDefersLoading(false);
- GetDocument()->ToExecutionContext()->SetLifecycleState(
- mojom::FrameLifecycleState::kRunning);
+ DomWindow()->SetLifecycleState(mojom::FrameLifecycleState::kRunning);
Loader().SetDefersLoading(false);
GetFrameScheduler()->SetPaused(false);
}
@@ -2121,6 +2153,38 @@ void LocalFrame::ZoomToFindInPageRect(const gfx::Rect& rect_in_root_frame) {
WebRect(rect_in_root_frame));
}
+#if defined(OS_MACOSX)
+void LocalFrame::GetCharacterIndexAtPoint(const gfx::Point& point) {
+ HitTestLocation location(View()->ViewportToFrame(IntPoint(point)));
+ HitTestResult result = GetEventHandler().HitTestResultAtLocation(
+ location, HitTestRequest::kReadOnly | HitTestRequest::kActive);
+ uint32_t index =
+ Selection().CharacterIndexForPoint(result.RoundedPointInInnerNodeFrame());
+ GetTextInputHost().GotCharacterIndexAtPoint(index);
+}
+
+void LocalFrame::GetFirstRectForRange(const gfx::Range& range) {
+ gfx::Rect rect;
+ WebLocalFrameClient* client = WebLocalFrameImpl::FromFrame(this)->Client();
+ if (!client)
+ return;
+
+ if (!client->GetCaretBoundsFromFocusedPlugin(rect)) {
+ blink::WebRect web_rect;
+ // When request range is invalid we will try to obtain it from current
+ // frame selection. The fallback value will be 0.
+ uint32_t start =
+ range.IsValid() ? range.start() : GetCurrentCursorPositionInFrame(this);
+
+ WebLocalFrameImpl::FromFrame(this)->FirstRectForCharacterRange(
+ start, range.length(), web_rect);
+ rect.SetRect(web_rect.x, web_rect.y, web_rect.width, web_rect.height);
+ }
+
+ GetTextInputHost().GotFirstRectForRange(rect);
+}
+#endif
+
HitTestResult LocalFrame::HitTestResultForVisualViewportPos(
const IntPoint& pos_in_viewport) {
IntPoint root_frame_point(
@@ -2219,7 +2283,23 @@ void LocalFrame::AddMessageToConsole(mojom::blink::ConsoleMessageLevel level,
}
void LocalFrame::AddInspectorIssue(mojom::blink::InspectorIssueInfoPtr info) {
- GetDocument()->AddInspectorIssue(InspectorIssue::Create(std::move(info)));
+ if (GetPage()) {
+ GetPage()->GetInspectorIssueStorage().AddInspectorIssue(DomWindow(), std::move(info));
+ }
+}
+
+void LocalFrame::StopLoading() {
+ Loader().StopAllLoaders();
+
+ // The stopLoading handler may run script, which may cause this frame to be
+ // detached/deleted. If that happens, return immediately.
+ if (!IsAttached())
+ return;
+
+ // Notify RenderFrame observers.
+ WebLocalFrameClient* client = Client()->GetWebFrame()->Client();
+ if (client)
+ client->OnStopLoading();
}
void LocalFrame::Collapse(bool collapsed) {
@@ -2448,6 +2528,19 @@ void LocalFrame::MediaPlayerActionAt(
MediaPlayerActionAtViewportPoint(location, action->type, action->enable);
}
+void LocalFrame::AdvanceFocusInFrame(
+ mojom::blink::FocusType focus_type,
+ const base::Optional<base::UnguessableToken>& source_frame_token) {
+ RemoteFrame* source_frame = SourceFrameForOptionalToken(source_frame_token);
+ if (!source_frame) {
+ SetInitialFocus(focus_type == mojom::blink::FocusType::kBackward);
+ return;
+ }
+
+ GetPage()->GetFocusController().AdvanceFocusAcrossFrames(focus_type,
+ source_frame, this);
+}
+
void LocalFrame::AdvanceFocusInForm(mojom::blink::FocusType focus_type) {
auto* focused_frame = GetPage()->GetFocusController().FocusedFrame();
if (focused_frame != this)
@@ -2504,6 +2597,84 @@ void LocalFrame::DidUpdateFramePolicy(const FramePolicy& frame_policy) {
To<RemoteFrameOwner>(Owner())->SetFramePolicy(frame_policy);
}
+void LocalFrame::OnScreensChange() {
+ if (RuntimeEnabledFeatures::WindowPlacementEnabled()) {
+ DomWindow()->DispatchEvent(
+ *Event::Create(event_type_names::kScreenschange));
+ }
+}
+
+void LocalFrame::PostMessageEvent(
+ const base::Optional<base::UnguessableToken>& source_frame_token,
+ const String& source_origin,
+ const String& target_origin,
+ BlinkTransferableMessage message) {
+ RemoteFrame* source_frame = SourceFrameForOptionalToken(source_frame_token);
+
+ // We must pass in the target_origin to do the security check on this side,
+ // since it may have changed since the original postMessage call was made.
+ scoped_refptr<SecurityOrigin> target_security_origin;
+ if (!target_origin.IsEmpty()) {
+ target_security_origin = SecurityOrigin::CreateFromString(target_origin);
+ }
+
+ // Preparation of the MessageEvent.
+ MessageEvent* message_event = MessageEvent::Create();
+ DOMWindow* window = nullptr;
+ if (source_frame)
+ window = source_frame->DomWindow();
+ MessagePortArray* ports = nullptr;
+ if (GetDocument()) {
+ ports = MessagePort::EntanglePorts(*GetDocument()->GetExecutionContext(),
+ std::move(message.ports));
+ }
+ UserActivation* user_activation = nullptr;
+ if (message.user_activation) {
+ user_activation = MakeGarbageCollected<UserActivation>(
+ message.user_activation->has_been_active,
+ message.user_activation->was_active);
+ }
+ message_event->initMessageEvent(
+ "message", false, false, std::move(message.message), source_origin,
+ "" /*lastEventId*/, window, ports, user_activation,
+ message.transfer_user_activation, message.allow_autoplay);
+
+ // If the agent cluster id had a value it means this was locked when it
+ // was serialized.
+ if (message.locked_agent_cluster_id)
+ message_event->LockToAgentCluster();
+
+ // Transfer user activation state in the target's renderer when
+ // |transferUserActivation| is true.
+ //
+ // Also do the same as an ad-hoc solution to allow the origin trial of dynamic
+ // delegation of autoplay capability through postMessages. Note that we
+ // skipped updating the user activation states in all other copies of the
+ // frame tree in this case because this is a temporary hack.
+ //
+ // TODO(mustaq): Remove the ad-hoc solution when the API shape is
+ // ready. https://crbug.com/985914
+ if ((RuntimeEnabledFeatures::UserActivationPostMessageTransferEnabled() &&
+ message.transfer_user_activation) ||
+ message.allow_autoplay) {
+ TransferUserActivationFrom(source_frame);
+ if (message.allow_autoplay)
+ UseCounter::Count(GetDocument(), WebFeature::kAutoplayDynamicDelegation);
+ }
+
+ // Finally dispatch the message to the DOM Window.
+ DomWindow()->DispatchMessageEventWithOriginCheck(
+ target_security_origin.get(), message_event,
+ std::make_unique<SourceLocation>(String(), 0, 0, nullptr),
+ message.locked_agent_cluster_id ? message.locked_agent_cluster_id.value()
+ : base::UnguessableToken());
+}
+
+void LocalFrame::BindReportingObserver(
+ mojo::PendingReceiver<mojom::blink::ReportingObserver> receiver) {
+ ReportingContext::From(DomWindow())->Bind(std::move(receiver));
+}
+
bool LocalFrame::ShouldThrottleDownload() {
const auto now = base::TimeTicks::Now();
if (num_burst_download_requests_ == 0) {
@@ -2523,6 +2694,13 @@ bool LocalFrame::ShouldThrottleDownload() {
return false;
}
+#if defined(OS_MACOSX)
+mojom::blink::TextInputHost& LocalFrame::GetTextInputHost() {
+ DCHECK(text_input_host_);
+ return *text_input_host_.get();
+}
+#endif
+
void LocalFrame::BindToReceiver(
blink::LocalFrame* frame,
mojo::PendingAssociatedReceiver<mojom::blink::LocalFrame> receiver) {
@@ -2541,4 +2719,19 @@ void LocalFrame::BindToMainFrameReceiver(
frame->GetTaskRunner(blink::TaskType::kInternalDefault));
}
+SpellChecker& LocalFrame::GetSpellChecker() const {
+ DCHECK(DomWindow());
+ return DomWindow()->GetSpellChecker();
+}
+
+InputMethodController& LocalFrame::GetInputMethodController() const {
+ DCHECK(DomWindow());
+ return DomWindow()->GetInputMethodController();
+}
+
+TextSuggestionController& LocalFrame::GetTextSuggestionController() const {
+ DCHECK(DomWindow());
+ return DomWindow()->GetTextSuggestionController();
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/frame/local_frame.h b/chromium/third_party/blink/renderer/core/frame/local_frame.h
index 30763d3fc99..a222d33ca63 100644
--- a/chromium/third_party/blink/renderer/core/frame/local_frame.h
+++ b/chromium/third_party/blink/renderer/core/frame/local_frame.h
@@ -34,6 +34,7 @@
#include "base/macros.h"
#include "base/time/default_tick_clock.h"
#include "base/unguessable_token.h"
+#include "build/build_config.h"
#include "mojo/public/cpp/bindings/associated_receiver.h"
#include "mojo/public/cpp/bindings/associated_remote.h"
#include "mojo/public/cpp/bindings/pending_associated_receiver.h"
@@ -42,6 +43,7 @@
#include "third_party/blink/public/mojom/frame/frame.mojom-blink.h"
#include "third_party/blink/public/mojom/frame/frame_owner_properties.mojom-blink-forward.h"
#include "third_party/blink/public/mojom/frame/lifecycle.mojom-blink-forward.h"
+#include "third_party/blink/public/mojom/frame/reporting_observer.mojom-blink-forward.h"
#include "third_party/blink/public/mojom/input/focus_type.mojom-blink-forward.h"
#include "third_party/blink/public/mojom/loader/pause_subresource_loading_handle.mojom-blink-forward.h"
#include "third_party/blink/public/mojom/reporting/reporting.mojom-blink.h"
@@ -56,7 +58,6 @@
#include "third_party/blink/renderer/core/frame/frame.h"
#include "third_party/blink/renderer/core/frame/frame_types.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
-#include "third_party/blink/renderer/core/inspector/inspector_issue.h"
#include "third_party/blink/renderer/core/loader/frame_loader.h"
#include "third_party/blink/renderer/platform/graphics/touch_action.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
@@ -64,6 +65,9 @@
#include "third_party/blink/renderer/platform/loader/fetch/client_hints_preferences.h"
#include "third_party/blink/renderer/platform/scheduler/public/frame_scheduler.h"
#include "third_party/blink/renderer/platform/supplementable.h"
+#if defined(OS_MACOSX)
+#include "third_party/blink/public/mojom/input/text_input_host.mojom-blink.h"
+#endif
namespace base {
class SingleThreadTaskRunner;
@@ -73,6 +77,12 @@ namespace gfx {
class Point;
}
+#if defined(OS_MACOSX)
+namespace gfx {
+class Range;
+}
+#endif
+
namespace blink {
class AdTracker;
@@ -131,6 +141,7 @@ class CORE_EXPORT LocalFrame final : public Frame,
LocalFrameClient*,
Page&,
FrameOwner*,
+ const base::UnguessableToken& frame_token,
WindowAgentFactory* inheriting_agent_factory,
InterfaceRegistry*,
const base::TickClock* clock = base::DefaultTickClock::GetInstance());
@@ -261,6 +272,10 @@ class CORE_EXPORT LocalFrame final : public Frame,
void DeviceScaleFactorChanged();
double DevicePixelRatio() const;
+ // Informs the local root's document and its local descendant subtree that a
+ // media query value changed.
+ void MediaQueryAffectingValueChangedForLocalSubtree(MediaValueChange);
+
String SelectedText() const;
String SelectedTextForClipboard() const;
@@ -510,6 +525,7 @@ class CORE_EXPORT LocalFrame final : public Frame,
const WTF::String& message,
bool discard_duplicates) final;
void AddInspectorIssue(mojom::blink::InspectorIssueInfoPtr) final;
+ void StopLoading() final;
void Collapse(bool collapsed) final;
void EnableViewSourceMode() final;
void Focus() final;
@@ -526,6 +542,9 @@ class CORE_EXPORT LocalFrame final : public Frame,
void MediaPlayerActionAt(
const gfx::Point& window_point,
blink::mojom::blink::MediaPlayerActionPtr action) final;
+ void AdvanceFocusInFrame(
+ mojom::blink::FocusType focus_type,
+ const base::Optional<base::UnguessableToken>& source_frame_token) final;
void AdvanceFocusInForm(mojom::blink::FocusType focus_type) final;
void ReportContentSecurityPolicyViolation(
network::mojom::blink::CSPViolationPtr csp_violation) final;
@@ -535,6 +554,14 @@ class CORE_EXPORT LocalFrame final : public Frame,
// sandbox flags or container policy. The new policy won't take effect until
// the next navigation.
void DidUpdateFramePolicy(const FramePolicy& frame_policy) final;
+ void OnScreensChange() final;
+ void PostMessageEvent(
+ const base::Optional<base::UnguessableToken>& source_frame_token,
+ const String& source_origin,
+ const String& target_origin,
+ BlinkTransferableMessage message) final;
+ void BindReportingObserver(
+ mojo::PendingReceiver<mojom::blink::ReportingObserver> receiver) final;
// blink::mojom::LocalMainFrame overrides:
void AnimateDoubleTapZoom(const gfx::Point& point,
@@ -548,6 +575,10 @@ class CORE_EXPORT LocalFrame final : public Frame,
void SetInitialFocus(bool reverse) override;
void EnablePreferredSizeChangedMode() override;
void ZoomToFindInPageRect(const gfx::Rect& rect_in_root_frame) override;
+#if defined(OS_MACOSX)
+ void GetCharacterIndexAtPoint(const gfx::Point& point) final;
+ void GetFirstRectForRange(const gfx::Range& range) final;
+#endif
SystemClipboard* GetSystemClipboard();
RawSystemClipboard* GetRawSystemClipboard();
@@ -561,6 +592,7 @@ class CORE_EXPORT LocalFrame final : public Frame,
private:
friend class FrameNavigationDisabler;
+ FRIEND_TEST_ALL_PREFIXES(LocalFrameTest, CharacterIndexAtPointWithPinchZoom);
// Frame protected overrides:
void DetachImpl(FrameDetachType) override;
@@ -614,6 +646,10 @@ class CORE_EXPORT LocalFrame final : public Frame,
bool ShouldThrottleDownload();
+#if defined(OS_MACOSX)
+ mojom::blink::TextInputHost& GetTextInputHost();
+#endif
+
static void BindToReceiver(
blink::LocalFrame* frame,
mojo::PendingAssociatedReceiver<mojom::blink::LocalFrame> receiver);
@@ -638,12 +674,9 @@ class CORE_EXPORT LocalFrame final : public Frame,
const Member<ScriptController> script_controller_;
const Member<Editor> editor_;
- const Member<SpellChecker> spell_checker_;
const Member<FrameSelection> selection_;
const Member<EventHandler> event_handler_;
const Member<FrameConsole> console_;
- const Member<InputMethodController> input_method_controller_;
- const Member<TextSuggestionController> text_suggestion_controller_;
int navigation_disable_count_;
// TODO(dcheng): In theory, this could be replaced by checking the
@@ -673,6 +706,10 @@ class CORE_EXPORT LocalFrame final : public Frame,
// const methods.
mutable mojo::Remote<mojom::blink::ReportingServiceProxy> reporting_service_;
+#if defined(OS_MACOSX)
+ mojo::Remote<mojom::blink::TextInputHost> text_input_host_;
+#endif
+
ViewportIntersectionState intersection_state_;
// Per-frame URLLoader factory.
@@ -744,23 +781,10 @@ inline Editor& LocalFrame::GetEditor() const {
return *editor_;
}
-inline SpellChecker& LocalFrame::GetSpellChecker() const {
- return *spell_checker_;
-}
-
inline FrameConsole& LocalFrame::Console() const {
return *console_;
}
-inline InputMethodController& LocalFrame::GetInputMethodController() const {
- return *input_method_controller_;
-}
-
-inline TextSuggestionController& LocalFrame::GetTextSuggestionController()
- const {
- return *text_suggestion_controller_;
-}
-
inline bool LocalFrame::InViewSourceMode() const {
return in_view_source_mode_;
}
diff --git a/chromium/third_party/blink/renderer/core/frame/local_frame_client.h b/chromium/third_party/blink/renderer/core/frame/local_frame_client.h
index 5faee38f8a7..b9a8d9bce7a 100644
--- a/chromium/third_party/blink/renderer/core/frame/local_frame_client.h
+++ b/chromium/third_party/blink/renderer/core/frame/local_frame_client.h
@@ -49,6 +49,7 @@
#include "third_party/blink/public/platform/scheduler/web_scoped_virtual_time_pauser.h"
#include "third_party/blink/public/platform/web_content_settings_client.h"
#include "third_party/blink/public/platform/web_effective_connection_type.h"
+#include "third_party/blink/public/platform/web_impression.h"
#include "third_party/blink/public/platform/web_worker_fetch_context.h"
#include "third_party/blink/public/web/web_frame_load_type.h"
#include "third_party/blink/public/web/web_history_commit_type.h"
@@ -146,7 +147,6 @@ class CORE_EXPORT LocalFrameClient : public FrameClient {
DocumentLoader*,
WebNavigationType,
NavigationPolicy,
- bool has_transient_activation,
WebFrameLoadType,
bool is_client_redirect,
TriggeringEventInfo,
@@ -156,6 +156,7 @@ class CORE_EXPORT LocalFrameClient : public FrameClient {
mojo::PendingRemote<mojom::blink::BlobURLToken>,
base::TimeTicks input_start_time,
const String& href_translate,
+ const base::Optional<WebImpression>& impression,
WTF::Vector<network::mojom::blink::ContentSecurityPolicyPtr>
initiator_csp,
network::mojom::blink::CSPSourcePtr initiator_self_source,
@@ -206,6 +207,13 @@ class CORE_EXPORT LocalFrameClient : public FrameClient {
virtual void DidObserveLayoutShift(double score, bool after_input_or_scroll) {
}
+ // Reports the number of LayoutBlock creation, and LayoutObject::UpdateLayout
+ // calls. All values are deltas since the last calls of this function.
+ virtual void DidObserveLayoutNg(uint32_t all_block_count,
+ uint32_t ng_block_count,
+ uint32_t all_call_count,
+ uint32_t ng_call_count) {}
+
// Reports lazy loaded behavior when the frame or image is fully deferred or
// if the frame or image is loaded after being deferred. Called every time the
// behavior occurs. This does not apply to images that were loaded as
@@ -280,7 +288,7 @@ class CORE_EXPORT LocalFrameClient : public FrameClient {
HTMLMediaElement&) = 0;
virtual void DidCreateInitialEmptyDocument() = 0;
- virtual void DidCommitJavascriptUrlNavigation(DocumentLoader*) = 0;
+ virtual void DidCommitDocumentReplacementNavigation(DocumentLoader*) = 0;
virtual void DispatchDidClearWindowObjectInMainWorld() = 0;
virtual void DocumentElementAvailable() = 0;
virtual void RunScriptsAtDocumentElementAvailable() = 0;
@@ -307,12 +315,10 @@ class CORE_EXPORT LocalFrameClient : public FrameClient {
virtual void DidChangeFramePolicy(Frame* child_frame, const FramePolicy&) {}
virtual void DidSetFramePolicyHeaders(
- mojom::blink::WebSandboxFlags,
+ network::mojom::blink::WebSandboxFlags,
const ParsedFeaturePolicy& feature_policy_header,
const DocumentPolicy::FeatureState& document_policy_header) {}
- virtual void DidChangeFrameOwnerProperties(HTMLFrameOwnerElement*) {}
-
virtual std::unique_ptr<WebServiceWorkerProvider>
CreateServiceWorkerProvider() = 0;
diff --git a/chromium/third_party/blink/renderer/core/frame/local_frame_test.cc b/chromium/third_party/blink/renderer/core/frame/local_frame_test.cc
index 0d63d5a2b8e..d1f8b812ac8 100644
--- a/chromium/third_party/blink/renderer/core/frame/local_frame_test.cc
+++ b/chromium/third_party/blink/renderer/core/frame/local_frame_test.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/core/frame/local_frame.h"
+#include "build/build_config.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/core/dom/node_computed_style.h"
#include "third_party/blink/renderer/core/frame/settings.h"
@@ -13,6 +14,13 @@
#include "third_party/blink/renderer/platform/loader/fetch/fetch_parameters.h"
#include "third_party/blink/renderer/platform/network/network_state_notifier.h"
#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
+#if defined(OS_MACOSX)
+#include "mojo/public/cpp/bindings/receiver.h"
+#include "third_party/blink/public/mojom/input/text_input_host.mojom-blink.h"
+#include "third_party/blink/renderer/core/frame/frame_test_helpers.h"
+#include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
+#include "third_party/blink/renderer/platform/testing/url_test_helpers.h"
+#endif
namespace blink {
@@ -25,6 +33,51 @@ void EnableLazyLoadInSettings(Settings& settings) {
settings.SetLazyLoadEnabled(true);
}
+#if defined(OS_MACOSX)
+void RegisterMockedHttpURLLoad(const std::string& base_url,
+ const std::string& file_name) {
+ url_test_helpers::RegisterMockedURLLoadFromBase(
+ WebString::FromUTF8(base_url), test::CoreTestDataPath(),
+ WebString::FromUTF8(file_name));
+}
+
+class TestTextInputHostWaiter : public mojom::blink::TextInputHost {
+ public:
+ TestTextInputHostWaiter() = default;
+ ~TestTextInputHostWaiter() override = default;
+
+ void Init(base::OnceClosure callback,
+ blink::BrowserInterfaceBrokerProxy& provider) {
+ callback_ = std::move(callback);
+ provider.SetBinderForTesting(
+ mojom::blink::TextInputHost::Name_,
+ base::BindRepeating(&TestTextInputHostWaiter::BindTextInputHostReceiver,
+ base::Unretained(this)));
+ }
+
+ void GotCharacterIndexAtPoint(uint32_t index) override {
+ index_ = index;
+ if (callback_)
+ std::move(callback_).Run();
+ }
+
+ void GotFirstRectForRange(const gfx::Rect& rect) override {}
+
+ void BindTextInputHostReceiver(
+ mojo::ScopedMessagePipeHandle message_pipe_handle) {
+ receiver_.Bind(mojo::PendingReceiver<mojom::blink::TextInputHost>(
+ std::move(message_pipe_handle)));
+ }
+
+ uint32_t index() { return index_; }
+
+ private:
+ mojo::Receiver<mojom::blink::TextInputHost> receiver_{this};
+ uint32_t index_;
+ base::OnceClosure callback_;
+};
+#endif
+
} // namespace
class LocalFrameTest : public testing::Test {
@@ -185,4 +238,35 @@ TEST_F(LocalFrameTest, ForceSynchronousDocumentInstall_XMLStyleSheet) {
TestGreenDiv(*page_holder);
}
+#if defined(OS_MACOSX)
+TEST_F(LocalFrameTest, CharacterIndexAtPointWithPinchZoom) {
+ RegisterMockedHttpURLLoad("http://internal.test/", "sometext.html");
+
+ frame_test_helpers::WebViewHelper web_view_helper;
+ web_view_helper.InitializeAndLoad("http://internal.test/sometext.html");
+ web_view_helper.LoadAhem();
+ web_view_helper.Resize(WebSize(640, 480));
+
+ // Move the visual viewport to the start of the target div containing the
+ // text.
+ web_view_helper.GetWebView()->SetPageScaleFactor(2);
+ web_view_helper.GetWebView()->SetVisualViewportOffset(gfx::PointF(100, 50));
+
+ Page* page = web_view_helper.GetWebView()->GetPage();
+ LocalFrame* main_frame = DynamicTo<LocalFrame>(page->MainFrame());
+ main_frame->text_input_host_.reset();
+
+ base::RunLoop run_loop;
+ TestTextInputHostWaiter waiter;
+ waiter.Init(run_loop.QuitClosure(), main_frame->GetBrowserInterfaceBroker());
+ main_frame->GetBrowserInterfaceBroker().GetInterface(
+ main_frame->text_input_host_.BindNewPipeAndPassReceiver());
+ // Since we're zoomed in to 2X, each char of Ahem is 20px wide/tall in
+ // viewport space. We expect to hit the fifth char on the first line.
+ main_frame->GetCharacterIndexAtPoint(gfx::Point(100, 15));
+ run_loop.Run();
+ EXPECT_EQ(waiter.index(), 5ul);
+}
+#endif
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/frame/local_frame_ukm_aggregator.h b/chromium/third_party/blink/renderer/core/frame/local_frame_ukm_aggregator.h
index ef31447acc5..d5d0f2e5315 100644
--- a/chromium/third_party/blink/renderer/core/frame/local_frame_ukm_aggregator.h
+++ b/chromium/third_party/blink/renderer/core/frame/local_frame_ukm_aggregator.h
@@ -5,7 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_LOCAL_FRAME_UKM_AGGREGATOR_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_LOCAL_FRAME_UKM_AGGREGATOR_H_
-#include "cc/metrics/frame_sequence_tracker.h"
+#include "cc/metrics/frame_sequence_tracker_collection.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/instrumentation/histogram.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
diff --git a/chromium/third_party/blink/renderer/core/frame/local_frame_view.cc b/chromium/third_party/blink/renderer/core/frame/local_frame_view.cc
index afab16121f7..a64c209a396 100644
--- a/chromium/third_party/blink/renderer/core/frame/local_frame_view.cc
+++ b/chromium/third_party/blink/renderer/core/frame/local_frame_view.cc
@@ -49,6 +49,7 @@
#include "third_party/blink/renderer/core/animation/document_animations.h"
#include "third_party/blink/renderer/core/css/font_face_set_document.h"
#include "third_party/blink/renderer/core/css/style_change_reason.h"
+#include "third_party/blink/renderer/core/display_lock/display_lock_utilities.h"
#include "third_party/blink/renderer/core/dom/static_node_list.h"
#include "third_party/blink/renderer/core/editing/compute_layer_selection.h"
#include "third_party/blink/renderer/core/editing/drag_caret.h"
@@ -60,6 +61,7 @@
#include "third_party/blink/renderer/core/frame/find_in_page.h"
#include "third_party/blink/renderer/core/frame/frame_overlay.h"
#include "third_party/blink/renderer/core/frame/frame_view_auto_size_info.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/local_frame_client.h"
#include "third_party/blink/renderer/core/frame/local_frame_ukm_aggregator.h"
@@ -155,7 +157,7 @@
#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/base/cursor/cursor.h"
-#include "ui/base/mojom/cursor_type.mojom-blink.h"
+#include "ui/base/cursor/mojom/cursor_type.mojom-blink.h"
// Used to check for dirty layouts violating document lifecycle rules.
// If arg evaluates to true, the program will continue. If arg evaluates to
@@ -230,7 +232,6 @@ LocalFrameView::LocalFrameView(LocalFrame& frame, const IntSize& initial_size)
LocalFrameView::LocalFrameView(LocalFrame& frame, IntRect frame_rect)
: FrameView(frame_rect),
frame_(frame),
- display_mode_(blink::mojom::DisplayMode::kBrowser),
can_have_scrollbars_(true),
has_pending_layout_(false),
layout_scheduling_enabled_(true),
@@ -271,7 +272,7 @@ LocalFrameView::LocalFrameView(LocalFrame& frame, IntRect frame_rect)
forced_layout_start_time_(base::TimeTicks()),
paint_frame_count_(0),
unique_id_(NewUniqueObjectId()),
- layout_shift_tracker_(std::make_unique<LayoutShiftTracker>(this)),
+ layout_shift_tracker_(MakeGarbageCollected<LayoutShiftTracker>(this)),
paint_timing_detector_(MakeGarbageCollected<PaintTimingDetector>(this))
#if DCHECK_IS_ON()
,
@@ -301,6 +302,7 @@ void LocalFrameView::Trace(Visitor* visitor) {
visitor->Trace(viewport_scrollable_area_);
visitor->Trace(anchoring_adjustment_queue_);
visitor->Trace(scroll_event_queue_);
+ visitor->Trace(layout_shift_tracker_);
visitor->Trace(paint_timing_detector_);
visitor->Trace(lifecycle_observers_);
}
@@ -639,11 +641,37 @@ void LocalFrameView::PerformPreLayoutTasks() {
Lifecycle().AdvanceTo(DocumentLifecycle::kStyleClean);
- if (was_resized)
+ if (was_resized) {
document->ClearResizedForViewportUnits();
+
+ // Mark all of writing-mode roots for layout, as the ICB size has changed.
+ MarkOrthogonalWritingModeRootsForLayout();
+ }
}
-void LocalFrameView::LayoutFromRootObject(LayoutObject& root) {
+bool LocalFrameView::LayoutFromRootObject(LayoutObject& root) {
+ if (!root.NeedsLayout())
+ return false;
+
+ if (auto* locked_ancestor =
+ DisplayLockUtilities::LockedAncestorPreventingLayout(root)) {
+ // Note that since we're preventing the layout on a layout root, we have to
+ // mark its ancestor chain for layout. The reason for this is that we will
+ // clear the layout roots whether or not we have finished laying them out,
+ // so the fact that this root still needs layout will be lost if we don't
+ // mark its container chain.
+ //
+ // Also, since we know that this root has a layout-blocking ancestor, the
+ // layout bit propagation will stop there.
+ //
+ // TODO(vmpstr): Note that an alternative to this approach is to keep `root`
+ // as a layout root in `layout_subtree_root_list_`. It would mean that we
+ // will keep it in the list while the display-lock prevents layout. We need
+ // to investigate which of these approaches is better.
+ root.MarkContainerChainForLayout();
+ return false;
+ }
+
LayoutState layout_state(root);
if (scrollable_areas_) {
for (auto& scrollable_area : *scrollable_areas_) {
@@ -654,6 +682,7 @@ void LocalFrameView::LayoutFromRootObject(LayoutObject& root) {
}
root.UpdateLayout();
+ return true;
}
void LocalFrameView::PrepareLayoutAnalyzer() {
@@ -730,9 +759,8 @@ void LocalFrameView::PerformLayout(bool in_subtree_layout) {
layout_subtree_root_list_.size());
}
for (auto& root : layout_subtree_root_list_.Ordered()) {
- if (!root->NeedsLayout())
+ if (!LayoutFromRootObject(*root))
continue;
- LayoutFromRootObject(*root);
root->PaintingLayer()->UpdateLayerPositionsAfterLayout();
@@ -1181,18 +1209,6 @@ void LocalFrameView::AddPartToUpdate(LayoutEmbeddedObject& object) {
part_update_set_.insert(&object);
}
-void LocalFrameView::SetDisplayMode(blink::mojom::DisplayMode mode) {
- if (mode == display_mode_)
- return;
-
- display_mode_ = mode;
-
- if (frame_->GetDocument()) {
- frame_->GetDocument()->MediaQueryAffectingValueChanged(
- MediaValueChange::kOther);
- }
-}
-
void LocalFrameView::SetDisplayShape(DisplayShape display_shape) {
if (display_shape == display_shape_)
return;
@@ -1279,16 +1295,35 @@ bool LocalFrameView::RequiresMainThreadScrollingForBackgroundAttachmentFixed()
return true;
}
-void LocalFrameView::AddViewportConstrainedObject(LayoutObject& object) {
+void LocalFrameView::AddViewportConstrainedObject(
+ LayoutObject& object,
+ ViewportConstrainedType constrained_reason) {
if (!viewport_constrained_objects_)
viewport_constrained_objects_ = std::make_unique<ObjectSet>();
- viewport_constrained_objects_->insert(&object);
+ auto result = viewport_constrained_objects_->insert(&object);
+ if (constrained_reason == ViewportConstrainedType::kSticky) {
+ if (result.is_new_entry) {
+ sticky_position_object_count_++;
+ }
+ DCHECK_LE(sticky_position_object_count_,
+ viewport_constrained_objects_->size());
+ }
}
-void LocalFrameView::RemoveViewportConstrainedObject(LayoutObject& object) {
- if (viewport_constrained_objects_)
- viewport_constrained_objects_->erase(&object);
+void LocalFrameView::RemoveViewportConstrainedObject(
+ LayoutObject& object,
+ ViewportConstrainedType constrained_reason) {
+ if (viewport_constrained_objects_) {
+ auto it = viewport_constrained_objects_->find(&object);
+ if (it != viewport_constrained_objects_->end()) {
+ viewport_constrained_objects_->erase(it);
+ if (constrained_reason == ViewportConstrainedType::kSticky) {
+ DCHECK_GT(sticky_position_object_count_, 0U);
+ sticky_position_object_count_--;
+ }
+ }
+ }
}
void LocalFrameView::ViewportSizeChanged(bool width_changed,
@@ -1623,6 +1658,17 @@ void LocalFrameView::ScheduleOrthogonalWritingModeRootsForLayout() {
}
}
+void LocalFrameView::MarkOrthogonalWritingModeRootsForLayout() {
+ for (auto& root : orthogonal_writing_mode_root_list_.Ordered()) {
+ // OOF-positioned objects don't depend on the ICB size.
+ if (root->NeedsLayout() || root->IsOutOfFlowPositioned())
+ continue;
+
+ root->SetNeedsLayoutAndIntrinsicWidthsRecalc(
+ layout_invalidation_reason::kSizeChanged);
+ }
+}
+
bool LocalFrameView::CheckLayoutInvalidationIsAllowed() const {
#if DCHECK_IS_ON()
if (allows_layout_invalidation_after_layout_clean_)
@@ -1694,7 +1740,8 @@ void LocalFrameView::ScheduleRelayoutOfSubtree(LayoutObject* relayout_root) {
if (!ShouldThrottleRendering())
GetPage()->Animator().ScheduleVisualUpdate(frame_.Get());
- Lifecycle().EnsureStateAtMost(DocumentLifecycle::kStyleClean);
+ if (GetPage()->Animator().IsServicingAnimations())
+ Lifecycle().EnsureStateAtMost(DocumentLifecycle::kStyleClean);
}
TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"),
"InvalidateLayout", TRACE_EVENT_SCOPE_THREAD, "data",
@@ -2191,34 +2238,33 @@ bool LocalFrameView::NotifyResizeObservers(
return false;
// Controller exists only if ResizeObserver was created.
- if (!GetFrame().GetDocument()->GetResizeObserverController())
+ ResizeObserverController* resize_controller =
+ ResizeObserverController::FromIfExists(*GetFrame().DomWindow());
+ if (!resize_controller)
return false;
- ResizeObserverController& resize_controller =
- frame_->GetDocument()->EnsureResizeObserverController();
-
DCHECK(Lifecycle().GetState() >= DocumentLifecycle::kPrePaintClean);
- size_t min_depth = resize_controller.GatherObservations();
+ size_t min_depth = resize_controller->GatherObservations();
if (min_depth != ResizeObserverController::kDepthBottom) {
- resize_controller.DeliverObservations();
+ resize_controller->DeliverObservations();
} else {
// Observation depth limit reached
- if (resize_controller.SkippedObservations()) {
- resize_controller.ClearObservations();
+ if (resize_controller->SkippedObservations() &&
+ !resize_controller->IsLoopLimitErrorDispatched()) {
+ resize_controller->ClearObservations();
ErrorEvent* error = ErrorEvent::Create(
"ResizeObserver loop limit exceeded",
- SourceLocation::Capture(frame_->GetDocument()->ToExecutionContext()),
- nullptr);
+ SourceLocation::Capture(frame_->DomWindow()), nullptr);
// We're using |SanitizeScriptErrors::kDoNotSanitize| as the error is made
// by blink itself.
// TODO(yhirano): Reconsider this.
- frame_->GetDocument()->ToExecutionContext()->DispatchErrorEvent(
+ frame_->DomWindow()->DispatchErrorEvent(
error, SanitizeScriptErrors::kDoNotSanitize);
// Ensure notifications will get delivered in next cycle.
ScheduleAnimation();
- DCHECK(Lifecycle().GetState() >= DocumentLifecycle::kPrePaintClean);
+ resize_controller->SetLoopLimitErrorDispatched(true);
}
if (Lifecycle().GetState() >= DocumentLifecycle::kPrePaintClean)
return false;
@@ -2433,9 +2479,10 @@ bool LocalFrameView::RunResizeObserverSteps(
}
if (!re_run_lifecycles) {
ForAllNonThrottledLocalFrameViews([](LocalFrameView& frame_view) {
- ResizeObserverController& resize_controller =
- frame_view.frame_->GetDocument()->EnsureResizeObserverController();
- resize_controller.ClearMinDepth();
+ ResizeObserverController* resize_controller =
+ ResizeObserverController::From(*frame_view.frame_->DomWindow());
+ resize_controller->ClearMinDepth();
+ resize_controller->SetLoopLimitErrorDispatched(false);
});
}
return re_run_lifecycles;
@@ -2972,9 +3019,18 @@ void LocalFrameView::PushPaintArtifactToCompositor() {
paint_controller_->CommitNewDisplayItems();
}
+ WTF::Vector<const TransformPaintPropertyNode*> scroll_translation_nodes;
+ if (RuntimeEnabledFeatures::ScrollUnificationEnabled()) {
+ ForAllNonThrottledLocalFrameViews(
+ [&scroll_translation_nodes](LocalFrameView& frame_view) {
+ scroll_translation_nodes.AppendVector(
+ frame_view.GetScrollTranslationNodes());
+ });
+ }
+
paint_artifact_compositor_->Update(
paint_controller_->GetPaintArtifactShared(), viewport_properties,
- settings);
+ settings, scroll_translation_nodes);
probe::LayerTreePainted(&GetFrame());
}
@@ -4545,4 +4601,17 @@ LocalFrameView::EnsureOverlayInterstitialAdDetector() {
return *overlay_interstitial_ad_detector_.get();
}
+WTF::Vector<const TransformPaintPropertyNode*>
+LocalFrameView::GetScrollTranslationNodes() {
+ WTF::Vector<const TransformPaintPropertyNode*> scroll_translation_nodes;
+ for (auto area : *ScrollableAreas()) {
+ const auto* paint_properties =
+ area->GetLayoutBox()->FirstFragment().PaintProperties();
+ if (paint_properties && paint_properties->Scroll()) {
+ scroll_translation_nodes.push_back(paint_properties->ScrollTranslation());
+ }
+ }
+ return scroll_translation_nodes;
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/frame/local_frame_view.h b/chromium/third_party/blink/renderer/core/frame/local_frame_view.h
index 076606e9eed..6d0cfa5b5c7 100644
--- a/chromium/third_party/blink/renderer/core/frame/local_frame_view.h
+++ b/chromium/third_party/blink/renderer/core/frame/local_frame_view.h
@@ -30,7 +30,6 @@
#include "third_party/blink/public/common/metrics/document_update_reason.h"
#include "third_party/blink/public/mojom/frame/lifecycle.mojom-blink-forward.h"
-#include "third_party/blink/public/mojom/manifest/display_mode.mojom-shared.h"
#include "third_party/blink/public/mojom/scroll/scroll_into_view_params.mojom-blink-forward.h"
#include "third_party/blink/public/platform/shape_properties.h"
#include "third_party/blink/renderer/core/core_export.h"
@@ -177,6 +176,7 @@ class CORE_EXPORT LocalFrameView final
bool HasOrthogonalWritingModeRoots() const;
void LayoutOrthogonalWritingModeRoots();
void ScheduleOrthogonalWritingModeRootsForLayout();
+ void MarkOrthogonalWritingModeRootsForLayout();
unsigned LayoutCountForTesting() const { return layout_count_for_testing_; }
unsigned LifecycleUpdateCountForTesting() const {
@@ -275,16 +275,16 @@ class CORE_EXPORT LocalFrameView final
void SetMediaType(const AtomicString&);
void AdjustMediaTypeForPrinting(bool printing);
- blink::mojom::DisplayMode DisplayMode() { return display_mode_; }
- void SetDisplayMode(blink::mojom::DisplayMode);
-
DisplayShape GetDisplayShape() { return display_shape_; }
void SetDisplayShape(DisplayShape);
- // Fixed-position objects.
+ // For any viewport-constrained object, we need to know if it's due to fixed
+ // or sticky so that we can support HasStickyViewportConstrainedObject().
+ enum ViewportConstrainedType { kFixed = 0, kSticky = 1 };
+ // Fixed-position and viewport-constrained sticky-position objects.
typedef HashSet<LayoutObject*> ObjectSet;
- void AddViewportConstrainedObject(LayoutObject&);
- void RemoveViewportConstrainedObject(LayoutObject&);
+ void AddViewportConstrainedObject(LayoutObject&, ViewportConstrainedType);
+ void RemoveViewportConstrainedObject(LayoutObject&, ViewportConstrainedType);
const ObjectSet* ViewportConstrainedObjects() const {
return viewport_constrained_objects_.get();
}
@@ -292,6 +292,12 @@ class CORE_EXPORT LocalFrameView final
return viewport_constrained_objects_ &&
viewport_constrained_objects_->size() > 0;
}
+ // Returns true if any of the objects in viewport_constrained_objects_ are
+ // sticky position.
+ bool HasStickyViewportConstrainedObject() const {
+ DCHECK(!sticky_position_object_count_ || HasViewportConstrainedObjects());
+ return sticky_position_object_count_ > 0;
+ }
// Objects with background-attachment:fixed.
void AddBackgroundAttachmentFixedObject(LayoutObject*);
@@ -726,7 +732,7 @@ class CORE_EXPORT LocalFrameView final
~DisallowLayoutInvalidationScope();
private:
- UntracedMember<LocalFrameView> local_frame_view_;
+ LocalFrameView* local_frame_view_;
};
#endif
@@ -845,7 +851,9 @@ class CORE_EXPORT LocalFrameView final
PaintController* GetPaintController() { return paint_controller_.get(); }
- void LayoutFromRootObject(LayoutObject& root);
+ // Returns true if the root object was laid out. Returns false if the layout
+ // was prevented (e.g. by ancestor display-lock) or not needed.
+ bool LayoutFromRootObject(LayoutObject& root);
void UpdateLayerDebugInfoEnabled();
@@ -853,6 +861,8 @@ class CORE_EXPORT LocalFrameView final
// necessary.
OverlayInterstitialAdDetector& EnsureOverlayInterstitialAdDetector();
+ WTF::Vector<const TransformPaintPropertyNode*> GetScrollTranslationNodes();
+
LayoutSize size_;
typedef HashSet<scoped_refptr<LayoutEmbeddedObject>> EmbeddedObjectSet;
@@ -860,8 +870,6 @@ class CORE_EXPORT LocalFrameView final
Member<LocalFrame> frame_;
- blink::mojom::DisplayMode display_mode_;
-
DisplayShape display_shape_;
bool can_have_scrollbars_;
@@ -897,6 +905,7 @@ class CORE_EXPORT LocalFrameView final
Member<ScrollableAreaSet> scrollable_areas_;
Member<ScrollableAreaSet> animating_scrollable_areas_;
std::unique_ptr<ObjectSet> viewport_constrained_objects_;
+ // Number of entries in viewport_constrained_objects_ that are sticky.
unsigned sticky_position_object_count_;
ObjectSet background_attachment_fixed_objects_;
Member<FrameViewAutoSizeInfo> auto_size_info_;
@@ -994,7 +1003,7 @@ class CORE_EXPORT LocalFrameView final
size_t paint_frame_count_;
UniqueObjectId unique_id_;
- std::unique_ptr<LayoutShiftTracker> layout_shift_tracker_;
+ Member<LayoutShiftTracker> layout_shift_tracker_;
Member<PaintTimingDetector> paint_timing_detector_;
HeapHashSet<WeakMember<LifecycleNotificationObserver>> lifecycle_observers_;
diff --git a/chromium/third_party/blink/renderer/core/frame/local_frame_view_test.cc b/chromium/third_party/blink/renderer/core/frame/local_frame_view_test.cc
index eae22851688..73c958ac79d 100644
--- a/chromium/third_party/blink/renderer/core/frame/local_frame_view_test.cc
+++ b/chromium/third_party/blink/renderer/core/frame/local_frame_view_test.cc
@@ -344,7 +344,7 @@ TEST_F(SimTest, FragmentNavChangesFocusWhileRenderingBlocked) {
<< "Scroll offset changed while rendering is blocked";
// Force a layout.
- anchor->style()->setProperty(GetDocument().ToExecutionContext(), "display",
+ anchor->style()->setProperty(GetDocument().GetExecutionContext(), "display",
"block", String(), ASSERT_NO_EXCEPTION);
GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest);
diff --git a/chromium/third_party/blink/renderer/core/frame/location.cc b/chromium/third_party/blink/renderer/core/frame/location.cc
index 63deafc4f52..ec10b320410 100644
--- a/chromium/third_party/blink/renderer/core/frame/location.cc
+++ b/chromium/third_party/blink/renderer/core/frame/location.cc
@@ -103,6 +103,7 @@ String Location::origin() const {
}
FragmentDirective* Location::fragmentDirective() const {
+ GetDocument()->CountUse(WebFeature::kLocationFragmentDirectiveAccessed);
return fragment_directive_;
}
diff --git a/chromium/third_party/blink/renderer/core/frame/location_report_body.cc b/chromium/third_party/blink/renderer/core/frame/location_report_body.cc
index 6525fb03152..5e37642db22 100644
--- a/chromium/third_party/blink/renderer/core/frame/location_report_body.cc
+++ b/chromium/third_party/blink/renderer/core/frame/location_report_body.cc
@@ -6,21 +6,35 @@
namespace blink {
+// static
+LocationReportBody::ReportLocation LocationReportBody::CreateReportLocation(
+ const String& file,
+ base::Optional<uint32_t> line_number,
+ base::Optional<uint32_t> column_number) {
+ return file.IsEmpty() ? CreateReportLocation(SourceLocation::Capture())
+ : ReportLocation{file, line_number, column_number};
+}
+
+// static
+LocationReportBody::ReportLocation LocationReportBody::CreateReportLocation(
+ std::unique_ptr<SourceLocation> location) {
+ return location->IsUnknown()
+ ? ReportLocation{}
+ : ReportLocation{location->Url(), location->LineNumber(),
+ location->ColumnNumber()};
+}
+
void LocationReportBody::BuildJSONValue(V8ObjectBuilder& builder) const {
builder.AddStringOrNull("sourceFile", sourceFile());
- bool is_null = false;
- uint32_t line_number = lineNumber(is_null);
- if (is_null) {
- builder.AddNull("lineNumber");
+ if (lineNumber()) {
+ builder.AddNumber("lineNumber", lineNumber().value());
} else {
- builder.AddNumber("lineNumber", line_number);
+ builder.AddNull("lineNumber");
}
- is_null = true;
- uint32_t column_number = columnNumber(is_null);
- if (is_null) {
- builder.AddNull("columnNumber");
+ if (columnNumber()) {
+ builder.AddNumber("columnNumber", columnNumber().value());
} else {
- builder.AddNumber("columnNumber", column_number);
+ builder.AddNull("columnNumber");
}
}
diff --git a/chromium/third_party/blink/renderer/core/frame/location_report_body.h b/chromium/third_party/blink/renderer/core/frame/location_report_body.h
index c7f86ba18ed..67237e188a2 100644
--- a/chromium/third_party/blink/renderer/core/frame/location_report_body.h
+++ b/chromium/third_party/blink/renderer/core/frame/location_report_body.h
@@ -15,25 +15,38 @@
namespace blink {
class CORE_EXPORT LocationReportBody : public ReportBody {
- public:
+ private:
+ struct ReportLocation {
+ String file;
+ base::Optional<uint32_t> line_number;
+ base::Optional<uint32_t> column_number;
+ };
+
+ static ReportLocation CreateReportLocation(
+ const String& file,
+ base::Optional<uint32_t> line_number,
+ base::Optional<uint32_t> column_number);
+
+ static ReportLocation CreateReportLocation(
+ std::unique_ptr<SourceLocation> location);
+
+ explicit LocationReportBody(const ReportLocation& location)
+ : source_file_(location.file),
+ line_number_(location.line_number),
+ column_number_(location.column_number) {}
+
+ protected:
explicit LocationReportBody(std::unique_ptr<SourceLocation> location)
- : source_file_(location->Url()),
- line_number_(location->IsUnknown()
- ? base::nullopt
- : base::make_optional(location->LineNumber())),
- column_number_(location->IsUnknown()
- ? base::nullopt
- : base::make_optional(location->ColumnNumber())) {}
-
- LocationReportBody() : LocationReportBody(SourceLocation::Capture()) {}
-
- LocationReportBody(const String& source_file,
- base::Optional<uint32_t> line_number = base::nullopt,
- base::Optional<uint32_t> column_number = base::nullopt)
- : source_file_(source_file),
- line_number_(line_number),
- column_number_(column_number) {}
+ : LocationReportBody(CreateReportLocation(std::move(location))) {}
+
+ explicit LocationReportBody(
+ const String& source_file = g_empty_string,
+ base::Optional<uint32_t> line_number = base::nullopt,
+ base::Optional<uint32_t> column_number = base::nullopt)
+ : LocationReportBody(
+ CreateReportLocation(source_file, line_number, column_number)) {}
+ public:
~LocationReportBody() override = default;
const String& sourceFile() const { return source_file_; }
@@ -41,16 +54,6 @@ class CORE_EXPORT LocationReportBody : public ReportBody {
base::Optional<uint32_t> lineNumber() const { return line_number_; }
base::Optional<uint32_t> columnNumber() const { return column_number_; }
- // TODO(crbug.com/1060971): Remove |is_null| version.
- uint32_t lineNumber(bool& is_null) const { // DEPRECATED
- is_null = !line_number_.has_value();
- return line_number_.value_or(0);
- }
- uint32_t columnNumber(bool& is_null) const { // DEPRECATED
- is_null = !column_number_.has_value();
- return column_number_.value_or(0);
- }
-
void BuildJSONValue(V8ObjectBuilder& builder) const override;
protected:
diff --git a/chromium/third_party/blink/renderer/core/frame/mhtml_loading_test.cc b/chromium/third_party/blink/renderer/core/frame/mhtml_loading_test.cc
index b73fafeae55..2c22e859220 100644
--- a/chromium/third_party/blink/renderer/core/frame/mhtml_loading_test.cc
+++ b/chromium/third_party/blink/renderer/core/frame/mhtml_loading_test.cc
@@ -30,6 +30,8 @@
#include "base/bind_helpers.h"
#include "build/build_config.h"
+#include "services/network/public/cpp/web_sandbox_flags.h"
+#include "services/network/public/mojom/web_sandbox_flags.mojom-blink.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/platform/web_string.h"
#include "third_party/blink/public/platform/web_url.h"
@@ -119,9 +121,9 @@ TEST_F(MHTMLLoadingTest, EnforceSandboxFlags) {
// Full sandboxing with the exception to new top-level windows should be
// turned on.
- EXPECT_EQ(mojom::blink::WebSandboxFlags::kAll &
- ~(mojom::blink::WebSandboxFlags::kPopups |
- mojom::blink::WebSandboxFlags::
+ EXPECT_EQ(network::mojom::blink::WebSandboxFlags::kAll &
+ ~(network::mojom::blink::WebSandboxFlags::kPopups |
+ network::mojom::blink::WebSandboxFlags::
kPropagatesToAuxiliaryBrowsingContexts),
document->GetSandboxFlags());
@@ -140,9 +142,9 @@ TEST_F(MHTMLLoadingTest, EnforceSandboxFlags) {
Document* child_document = child_frame->GetDocument();
ASSERT_TRUE(child_document);
- EXPECT_EQ(mojom::blink::WebSandboxFlags::kAll &
- ~(mojom::blink::WebSandboxFlags::kPopups |
- mojom::blink::WebSandboxFlags::
+ EXPECT_EQ(network::mojom::blink::WebSandboxFlags::kAll &
+ ~(network::mojom::blink::WebSandboxFlags::kPopups |
+ network::mojom::blink::WebSandboxFlags::
kPropagatesToAuxiliaryBrowsingContexts),
child_document->GetSandboxFlags());
@@ -167,9 +169,9 @@ TEST_F(MHTMLLoadingTest, EnforceSandboxFlagsInXSLT) {
// Full sandboxing with the exception to new top-level windows should be
// turned on.
- EXPECT_EQ(mojom::blink::WebSandboxFlags::kAll &
- ~(mojom::blink::WebSandboxFlags::kPopups |
- mojom::blink::WebSandboxFlags::
+ EXPECT_EQ(network::mojom::blink::WebSandboxFlags::kAll &
+ ~(network::mojom::blink::WebSandboxFlags::kPopups |
+ network::mojom::blink::WebSandboxFlags::
kPropagatesToAuxiliaryBrowsingContexts),
document->GetSandboxFlags());
@@ -189,7 +191,6 @@ TEST_F(MHTMLLoadingTest, ShadowDom) {
Document* document = frame->GetDocument();
ASSERT_TRUE(document);
- EXPECT_TRUE(IsShadowHost(document->getElementById("h1")));
EXPECT_TRUE(IsShadowHost(document->getElementById("h2")));
// The nested shadow DOM tree is created.
EXPECT_TRUE(IsShadowHost(
diff --git a/chromium/third_party/blink/renderer/core/frame/navigator.cc b/chromium/third_party/blink/renderer/core/frame/navigator.cc
index f00fb00e14c..8918712cc0a 100644
--- a/chromium/third_party/blink/renderer/core/frame/navigator.cc
+++ b/chromium/third_party/blink/renderer/core/frame/navigator.cc
@@ -26,6 +26,7 @@
#include "third_party/blink/public/common/user_agent/user_agent_metadata.h"
#include "third_party/blink/renderer/bindings/core/v8/script_controller.h"
#include "third_party/blink/renderer/core/dom/document.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/navigator_id.h"
#include "third_party/blink/renderer/core/frame/settings.h"
@@ -38,9 +39,8 @@
namespace blink {
Navigator::Navigator(LocalFrame* frame)
- : NavigatorLanguage(frame ? frame->GetDocument()->ToExecutionContext()
- : nullptr),
- DOMWindowClient(frame) {}
+ : NavigatorLanguage(frame ? frame->DomWindow() : nullptr),
+ ExecutionContextClient(frame) {}
String Navigator::productSub() const {
return "20030107";
@@ -117,7 +117,7 @@ String Navigator::GetAcceptLanguages() {
void Navigator::Trace(Visitor* visitor) {
ScriptWrappable::Trace(visitor);
NavigatorLanguage::Trace(visitor);
- DOMWindowClient::Trace(visitor);
+ ExecutionContextClient::Trace(visitor);
Supplementable<Navigator>::Trace(visitor);
}
diff --git a/chromium/third_party/blink/renderer/core/frame/navigator.h b/chromium/third_party/blink/renderer/core/frame/navigator.h
index b01e1a2c6f0..4a4dd79a03f 100644
--- a/chromium/third_party/blink/renderer/core/frame/navigator.h
+++ b/chromium/third_party/blink/renderer/core/frame/navigator.h
@@ -45,7 +45,7 @@ class CORE_EXPORT Navigator final : public ScriptWrappable,
public NavigatorLanguage,
public NavigatorOnLine,
public NavigatorUA,
- public DOMWindowClient,
+ public ExecutionContextClient,
public Supplementable<Navigator> {
DEFINE_WRAPPERTYPEINFO();
USING_GARBAGE_COLLECTED_MIXIN(Navigator);
diff --git a/chromium/third_party/blink/renderer/core/frame/navigator_automation_information.idl b/chromium/third_party/blink/renderer/core/frame/navigator_automation_information.idl
index 263575eabe4..3d7ca44799b 100644
--- a/chromium/third_party/blink/renderer/core/frame/navigator_automation_information.idl
+++ b/chromium/third_party/blink/renderer/core/frame/navigator_automation_information.idl
@@ -5,7 +5,6 @@
// https://w3c.github.io/webdriver/#interface
[
- Exposed=Window,
RuntimeEnabled=AutomationControlled
] interface mixin NavigatorAutomationInformation {
readonly attribute boolean webdriver;
diff --git a/chromium/third_party/blink/renderer/core/frame/navigator_concurrent_hardware.idl b/chromium/third_party/blink/renderer/core/frame/navigator_concurrent_hardware.idl
index f10248c815f..3bb78d4b00c 100644
--- a/chromium/third_party/blink/renderer/core/frame/navigator_concurrent_hardware.idl
+++ b/chromium/third_party/blink/renderer/core/frame/navigator_concurrent_hardware.idl
@@ -4,8 +4,6 @@
// https://html.spec.whatwg.org/C/#navigator.hardwareconcurrency
-[
- Exposed=(Window, Worker)
-] interface mixin NavigatorConcurrentHardware {
+interface mixin NavigatorConcurrentHardware {
[HighEntropy, MeasureAs=NavigatorHardwareConcurrency] readonly attribute unsigned long long hardwareConcurrency;
};
diff --git a/chromium/third_party/blink/renderer/core/frame/navigator_cookies.idl b/chromium/third_party/blink/renderer/core/frame/navigator_cookies.idl
index 3909adb7bc6..a231a8627bc 100644
--- a/chromium/third_party/blink/renderer/core/frame/navigator_cookies.idl
+++ b/chromium/third_party/blink/renderer/core/frame/navigator_cookies.idl
@@ -5,5 +5,6 @@
// https://html.spec.whatwg.org/C/#cookies
interface mixin NavigatorCookies {
+ [HighEntropy,MeasureAs=NavigatorCookieEnabled]
readonly attribute boolean cookieEnabled;
};
diff --git a/chromium/third_party/blink/renderer/core/frame/navigator_device_memory.idl b/chromium/third_party/blink/renderer/core/frame/navigator_device_memory.idl
index 76295186c35..8f2f283a210 100644
--- a/chromium/third_party/blink/renderer/core/frame/navigator_device_memory.idl
+++ b/chromium/third_party/blink/renderer/core/frame/navigator_device_memory.idl
@@ -4,9 +4,7 @@
// https://github.com/w3c/device-memory#the-web-exposed-api
-[
- Exposed=(Window, Worker)
-] interface mixin NavigatorDeviceMemory {
+interface mixin NavigatorDeviceMemory {
[HighEntropy,MeasureAs=NavigatorDeviceMemory,SecureContext]
readonly attribute float deviceMemory;
};
diff --git a/chromium/third_party/blink/renderer/core/frame/navigator_id.idl b/chromium/third_party/blink/renderer/core/frame/navigator_id.idl
index 803f5e25f5a..8eb98208c8d 100644
--- a/chromium/third_party/blink/renderer/core/frame/navigator_id.idl
+++ b/chromium/third_party/blink/renderer/core/frame/navigator_id.idl
@@ -30,9 +30,7 @@
// https://html.spec.whatwg.org/C/#client-identification
-[
- Exposed=(Window,Worker)
-] interface mixin NavigatorID {
+interface mixin NavigatorID {
readonly attribute DOMString appCodeName; // constant "Mozilla"
readonly attribute DOMString appName; // constant "Netscape"
[HighEntropy, MeasureAs=NavigatorAppVersion] readonly attribute DOMString appVersion;
diff --git a/chromium/third_party/blink/renderer/core/frame/navigator_language.idl b/chromium/third_party/blink/renderer/core/frame/navigator_language.idl
index cba24ed03cb..a5a08667c91 100644
--- a/chromium/third_party/blink/renderer/core/frame/navigator_language.idl
+++ b/chromium/third_party/blink/renderer/core/frame/navigator_language.idl
@@ -4,9 +4,7 @@
// https://html.spec.whatwg.org/C/#language-preferences
-[
- Exposed=(Window, Worker)
-] interface mixin NavigatorLanguage {
+interface mixin NavigatorLanguage {
[HighEntropy, MeasureAs=NavigatorLanguage] readonly attribute DOMString language;
[CachedAttribute=IsLanguagesDirty, HighEntropy, MeasureAs=NavigatorLanguages] readonly attribute FrozenArray<DOMString> languages;
};
diff --git a/chromium/third_party/blink/renderer/core/frame/navigator_on_line.idl b/chromium/third_party/blink/renderer/core/frame/navigator_on_line.idl
index 4fcfb1344dc..63a987cf5dc 100644
--- a/chromium/third_party/blink/renderer/core/frame/navigator_on_line.idl
+++ b/chromium/third_party/blink/renderer/core/frame/navigator_on_line.idl
@@ -30,8 +30,6 @@
// https://html.spec.whatwg.org/C/#navigator.online
-[
- Exposed=(Window,Worker)
-] interface mixin NavigatorOnLine {
+interface mixin NavigatorOnLine {
readonly attribute boolean onLine;
};
diff --git a/chromium/third_party/blink/renderer/core/frame/navigator_scheduling.idl b/chromium/third_party/blink/renderer/core/frame/navigator_scheduling.idl
index 76d9e9b75a5..69c476d8b7f 100644
--- a/chromium/third_party/blink/renderer/core/frame/navigator_scheduling.idl
+++ b/chromium/third_party/blink/renderer/core/frame/navigator_scheduling.idl
@@ -2,9 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// https://github.com/tdresser/is-input-pending
+// https://github.com/WICG/is-input-pending
[
- Exposed=Window,
ImplementedAs=NavigatorScheduling,
RuntimeEnabled=ExperimentalIsInputPending
] partial interface Navigator {
diff --git a/chromium/third_party/blink/renderer/core/frame/navigator_ua.cc b/chromium/third_party/blink/renderer/core/frame/navigator_ua.cc
index 09d4cd858c3..f19b1b83a10 100644
--- a/chromium/third_party/blink/renderer/core/frame/navigator_ua.cc
+++ b/chromium/third_party/blink/renderer/core/frame/navigator_ua.cc
@@ -11,8 +11,7 @@ NavigatorUAData* NavigatorUA::userAgentData() {
MakeGarbageCollected<NavigatorUAData>(GetUAExecutionContext());
UserAgentMetadata metadata = GetUserAgentMetadata();
- ua_data->AddBrand(String::FromUTF8(metadata.brand),
- String::FromUTF8(metadata.major_version));
+ ua_data->SetBrandVersionList(metadata.brand_version_list);
ua_data->SetMobile(metadata.mobile);
ua_data->SetPlatform(String::FromUTF8(metadata.platform),
String::FromUTF8(metadata.platform_version));
diff --git a/chromium/third_party/blink/renderer/core/frame/navigator_ua_data.cc b/chromium/third_party/blink/renderer/core/frame/navigator_ua_data.cc
index c0c00cbc876..050c34a84ae 100644
--- a/chromium/third_party/blink/renderer/core/frame/navigator_ua_data.cc
+++ b/chromium/third_party/blink/renderer/core/frame/navigator_ua_data.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/core/frame/navigator_ua_data.h"
+#include "base/single_thread_task_runner.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_ua_data_values.h"
#include "third_party/blink/renderer/core/page/page.h"
@@ -18,13 +19,22 @@ NavigatorUAData::NavigatorUAData(ExecutionContext* context)
empty_brand_set_.push_back(dict);
}
-void NavigatorUAData::AddBrand(const String& brand, const String& version) {
+void NavigatorUAData::AddBrandVersion(const String& brand,
+ const String& version) {
NavigatorUABrandVersion* dict = NavigatorUABrandVersion::Create();
dict->setBrand(brand);
dict->setVersion(version);
brand_set_.push_back(dict);
}
+void NavigatorUAData::SetBrandVersionList(
+ const UserAgentBrandList& brand_version_list) {
+ for (const auto& brand_version : brand_version_list) {
+ AddBrandVersion(String::FromUTF8(brand_version.brand),
+ String::FromUTF8(brand_version.major_version));
+ }
+}
+
void NavigatorUAData::SetMobile(bool mobile) {
is_mobile_ = mobile;
}
@@ -53,7 +63,7 @@ bool NavigatorUAData::mobile() const {
return false;
}
-const HeapVector<Member<NavigatorUABrandVersion>>& NavigatorUAData::uaList()
+const HeapVector<Member<NavigatorUABrandVersion>>& NavigatorUAData::brands()
const {
if (GetExecutionContext()) {
return brand_set_;
@@ -66,6 +76,8 @@ ScriptPromise NavigatorUAData::getHighEntropyValues(
Vector<String>& hints) const {
auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
ScriptPromise promise = resolver->Promise();
+ auto* executionContext =
+ ExecutionContext::From(script_state); // GetExecutionContext();
UADataValues* values = MakeGarbageCollected<UADataValues>();
for (const String& hint : hints) {
if (hint == "platform") {
@@ -80,7 +92,15 @@ ScriptPromise NavigatorUAData::getHighEntropyValues(
values->setUaFullVersion(ua_full_version_);
}
}
- resolver->Resolve(values);
+
+ DCHECK(executionContext);
+ executionContext->GetTaskRunner(TaskType::kPermission)
+ ->PostTask(
+ FROM_HERE,
+ WTF::Bind([](ScriptPromiseResolver* resolver,
+ UADataValues* values) { resolver->Resolve(values); },
+ WrapPersistent(resolver), WrapPersistent(values)));
+
return promise;
}
diff --git a/chromium/third_party/blink/renderer/core/frame/navigator_ua_data.h b/chromium/third_party/blink/renderer/core/frame/navigator_ua_data.h
index 49e69793312..e14afb7d942 100644
--- a/chromium/third_party/blink/renderer/core/frame/navigator_ua_data.h
+++ b/chromium/third_party/blink/renderer/core/frame/navigator_ua_data.h
@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_NAVIGATOR_UA_DATA_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_NAVIGATOR_UA_DATA_H_
+#include "third_party/blink/public/common/user_agent/user_agent_metadata.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_navigator_ua_brand_version.h"
#include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.h"
@@ -13,6 +14,7 @@
namespace blink {
+class NavigatorUABrandVersion;
class ScriptState;
class NavigatorUAData : public ScriptWrappable, ExecutionContextClient {
@@ -26,7 +28,7 @@ class NavigatorUAData : public ScriptWrappable, ExecutionContextClient {
explicit NavigatorUAData(ExecutionContext* context);
- void AddBrand(const String& brand, const String& version);
+ void SetBrandVersionList(const UserAgentBrandList& brand_version_list);
void SetMobile(bool mobile);
void SetPlatform(const String& brand, const String& version);
void SetArchitecture(const String& architecture);
@@ -34,7 +36,7 @@ class NavigatorUAData : public ScriptWrappable, ExecutionContextClient {
void SetUAFullVersion(const String& uaFullVersion);
// IDL implementation
- const HeapVector<Member<NavigatorUABrandVersion>>& uaList() const;
+ const HeapVector<Member<NavigatorUABrandVersion>>& brands() const;
bool mobile() const;
ScriptPromise getHighEntropyValues(ScriptState*, Vector<String>&) const;
@@ -49,6 +51,8 @@ class NavigatorUAData : public ScriptWrappable, ExecutionContextClient {
String architecture_;
String model_;
String ua_full_version_;
+
+ void AddBrandVersion(const String& brand, const String& version);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/frame/navigator_ua_data.idl b/chromium/third_party/blink/renderer/core/frame/navigator_ua_data.idl
index 5e0e6a10f20..17d29118034 100644
--- a/chromium/third_party/blink/renderer/core/frame/navigator_ua_data.idl
+++ b/chromium/third_party/blink/renderer/core/frame/navigator_ua_data.idl
@@ -8,7 +8,7 @@
RuntimeEnabled=UserAgentClientHint,
Exposed=(Window,Worker)
] interface NavigatorUAData {
- readonly attribute FrozenArray<NavigatorUABrandVersion> uaList;
+ readonly attribute FrozenArray<NavigatorUABrandVersion> brands;
readonly attribute boolean mobile;
[CallWith=ScriptState] Promise<UADataValues> getHighEntropyValues(sequence<DOMString> hints);
};
diff --git a/chromium/third_party/blink/renderer/core/frame/overlay_interstitial_ad_detector.cc b/chromium/third_party/blink/renderer/core/frame/overlay_interstitial_ad_detector.cc
index 3c699046130..9d343f2fded 100644
--- a/chromium/third_party/blink/renderer/core/frame/overlay_interstitial_ad_detector.cc
+++ b/chromium/third_party/blink/renderer/core/frame/overlay_interstitial_ad_detector.cc
@@ -4,12 +4,14 @@
#include "third_party/blink/renderer/core/frame/overlay_interstitial_ad_detector.h"
+#include "third_party/blink/renderer/core/dom/dom_node_ids.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/html/html_frame_owner_element.h"
#include "third_party/blink/renderer/core/html/html_image_element.h"
#include "third_party/blink/renderer/core/layout/layout_object.h"
#include "third_party/blink/renderer/core/layout/layout_object_inlines.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
+#include "third_party/blink/renderer/core/paint/first_meaningful_paint_detector.h"
#include "third_party/blink/renderer/core/scroll/scrollable_area.h"
namespace blink {
@@ -17,6 +19,7 @@ namespace blink {
namespace {
constexpr base::TimeDelta kFireInterval = base::TimeDelta::FromSeconds(1);
+constexpr double kLargeAdSizeToViewportSizeThreshold = 0.1;
bool IsIframeAd(Element* element) {
HTMLFrameOwnerElement* frame_owner_element =
@@ -69,7 +72,7 @@ bool IsImmobileAndCanOverlapWithOtherContent(Element* element) {
return false;
}
-bool IsInterstitialAd(Element* element) {
+bool IsOverlayAdCandidate(Element* element) {
return (IsIframeAd(element) || IsImageAd(element)) &&
IsImmobileAndCanOverlapWithOtherContent(element);
}
@@ -86,24 +89,106 @@ void OverlayInterstitialAdDetector::MaybeFireDetection(LocalFrame* main_frame) {
DCHECK(main_frame->ContentLayoutObject());
base::Time current_time = base::Time::Now();
- if (!last_detection_time_.has_value() ||
- current_time - last_detection_time_.value() >= kFireInterval) {
- IntSize main_frame_size =
- main_frame->View()->GetScrollableArea()->VisibleContentRect().Size();
+
+ if (!started_detection_ ||
+ current_time - last_detection_time_ >= kFireInterval) {
+ IntSize main_frame_size = main_frame->GetMainFrameViewportSize();
+
+ if (started_detection_ &&
+ main_frame_size != last_detection_main_frame_size_) {
+ // Reset the candidate when the the viewport size has changed. Changing
+ // the viewport size could influence the layout and may trick the detector
+ // into believing that an element appeared and was dismissed, but what
+ // could have happened is that the element no longer covers the center,
+ // but still exists (e.g. a sticky ad at the top).
+ candidate_id_ = kInvalidDOMNodeId;
+ }
+
HitTestLocation location(DoublePoint(main_frame_size.Width() / 2.0,
main_frame_size.Height() / 2.0));
HitTestResult result;
main_frame->ContentLayoutObject()->HitTestNoLifecycleUpdate(location,
result);
+ started_detection_ = true;
+
+ last_detection_time_ = current_time;
+ last_detection_main_frame_size_ = main_frame_size;
+
Element* element = result.InnerElement();
+ if (!element)
+ return;
+
+ DOMNodeId element_id = DOMNodeIds::IdForNode(element);
+
+ bool is_new_element = (element_id != candidate_id_);
+
+ if (is_new_element && candidate_id_ != kInvalidDOMNodeId) {
+ // If the main frame scrolling offset hasn't changed since the candidate's
+ // appearance, we consider it to be a overlay interstitial; otherwise, we
+ // skip that candidate because it could be a parallax/scroller ad.
+ if (main_frame->GetMainFrameScrollOffset().Y() ==
+ candidate_start_main_frame_scroll_offset_) {
+ OnPopupAdDetected(main_frame);
+ return;
+ }
+ last_unqualified_element_id_ = candidate_id_;
+ candidate_id_ = kInvalidDOMNodeId;
+ }
- if (element && IsInterstitialAd(element)) {
- UseCounter::Count(main_frame->GetDocument(),
- WebFeature::kOverlayInterstitialAd);
- done_detection_ = true;
+ if (!is_new_element)
+ return;
+
+ if (element_id == last_unqualified_element_id_)
+ return;
+
+ if (!element->GetLayoutObject())
+ return;
+
+ // Skip considering the overlay for a pop-up candidate if we haven't seen or
+ // have just seen the first meaningful paint. If we have just seen the first
+ // meaningful paint, however, we would consider future overlays for pop-up
+ // candidates.
+ if (!main_content_has_loaded_) {
+ if (FirstMeaningfulPaintDetector::From(*(main_frame->GetDocument()))
+ .SeenFirstMeaningfulPaint()) {
+ main_content_has_loaded_ = true;
+ }
+ last_unqualified_element_id_ = element_id;
+ return;
+ }
+
+ IntRect overlay_rect =
+ element->GetLayoutObject()->AbsoluteBoundingBoxRect();
+
+ bool is_large =
+ !overlay_rect.IsEmpty() &&
+ (overlay_rect.Size().Area() >
+ main_frame_size.Area() * kLargeAdSizeToViewportSizeThreshold);
+
+ bool has_gesture = LocalFrame::HasTransientUserActivation(main_frame);
+
+ if (!has_gesture && is_large && IsOverlayAdCandidate(element)) {
+ // If main page is not scrollable, immediately determinine the overlay
+ // to be a popup. There's is no need to check any state at the dismissal
+ // time.
+ if (!main_frame->GetDocument()
+ ->GetLayoutView()
+ ->HasScrollableOverflowY()) {
+ OnPopupAdDetected(main_frame);
+ return;
+ }
+ candidate_id_ = element_id;
+ candidate_start_main_frame_scroll_offset_ =
+ main_frame->GetMainFrameScrollOffset().Y();
+ } else {
+ last_unqualified_element_id_ = element_id;
}
- last_detection_time_ = current_time;
}
}
+void OverlayInterstitialAdDetector::OnPopupAdDetected(LocalFrame* main_frame) {
+ UseCounter::Count(main_frame->GetDocument(), WebFeature::kOverlayPopupAd);
+ done_detection_ = true;
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/frame/overlay_interstitial_ad_detector.h b/chromium/third_party/blink/renderer/core/frame/overlay_interstitial_ad_detector.h
index eb81875e614..e3a2bb379a2 100644
--- a/chromium/third_party/blink/renderer/core/frame/overlay_interstitial_ad_detector.h
+++ b/chromium/third_party/blink/renderer/core/frame/overlay_interstitial_ad_detector.h
@@ -5,23 +5,79 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_OVERLAY_INTERSTITIAL_AD_DETECTOR_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_OVERLAY_INTERSTITIAL_AD_DETECTOR_H_
-#include "base/optional.h"
+#include "base/macros.h"
#include "base/time/time.h"
#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/platform/geometry/int_size.h"
+#include "third_party/blink/renderer/platform/graphics/dom_node_id.h"
namespace blink {
class LocalFrame;
+// Detects overlay interstitials and record a use counter when an instance is
+// found. The current scope is to consider only pop-ups, which appear after
+// content on the page begins to load.
+//
+// Better Ads Standards definition:
+// https://www.betterads.org/desktop-pop-up-ad/
+// https://www.betterads.org/mobile-pop-up-ad/
+//
+// Heuristic:
+// We do hit testing at the center of the browser viewport at regular intervals.
+// The top element is an interstitial pop-up candidate if the following
+// conditions are met:
+// 1) It's immobile to scrolling (e.g. position:fixed).
+// 2) The size is large.
+// 3) It's created without user gesture.
+// 4) It's created after the main content has loaded.
+//
+// The candidate will be actually counted as an overlay pop-up instance after we
+// have checked some status at its dismissal time. On dismissal, if the main
+// frame scrolling offset hasn't changed since the candidate's appearance, we
+// count it as an overlay pop-up; otherwise, we skip that candidate because it
+// could be a parallax/scroller ad.
+//
+// We could potentially miss some true positive cases: the user could click at
+// an empty space which activates the user gesture, and coincidentally the
+// pop-up automatically shows up; the user could make some scrolling
+// before closing the pop-up; etc. However, we accept the trade-off exchanging a
+// lower rate of false positive for an increase in the rate of false negatives.
class CORE_EXPORT OverlayInterstitialAdDetector {
public:
OverlayInterstitialAdDetector() = default;
~OverlayInterstitialAdDetector() = default;
void MaybeFireDetection(LocalFrame* main_frame);
+ void OnPopupAdDetected(LocalFrame* main_frame);
private:
- base::Optional<base::Time> last_detection_time_;
+ bool started_detection_ = false;
+ bool main_content_has_loaded_ = false;
+
+ // The following members are valid only when |started_detection_| is true.
+ base::Time last_detection_time_;
+ IntSize last_detection_main_frame_size_;
+
+ DOMNodeId candidate_id_;
+
+ // The following members are valid only when |candidate_| is not nullptr.
+ int candidate_start_main_frame_scroll_offset_ = 0;
+
+ // The node id of the last element that was detected as unqualified to be an
+ // overlay pop-up. We compare any potential candidate with the last
+ // unqualified element and skip it if they are equal.
+ //
+ // It allows us to exclude some false positive cases. e.g. an
+ // overlay was excluded from the initial consideration because it was created
+ // with a gesture. After 5 seconds the gesture would be gone, but we still
+ // want to exclude it as it was originally created with a gesture.
+ //
+ // Another advantage is this saves some computation cost. e.g. if an ad was
+ // unqualified because it didn't have a viewport constraint position, then we
+ // can skip it on its next occurrence without computing the style again.
+ DOMNodeId last_unqualified_element_id_;
+
bool done_detection_ = false;
DISALLOW_COPY_AND_ASSIGN(OverlayInterstitialAdDetector);
diff --git a/chromium/third_party/blink/renderer/core/frame/pausable_script_executor.cc b/chromium/third_party/blink/renderer/core/frame/pausable_script_executor.cc
index a95f9754017..8a5f658b7ea 100644
--- a/chromium/third_party/blink/renderer/core/frame/pausable_script_executor.cc
+++ b/chromium/third_party/blink/renderer/core/frame/pausable_script_executor.cc
@@ -16,6 +16,7 @@
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
#include "third_party/blink/renderer/bindings/core/v8/window_proxy.h"
#include "third_party/blink/renderer/core/dom/document.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/platform/bindings/trace_wrapper_v8_reference.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
@@ -115,7 +116,7 @@ Vector<v8::Local<v8::Value>> V8FunctionExecutor::Execute(LocalFrame* frame) {
{
if (V8ScriptRunner::CallFunction(function_.NewLocal(isolate),
- frame->GetDocument()->ToExecutionContext(),
+ frame->DomWindow(),
receiver_.NewLocal(isolate), args.size(),
args.data(), ToIsolate(frame))
.ToLocal(&single_result))
@@ -187,7 +188,7 @@ PausableScriptExecutor::PausableScriptExecutor(
ScriptState* script_state,
WebScriptExecutionCallback* callback,
Executor* executor)
- : ExecutionContextLifecycleObserver(frame->GetDocument()),
+ : ExecutionContextLifecycleObserver(frame->DomWindow()),
script_state_(script_state),
callback_(callback),
blocking_option_(kNonBlocking),
@@ -216,7 +217,7 @@ void PausableScriptExecutor::RunAsync(BlockingOption blocking) {
DCHECK(context);
blocking_option_ = blocking;
if (blocking_option_ == kOnloadBlocking)
- Document::From(GetExecutionContext())->IncrementLoadEventDelayCount();
+ To<LocalDOMWindow>(context)->document()->IncrementLoadEventDelayCount();
task_handle_ = PostCancellableTask(
*context->GetTaskRunner(TaskType::kJavascriptTimer), FROM_HERE,
@@ -230,9 +231,9 @@ void PausableScriptExecutor::ExecuteAndDestroySelf() {
if (callback_)
callback_->WillExecute();
+ auto* window = To<LocalDOMWindow>(GetExecutionContext());
ScriptState::Scope script_scope(script_state_);
- Vector<v8::Local<v8::Value>> results =
- executor_->Execute(Document::From(GetExecutionContext())->GetFrame());
+ Vector<v8::Local<v8::Value>> results = executor_->Execute(window->GetFrame());
// The script may have removed the frame, in which case contextDestroyed()
// will have handled the disposal/callback.
@@ -240,7 +241,7 @@ void PausableScriptExecutor::ExecuteAndDestroySelf() {
return;
if (blocking_option_ == kOnloadBlocking)
- Document::From(GetExecutionContext())->DecrementLoadEventDelayCount();
+ window->document()->DecrementLoadEventDelayCount();
if (callback_)
callback_->Completed(results);
diff --git a/chromium/third_party/blink/renderer/core/frame/performance_monitor.cc b/chromium/third_party/blink/renderer/core/frame/performance_monitor.cc
index 26ae7e33046..14e9d641b5e 100644
--- a/chromium/third_party/blink/renderer/core/frame/performance_monitor.cc
+++ b/chromium/third_party/blink/renderer/core/frame/performance_monitor.cc
@@ -14,6 +14,7 @@
#include "third_party/blink/renderer/core/dom/events/event_listener.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/frame/frame.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/html/parser/html_document_parser.h"
#include "third_party/blink/renderer/core/probe/core_probes.h"
@@ -52,10 +53,10 @@ void PerformanceMonitor::ReportGenericViolation(
// static
PerformanceMonitor* PerformanceMonitor::Monitor(
const ExecutionContext* context) {
- const auto* document = Document::DynamicFrom(context);
- if (!document)
+ const auto* window = DynamicTo<LocalDOMWindow>(context);
+ if (!window)
return nullptr;
- LocalFrame* frame = document->GetFrame();
+ LocalFrame* frame = window->GetFrame();
if (!frame)
return nullptr;
return frame->GetPerformanceMonitor();
@@ -147,12 +148,12 @@ void PerformanceMonitor::DidExecuteScript() {
}
void PerformanceMonitor::UpdateTaskAttribution(ExecutionContext* context) {
- // If |context| is not a document, unable to attribute a frame context.
- auto* document = Document::DynamicFrom(context);
- if (!document)
+ // If |context| is not a window, unable to attribute a frame context.
+ auto* window = DynamicTo<LocalDOMWindow>(context);
+ if (!window)
return;
- UpdateTaskShouldBeReported(document->GetFrame());
+ UpdateTaskShouldBeReported(window->GetFrame());
if (!task_execution_context_)
task_execution_context_ = context;
else if (task_execution_context_ != context)
@@ -263,7 +264,7 @@ void PerformanceMonitor::DocumentWriteFetchScript(Document* document) {
if (!enabled_)
return;
String text = "Parser was blocked due to document.write(<script>)";
- InnerReportGenericViolation(document->ToExecutionContext(), kBlockedParser,
+ InnerReportGenericViolation(document->GetExecutionContext(), kBlockedParser,
text, base::TimeDelta(), nullptr);
}
diff --git a/chromium/third_party/blink/renderer/core/frame/performance_monitor_test.cc b/chromium/third_party/blink/renderer/core/frame/performance_monitor_test.cc
index 349beab1d42..d0573ee357c 100644
--- a/chromium/third_party/blink/renderer/core/frame/performance_monitor_test.cc
+++ b/chromium/third_party/blink/renderer/core/frame/performance_monitor_test.cc
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/core/frame/performance_monitor.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/location.h"
#include "third_party/blink/renderer/core/probe/core_probes.h"
@@ -25,13 +26,13 @@ class PerformanceMonitorTest : public testing::Test {
return page_holder_->GetDocument().GetFrame();
}
ExecutionContext* GetExecutionContext() const {
- return page_holder_->GetDocument().ToExecutionContext();
+ return page_holder_->GetFrame().DomWindow();
}
LocalFrame* AnotherFrame() const {
return another_page_holder_->GetDocument().GetFrame();
}
ExecutionContext* AnotherExecutionContext() const {
- return another_page_holder_->GetDocument().ToExecutionContext();
+ return another_page_holder_->GetFrame().DomWindow();
}
void WillExecuteScript(ExecutionContext* execution_context) {
@@ -91,7 +92,7 @@ String PerformanceMonitorTest::FrameContextURL() {
// This is reported only if there is a single frameContext URL.
if (monitor_->task_has_multiple_contexts_)
return g_empty_string;
- return Document::From(monitor_->task_execution_context_.Get())
+ return To<LocalDOMWindow>(monitor_->task_execution_context_.Get())
->location()
->toString();
}
diff --git a/chromium/third_party/blink/renderer/core/frame/platform_event_controller.cc b/chromium/third_party/blink/renderer/core/frame/platform_event_controller.cc
index 18273936e12..33f9529c925 100644
--- a/chromium/third_party/blink/renderer/core/frame/platform_event_controller.cc
+++ b/chromium/third_party/blink/renderer/core/frame/platform_event_controller.cc
@@ -4,16 +4,16 @@
#include "third_party/blink/renderer/core/frame/platform_event_controller.h"
-#include "third_party/blink/renderer/core/dom/document.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/page/page.h"
namespace blink {
-PlatformEventController::PlatformEventController(Document* document)
- : PageVisibilityObserver(document ? document->GetPage() : nullptr),
+PlatformEventController::PlatformEventController(LocalDOMWindow& window)
+ : PageVisibilityObserver(window.GetFrame()->GetPage()),
has_event_listener_(false),
is_active_(false),
- document_(document) {}
+ window_(window) {}
PlatformEventController::~PlatformEventController() = default;
@@ -23,12 +23,12 @@ void PlatformEventController::UpdateCallback() {
}
void PlatformEventController::StartUpdating() {
- if (is_active_ || !document_)
+ if (is_active_ || !window_)
return;
if (HasLastData() && !update_callback_handle_.IsActive()) {
update_callback_handle_ = PostCancellableTask(
- *document_->GetTaskRunner(TaskType::kInternalDefault), FROM_HERE,
+ *window_->GetTaskRunner(TaskType::kInternalDefault), FROM_HERE,
WTF::Bind(&PlatformEventController::UpdateCallback,
WrapWeakPersistent(this)));
}
@@ -57,7 +57,7 @@ void PlatformEventController::PageVisibilityChanged() {
}
void PlatformEventController::Trace(Visitor* visitor) {
- visitor->Trace(document_);
+ visitor->Trace(window_);
PageVisibilityObserver::Trace(visitor);
}
diff --git a/chromium/third_party/blink/renderer/core/frame/platform_event_controller.h b/chromium/third_party/blink/renderer/core/frame/platform_event_controller.h
index 078167cf7ce..d52c3c5f487 100644
--- a/chromium/third_party/blink/renderer/core/frame/platform_event_controller.h
+++ b/chromium/third_party/blink/renderer/core/frame/platform_event_controller.h
@@ -14,7 +14,7 @@
namespace blink {
-class Document;
+class LocalDOMWindow;
// Base controller class for registering controllers with a dispatcher.
// It watches page visibility and calls stopUpdating when page is not visible.
@@ -29,10 +29,10 @@ class CORE_EXPORT PlatformEventController : public PageVisibilityObserver {
virtual void DidUpdateData() = 0;
void Trace(Visitor*) override;
- Document* GetDocument() const { return document_; }
+ LocalDOMWindow& GetWindow() const { return *window_; }
protected:
- explicit PlatformEventController(Document*);
+ explicit PlatformEventController(LocalDOMWindow&);
virtual ~PlatformEventController();
virtual void RegisterWithDispatcher() = 0;
@@ -51,7 +51,7 @@ class CORE_EXPORT PlatformEventController : public PageVisibilityObserver {
void UpdateCallback();
bool is_active_;
- Member<Document> document_;
+ Member<LocalDOMWindow> window_;
TaskHandle update_callback_handle_;
};
diff --git a/chromium/third_party/blink/renderer/core/frame/remote_frame.cc b/chromium/third_party/blink/renderer/core/frame/remote_frame.cc
index 04c16e3882d..3c80fea603e 100644
--- a/chromium/third_party/blink/renderer/core/frame/remote_frame.cc
+++ b/chromium/third_party/blink/renderer/core/frame/remote_frame.cc
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/core/frame/remote_frame.h"
#include "cc/layers/surface_layer.h"
+#include "services/network/public/mojom/web_sandbox_flags.mojom-blink.h"
#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
#include "third_party/blink/public/mojom/frame/frame_owner_properties.mojom-blink.h"
#include "third_party/blink/public/mojom/frame/intrinsic_sizing_info.mojom-blink.h"
@@ -16,6 +17,7 @@
#include "third_party/blink/renderer/bindings/core/v8/window_proxy.h"
#include "third_party/blink/renderer/bindings/core/v8/window_proxy_manager.h"
#include "third_party/blink/renderer/core/frame/csp/content_security_policy.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/local_frame_client.h"
#include "third_party/blink/renderer/core/frame/remote_dom_window.h"
@@ -39,6 +41,7 @@
#include "third_party/blink/renderer/core/timing/dom_window_performance.h"
#include "third_party/blink/renderer/platform/graphics/graphics_layer.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/loader/fetch/fetch_client_settings_object.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher_properties.h"
@@ -49,6 +52,16 @@
namespace blink {
namespace {
+
+// Maintain a global (statically-allocated) hash map indexed by the the result
+// of hashing the |frame_token| passed on creation of a RemoteFrame object.
+typedef HeapHashMap<uint64_t, WeakMember<RemoteFrame>> RemoteFramesByTokenMap;
+static RemoteFramesByTokenMap& GetRemoteFramesMap() {
+ DEFINE_STATIC_LOCAL(Persistent<RemoteFramesByTokenMap>, map,
+ (MakeGarbageCollected<RemoteFramesByTokenMap>()));
+ return *map;
+}
+
FloatRect DeNormalizeRect(const gfx::RectF& normalized, const IntRect& base) {
FloatRect result(normalized);
result.Scale(base.Width(), base.Height());
@@ -58,18 +71,32 @@ FloatRect DeNormalizeRect(const gfx::RectF& normalized, const IntRect& base) {
} // namespace
+// static
+RemoteFrame* RemoteFrame::FromFrameToken(
+ const base::UnguessableToken& frame_token) {
+ RemoteFramesByTokenMap& remote_frames_map = GetRemoteFramesMap();
+ auto it = remote_frames_map.find(base::UnguessableTokenHash()(frame_token));
+ return it == remote_frames_map.end() ? nullptr : it->value.Get();
+}
+
RemoteFrame::RemoteFrame(
RemoteFrameClient* client,
Page& page,
FrameOwner* owner,
+ const base::UnguessableToken& frame_token,
WindowAgentFactory* inheriting_agent_factory,
InterfaceRegistry* interface_registry,
AssociatedInterfaceProvider* associated_interface_provider)
: Frame(client,
page,
owner,
+ frame_token,
MakeGarbageCollected<RemoteWindowProxyManager>(*this),
inheriting_agent_factory) {
+ auto frame_tracking_result = GetRemoteFramesMap().insert(
+ base::UnguessableTokenHash()(frame_token), this);
+ CHECK(frame_tracking_result.stored_value) << "Inserting a duplicate item.";
+
dom_window_ = MakeGarbageCollected<RemoteDOMWindow>(*this);
interface_registry->AddAssociatedInterface(WTF::BindRepeating(
@@ -130,10 +157,7 @@ void RemoteFrame::Navigate(FrameLoadRequest& frame_request,
: nullptr;
MixedContentChecker::UpgradeInsecureRequest(
frame_request.GetResourceRequest(), fetch_client_settings_object,
- frame_request.OriginDocument()
- ? frame_request.OriginDocument()->ToExecutionContext()
- : nullptr,
- frame_request.GetFrameType(),
+ frame ? frame->DomWindow() : nullptr, frame_request.GetFrameType(),
frame ? frame->GetContentSettingsClient() : nullptr);
// Navigations in portal contexts do not create back/forward entries.
@@ -142,6 +166,9 @@ void RemoteFrame::Navigate(FrameLoadRequest& frame_request,
frame_load_type = WebFrameLoadType::kReplaceCurrentItem;
}
+ WebLocalFrame* initiator_frame =
+ frame ? frame->Client()->GetWebFrame() : nullptr;
+
bool is_opener_navigation = false;
bool initiator_frame_has_download_sandbox_flag = false;
bool initiator_frame_is_ad = false;
@@ -151,19 +178,21 @@ void RemoteFrame::Navigate(FrameLoadRequest& frame_request,
initiator_frame_has_download_sandbox_flag =
frame->GetSecurityContext() &&
frame->GetSecurityContext()->IsSandboxed(
- mojom::blink::WebSandboxFlags::kDownloads);
+ network::mojom::blink::WebSandboxFlags::kDownloads);
initiator_frame_is_ad = frame->IsAdSubframe();
if (frame_request.ClientRedirectReason() != ClientNavigationReason::kNone) {
probe::FrameRequestedNavigation(frame, this, url,
- frame_request.ClientRedirectReason());
+ frame_request.ClientRedirectReason(),
+ kNavigationPolicyCurrentTab);
}
}
- Client()->Navigate(frame_request.GetResourceRequest(),
+ Client()->Navigate(frame_request.GetResourceRequest(), initiator_frame,
frame_load_type == WebFrameLoadType::kReplaceCurrentItem,
is_opener_navigation,
initiator_frame_has_download_sandbox_flag,
- initiator_frame_is_ad, frame_request.GetBlobURLToken());
+ initiator_frame_is_ad, frame_request.GetBlobURLToken(),
+ frame_request.Impression());
}
void RemoteFrame::DetachImpl(FrameDetachType type) {
@@ -323,7 +352,7 @@ void RemoteFrame::SetReplicatedFeaturePolicyHeaderAndOpenerPolicies(
}
void RemoteFrame::SetReplicatedSandboxFlags(
- mojom::blink::WebSandboxFlags flags) {
+ network::mojom::blink::WebSandboxFlags flags) {
security_context_.ResetAndEnforceSandboxFlags(flags);
}
@@ -564,8 +593,8 @@ void RemoteFrame::IntrinsicSizingInfoOfChildChanged(
// ensure that sandbox flags and feature policy are inherited properly if this
// proxy ever parents a local frame.
void RemoteFrame::DidSetFramePolicyHeaders(
- mojom::blink::WebSandboxFlags sandbox_flags,
- const Vector<ParsedFeaturePolicyDeclaration>& parsed_feature_policy) {
+ network::mojom::blink::WebSandboxFlags sandbox_flags,
+ const WTF::Vector<ParsedFeaturePolicyDeclaration>& parsed_feature_policy) {
SetReplicatedSandboxFlags(sandbox_flags);
// Convert from WTF::Vector<ParsedFeaturePolicyDeclaration>
// to std::vector<ParsedFeaturePolicyDeclaration>, since ParsedFeaturePolicy
@@ -620,7 +649,7 @@ bool RemoteFrame::IsIgnoredForHitTest() const {
if (!owner || !owner->GetLayoutObject())
return false;
- return owner->OwnerType() == FrameOwnerElementType::kPortal ||
+ return owner->OwnerType() == mojom::blink::FrameOwnerElementType::kPortal ||
!visible_to_hit_testing_;
}
diff --git a/chromium/third_party/blink/renderer/core/frame/remote_frame.h b/chromium/third_party/blink/renderer/core/frame/remote_frame.h
index 15767ce1b4b..dc29695ff00 100644
--- a/chromium/third_party/blink/renderer/core/frame/remote_frame.h
+++ b/chromium/third_party/blink/renderer/core/frame/remote_frame.h
@@ -7,6 +7,7 @@
#include "mojo/public/cpp/bindings/associated_receiver.h"
#include "mojo/public/cpp/bindings/associated_remote.h"
+#include "services/network/public/mojom/web_sandbox_flags.mojom-blink-forward.h"
#include "third_party/blink/public/mojom/frame/frame.mojom-blink.h"
#include "third_party/blink/public/mojom/frame/frame_owner_properties.mojom-blink-forward.h"
#include "third_party/blink/public/mojom/input/focus_type.mojom-blink-forward.h"
@@ -33,11 +34,15 @@ struct FrameLoadRequest;
class CORE_EXPORT RemoteFrame final : public Frame,
public mojom::blink::RemoteFrame {
public:
+ // Returns the RemoteFrame for the given |frame_token|.
+ static RemoteFrame* FromFrameToken(const base::UnguessableToken& frame_token);
+
// For a description of |inheriting_agent_factory| go see the comment on the
// Frame constructor.
RemoteFrame(RemoteFrameClient*,
Page&,
FrameOwner*,
+ const base::UnguessableToken& frame_token,
WindowAgentFactory* inheriting_agent_factory,
InterfaceRegistry*,
AssociatedInterfaceProvider*);
@@ -89,7 +94,7 @@ class CORE_EXPORT RemoteFrame final : public Frame,
const ParsedFeaturePolicy& parsed_header,
const FeaturePolicy::FeatureState&);
- void SetReplicatedSandboxFlags(mojom::blink::WebSandboxFlags);
+ void SetReplicatedSandboxFlags(network::mojom::blink::WebSandboxFlags);
void SetInsecureRequestPolicy(mojom::blink::InsecureRequestPolicy);
void SetInsecureNavigationsSet(const WebVector<unsigned>&);
@@ -130,7 +135,7 @@ class CORE_EXPORT RemoteFrame final : public Frame,
void IntrinsicSizingInfoOfChildChanged(
mojom::blink::IntrinsicSizingInfoPtr sizing_info) override;
void DidSetFramePolicyHeaders(
- mojom::blink::WebSandboxFlags,
+ network::mojom::blink::WebSandboxFlags,
const WTF::Vector<ParsedFeaturePolicyDeclaration>&) override;
// Updates the snapshotted policy attributes (sandbox flags and feature policy
// container policy) in the frame's FrameOwner. This is used when this frame's
diff --git a/chromium/third_party/blink/renderer/core/frame/remote_frame_client.h b/chromium/third_party/blink/renderer/core/frame/remote_frame_client.h
index e73cc62bcef..056e0d5969f 100644
--- a/chromium/third_party/blink/renderer/core/frame/remote_frame_client.h
+++ b/chromium/third_party/blink/renderer/core/frame/remote_frame_client.h
@@ -5,9 +5,11 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_REMOTE_FRAME_CLIENT_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_REMOTE_FRAME_CLIENT_H_
+#include "base/optional.h"
#include "cc/paint/paint_canvas.h"
#include "third_party/blink/public/mojom/blob/blob_url_store.mojom-blink-forward.h"
#include "third_party/blink/public/platform/viewport_intersection_state.h"
+#include "third_party/blink/public/platform/web_impression.h"
#include "third_party/blink/public/web/web_frame_load_type.h"
#include "third_party/blink/renderer/core/frame/frame_client.h"
#include "third_party/blink/renderer/core/frame/frame_types.h"
@@ -23,17 +25,20 @@ class LocalFrame;
class MessageEvent;
class ResourceRequest;
class SecurityOrigin;
+class WebLocalFrame;
class RemoteFrameClient : public FrameClient {
public:
~RemoteFrameClient() override = default;
virtual void Navigate(const ResourceRequest&,
+ blink::WebLocalFrame* initiator_frame,
bool should_replace_current_entry,
bool is_opener_navigation,
bool initiator_frame_has_download_sandbox_flag,
bool initiator_frame_is_ad,
- mojo::PendingRemote<mojom::blink::BlobURLToken>) = 0;
+ mojo::PendingRemote<mojom::blink::BlobURLToken>,
+ const base::Optional<WebImpression>& impression) = 0;
unsigned BackForwardLength() override = 0;
// Forwards a postMessage for a remote frame.
diff --git a/chromium/third_party/blink/renderer/core/frame/remote_frame_client_impl.cc b/chromium/third_party/blink/renderer/core/frame/remote_frame_client_impl.cc
index ec1271d743a..312b23cd3ab 100644
--- a/chromium/third_party/blink/renderer/core/frame/remote_frame_client_impl.cc
+++ b/chromium/third_party/blink/renderer/core/frame/remote_frame_client_impl.cc
@@ -100,19 +100,22 @@ base::UnguessableToken RemoteFrameClientImpl::GetDevToolsFrameToken() const {
void RemoteFrameClientImpl::Navigate(
const ResourceRequest& request,
+ blink::WebLocalFrame* initiator_frame,
bool should_replace_current_entry,
bool is_opener_navigation,
bool initiator_frame_has_download_sandbox_flag,
bool initiator_frame_is_ad,
- mojo::PendingRemote<mojom::blink::BlobURLToken> blob_url_token) {
+ mojo::PendingRemote<mojom::blink::BlobURLToken> blob_url_token,
+ const base::Optional<WebImpression>& impression) {
bool blocking_downloads_in_sandbox_enabled =
RuntimeEnabledFeatures::BlockingDownloadsInSandboxEnabled();
if (web_frame_->Client()) {
web_frame_->Client()->Navigate(
- WrappedResourceRequest(request), should_replace_current_entry,
- is_opener_navigation, initiator_frame_has_download_sandbox_flag,
+ WrappedResourceRequest(request), initiator_frame,
+ should_replace_current_entry, is_opener_navigation,
+ initiator_frame_has_download_sandbox_flag,
blocking_downloads_in_sandbox_enabled, initiator_frame_is_ad,
- blob_url_token.PassPipe());
+ blob_url_token.PassPipe(), impression);
}
}
diff --git a/chromium/third_party/blink/renderer/core/frame/remote_frame_client_impl.h b/chromium/third_party/blink/renderer/core/frame/remote_frame_client_impl.h
index 382e4f8214b..a0591ce692f 100644
--- a/chromium/third_party/blink/renderer/core/frame/remote_frame_client_impl.h
+++ b/chromium/third_party/blink/renderer/core/frame/remote_frame_client_impl.h
@@ -34,11 +34,13 @@ class RemoteFrameClientImpl final : public RemoteFrameClient {
// RemoteFrameClient overrides:
void Navigate(const ResourceRequest&,
+ blink::WebLocalFrame* initiator_frame,
bool should_replace_current_entry,
bool is_opener_navigation,
bool prevent_sandboxed_download,
bool initiator_frame_is_ad,
- mojo::PendingRemote<mojom::blink::BlobURLToken>) override;
+ mojo::PendingRemote<mojom::blink::BlobURLToken>,
+ const base::Optional<WebImpression>& impression) override;
unsigned BackForwardLength() override;
void ForwardPostMessage(MessageEvent*,
scoped_refptr<const SecurityOrigin> target,
diff --git a/chromium/third_party/blink/renderer/core/frame/remote_frame_owner.cc b/chromium/third_party/blink/renderer/core/frame/remote_frame_owner.cc
index 525f18e1705..4abf53df891 100644
--- a/chromium/third_party/blink/renderer/core/frame/remote_frame_owner.cc
+++ b/chromium/third_party/blink/renderer/core/frame/remote_frame_owner.cc
@@ -4,8 +4,10 @@
#include "third_party/blink/renderer/core/frame/remote_frame_owner.h"
+#include "third_party/blink/public/mojom/frame/intrinsic_sizing_info.mojom-blink.h"
#include "third_party/blink/public/web/web_local_frame_client.h"
#include "third_party/blink/renderer/core/exported/web_remote_frame_impl.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/local_frame_client.h"
#include "third_party/blink/renderer/core/frame/web_frame_widget_base.h"
@@ -18,7 +20,7 @@ namespace blink {
RemoteFrameOwner::RemoteFrameOwner(
const FramePolicy& frame_policy,
const WebFrameOwnerProperties& frame_owner_properties,
- FrameOwnerElementType frame_owner_element_type)
+ mojom::blink::FrameOwnerElementType frame_owner_element_type)
: frame_policy_(frame_policy),
browsing_context_container_name_(
static_cast<String>(frame_owner_properties.name)),
@@ -55,7 +57,7 @@ void RemoteFrameOwner::AddResourceTiming(const ResourceTimingInfo& info) {
mojom::blink::ResourceTimingInfoPtr resource_timing =
Performance::GenerateResourceTiming(
*frame->Tree().Parent()->GetSecurityContext()->GetSecurityOrigin(),
- info, *frame->GetDocument()->ToExecutionContext());
+ info, *frame->DomWindow());
frame->GetLocalFrameHostRemote().ForwardResourceTimingToParent(
std::move(resource_timing));
}
@@ -66,7 +68,7 @@ void RemoteFrameOwner::DispatchLoad() {
}
void RemoteFrameOwner::RenderFallbackContent(Frame* failed_frame) {
- if (frame_owner_element_type_ != FrameOwnerElementType::kObject)
+ if (frame_owner_element_type_ != mojom::blink::FrameOwnerElementType::kObject)
return;
DCHECK(failed_frame->IsLocalFrame());
LocalFrame* local_frame = To<LocalFrame>(failed_frame);
@@ -82,9 +84,14 @@ void RemoteFrameOwner::IntrinsicSizingInfoChanged() {
// By virtue of having been invoked, GetIntrinsicSizingInfo() should always
// succeed here.
DCHECK(result);
+
+ auto sizing_info = mojom::blink::IntrinsicSizingInfo::New(
+ gfx::SizeF(intrinsic_sizing_info.size),
+ gfx::SizeF(intrinsic_sizing_info.aspect_ratio),
+ intrinsic_sizing_info.has_width, intrinsic_sizing_info.has_height);
WebLocalFrameImpl::FromFrame(local_frame)
->FrameWidgetImpl()
- ->IntrinsicSizingInfoChanged(intrinsic_sizing_info);
+ ->IntrinsicSizingInfoChanged(std::move(sizing_info));
}
void RemoteFrameOwner::SetNeedsOcclusionTracking(bool needs_tracking) {
diff --git a/chromium/third_party/blink/renderer/core/frame/remote_frame_owner.h b/chromium/third_party/blink/renderer/core/frame/remote_frame_owner.h
index a75f1badd8f..17605568826 100644
--- a/chromium/third_party/blink/renderer/core/frame/remote_frame_owner.h
+++ b/chromium/third_party/blink/renderer/core/frame/remote_frame_owner.h
@@ -5,8 +5,8 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_REMOTE_FRAME_OWNER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_REMOTE_FRAME_OWNER_H_
-#include "third_party/blink/public/common/frame/frame_owner_element_type.h"
#include "third_party/blink/public/common/frame/frame_policy.h"
+#include "third_party/blink/public/mojom/frame/frame_owner_element_type.mojom-blink.h"
#include "third_party/blink/public/mojom/scroll/scrollbar_mode.mojom-blink.h"
#include "third_party/blink/public/web/web_frame_owner_properties.h"
#include "third_party/blink/renderer/core/core_export.h"
@@ -27,9 +27,10 @@ class CORE_EXPORT RemoteFrameOwner final
USING_GARBAGE_COLLECTED_MIXIN(RemoteFrameOwner);
public:
- RemoteFrameOwner(const FramePolicy&,
- const WebFrameOwnerProperties&,
- FrameOwnerElementType frame_owner_element_type);
+ RemoteFrameOwner(
+ const FramePolicy&,
+ const WebFrameOwnerProperties&,
+ mojom::blink::FrameOwnerElementType frame_owner_element_type);
// FrameOwner overrides:
Frame* ContentFrame() const override { return frame_.Get(); }
@@ -39,7 +40,8 @@ class CORE_EXPORT RemoteFrameOwner final
void AddResourceTiming(const ResourceTimingInfo&) override;
void DispatchLoad() override;
bool CanRenderFallbackContent() const override {
- return frame_owner_element_type_ == FrameOwnerElementType::kObject;
+ return frame_owner_element_type_ ==
+ mojom::blink::FrameOwnerElementType::kObject;
}
void RenderFallbackContent(Frame*) override;
void IntrinsicSizingInfoChanged() override;
@@ -100,7 +102,7 @@ class CORE_EXPORT RemoteFrameOwner final
bool is_display_none_;
bool needs_occlusion_tracking_;
WebString required_csp_;
- const FrameOwnerElementType frame_owner_element_type_;
+ const mojom::blink::FrameOwnerElementType frame_owner_element_type_;
};
template <>
diff --git a/chromium/third_party/blink/renderer/core/frame/remote_frame_view.cc b/chromium/third_party/blink/renderer/core/frame/remote_frame_view.cc
index f6a342c248f..1e58c5d6d81 100644
--- a/chromium/third_party/blink/renderer/core/frame/remote_frame_view.cc
+++ b/chromium/third_party/blink/renderer/core/frame/remote_frame_view.cc
@@ -5,7 +5,7 @@
#include "third_party/blink/renderer/core/frame/remote_frame_view.h"
#include "components/paint_preview/common/paint_preview_tracker.h"
-#include "third_party/blink/public/common/frame/frame_owner_element_type.h"
+#include "third_party/blink/public/mojom/frame/frame_owner_element_type.mojom-blink.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
@@ -36,7 +36,8 @@ LocalFrameView* RemoteFrameView::ParentFrameView() const {
return nullptr;
HTMLFrameOwnerElement* owner = remote_frame_->DeprecatedLocalOwner();
- if (owner && owner->OwnerType() == FrameOwnerElementType::kPortal)
+ if (owner &&
+ owner->OwnerType() == mojom::blink::FrameOwnerElementType::kPortal)
return owner->GetDocument().GetFrame()->View();
// |is_attached_| is only set from AttachToLayout(), which ensures that the
@@ -53,7 +54,8 @@ LocalFrameView* RemoteFrameView::ParentLocalRootFrameView() const {
return nullptr;
HTMLFrameOwnerElement* owner = remote_frame_->DeprecatedLocalOwner();
- if (owner && owner->OwnerType() == FrameOwnerElementType::kPortal)
+ if (owner &&
+ owner->OwnerType() == mojom::blink::FrameOwnerElementType::kPortal)
return owner->GetDocument().GetFrame()->LocalFrameRoot().View();
// |is_attached_| is only set from AttachToLayout(), which ensures that the
diff --git a/chromium/third_party/blink/renderer/core/frame/reporting_context.cc b/chromium/third_party/blink/renderer/core/frame/reporting_context.cc
index fbbc1b1b1a9..0da2f0398e5 100644
--- a/chromium/third_party/blink/renderer/core/frame/reporting_context.cc
+++ b/chromium/third_party/blink/renderer/core/frame/reporting_context.cc
@@ -23,13 +23,39 @@
namespace blink {
+namespace {
+
+// In the spec (https://w3c.github.io/reporting/#report-body) a report body can
+// have anything that can be serialized into a JSON text, but V8ObjectBuilder
+// doesn't allow us to implement that. Hence here we implement just a one-level
+// dictionary, as that is what is needed currently.
+class DictionaryValueReportBody final : public ReportBody {
+ public:
+ explicit DictionaryValueReportBody(mojom::blink::ReportBodyPtr body)
+ : body_(std::move(body)) {}
+
+ void BuildJSONValue(V8ObjectBuilder& builder) const override {
+ DCHECK(body_);
+
+ for (const auto& element : body_->body) {
+ builder.AddString(element->name, element->value);
+ }
+ }
+
+ private:
+ const mojom::blink::ReportBodyPtr body_;
+};
+
+} // namespace
+
// static
const char ReportingContext::kSupplementName[] = "ReportingContext";
ReportingContext::ReportingContext(ExecutionContext& context)
: Supplement<ExecutionContext>(context),
execution_context_(context),
- reporting_service_(&context) {}
+ reporting_service_(&context),
+ receiver_(this, &context) {}
// static
ReportingContext* ReportingContext::From(ExecutionContext* context) {
@@ -42,30 +68,25 @@ ReportingContext* ReportingContext::From(ExecutionContext* context) {
return reporting_context;
}
+void ReportingContext::Bind(
+ mojo::PendingReceiver<mojom::blink::ReportingObserver> receiver) {
+ receiver_.reset();
+ receiver_.Bind(std::move(receiver),
+ execution_context_->GetTaskRunner(TaskType::kMiscPlatformAPI));
+}
+
void ReportingContext::QueueReport(Report* report,
const Vector<String>& endpoints) {
CountReport(report);
- // Buffer the report.
- if (!report_buffer_.Contains(report->type()))
- report_buffer_.insert(report->type(), HeapListHashSet<Member<Report>>());
- report_buffer_.find(report->type())->value.insert(report);
-
- // Only the most recent 100 reports will remain buffered, per report type.
- // https://w3c.github.io/reporting/#notify-observers
- if (report_buffer_.at(report->type()).size() > 100)
- report_buffer_.find(report->type())->value.RemoveFirst();
-
- // Queue the report in all registered observers.
- for (auto observer : observers_)
- observer->QueueReport(report);
+ NotifyInternal(report);
// Send the report via the Reporting API.
for (auto& endpoint : endpoints)
SendToReportingAPI(report, endpoint);
}
-void ReportingContext::RegisterObserver(ReportingObserver* observer) {
+void ReportingContext::RegisterObserver(blink::ReportingObserver* observer) {
UseCounter::Count(execution_context_, WebFeature::kReportingObserver);
observers_.insert(observer);
@@ -80,15 +101,25 @@ void ReportingContext::RegisterObserver(ReportingObserver* observer) {
}
}
-void ReportingContext::UnregisterObserver(ReportingObserver* observer) {
+void ReportingContext::UnregisterObserver(blink::ReportingObserver* observer) {
observers_.erase(observer);
}
+void ReportingContext::Notify(mojom::blink::ReportPtr report) {
+ ReportBody* body = report->body
+ ? MakeGarbageCollected<DictionaryValueReportBody>(
+ std::move(report->body))
+ : nullptr;
+ NotifyInternal(MakeGarbageCollected<Report>(report->type,
+ report->url.GetString(), body));
+}
+
void ReportingContext::Trace(Visitor* visitor) {
visitor->Trace(observers_);
visitor->Trace(report_buffer_);
visitor->Trace(execution_context_);
visitor->Trace(reporting_service_);
+ visitor->Trace(receiver_);
Supplement<ExecutionContext>::Trace(visitor);
}
@@ -119,6 +150,22 @@ ReportingContext::GetReportingService() const {
return reporting_service_;
}
+void ReportingContext::NotifyInternal(Report* report) {
+ // Buffer the report.
+ if (!report_buffer_.Contains(report->type()))
+ report_buffer_.insert(report->type(), HeapListHashSet<Member<Report>>());
+ report_buffer_.find(report->type())->value.insert(report);
+
+ // Only the most recent 100 reports will remain buffered, per report type.
+ // https://w3c.github.io/reporting/#notify-observers
+ if (report_buffer_.at(report->type()).size() > 100)
+ report_buffer_.find(report->type())->value.RemoveFirst();
+
+ // Queue the report in all registered observers.
+ for (auto observer : observers_)
+ observer->QueueReport(report);
+}
+
void ReportingContext::SendToReportingAPI(Report* report,
const String& endpoint) const {
const String& type = report->type();
@@ -131,13 +178,8 @@ void ReportingContext::SendToReportingAPI(Report* report,
const LocationReportBody* location_body =
static_cast<LocationReportBody*>(report->body());
- bool is_null;
- int line_number = location_body->lineNumber(is_null);
- if (is_null)
- line_number = 0;
- int column_number = location_body->columnNumber(is_null);
- if (is_null)
- column_number = 0;
+ int line_number = location_body->lineNumber().value_or(0);
+ int column_number = location_body->columnNumber().value_or(0);
KURL url = KURL(report->url());
if (type == ReportType::kCSPViolation) {
diff --git a/chromium/third_party/blink/renderer/core/frame/reporting_context.h b/chromium/third_party/blink/renderer/core/frame/reporting_context.h
index 67a26a9becd..ec572629ed7 100644
--- a/chromium/third_party/blink/renderer/core/frame/reporting_context.h
+++ b/chromium/third_party/blink/renderer/core/frame/reporting_context.h
@@ -5,9 +5,11 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_REPORTING_CONTEXT_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_REPORTING_CONTEXT_H_
+#include "third_party/blink/public/mojom/frame/reporting_observer.mojom-blink.h"
#include "third_party/blink/public/mojom/reporting/reporting.mojom-blink.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
+#include "third_party/blink/renderer/platform/mojo/heap_mojo_receiver.h"
#include "third_party/blink/renderer/platform/mojo/heap_mojo_remote.h"
#include "third_party/blink/renderer/platform/supplementable.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
@@ -22,6 +24,7 @@ class ReportingObserver;
// a container for all active ReportingObservers on that ExecutionContext.
class CORE_EXPORT ReportingContext final
: public GarbageCollected<ReportingContext>,
+ public mojom::blink::ReportingObserver,
public Supplement<ExecutionContext> {
USING_GARBAGE_COLLECTED_MIXIN(ReportingContext);
@@ -36,12 +39,16 @@ class CORE_EXPORT ReportingContext final
static ReportingContext* From(const ExecutionContext* context) {
return ReportingContext::From(const_cast<ExecutionContext*>(context));
}
+ void Bind(mojo::PendingReceiver<mojom::blink::ReportingObserver> receiver);
// Queues a report for the Reporting API and in all registered observers.
void QueueReport(Report*, const Vector<String>& endpoints = {"default"});
- void RegisterObserver(ReportingObserver*);
- void UnregisterObserver(ReportingObserver*);
+ void RegisterObserver(blink::ReportingObserver*);
+ void UnregisterObserver(blink::ReportingObserver*);
+
+ // mojom::blink::ReportingObserver implementation.
+ void Notify(mojom::blink::ReportPtr report) override;
void Trace(Visitor*) override;
@@ -52,10 +59,11 @@ class CORE_EXPORT ReportingContext final
const HeapMojoRemote<mojom::blink::ReportingServiceProxy>&
GetReportingService() const;
+ void NotifyInternal(Report* report);
// Send |report| via the Reporting API to |endpoint|.
void SendToReportingAPI(Report* report, const String& endpoint) const;
- HeapListHashSet<Member<ReportingObserver>> observers_;
+ HeapListHashSet<Member<blink::ReportingObserver>> observers_;
HeapHashMap<String, HeapListHashSet<Member<Report>>> report_buffer_;
Member<ExecutionContext> execution_context_;
@@ -63,6 +71,8 @@ class CORE_EXPORT ReportingContext final
// const methods.
mutable HeapMojoRemote<mojom::blink::ReportingServiceProxy>
reporting_service_;
+
+ HeapMojoReceiver<mojom::blink::ReportingObserver, ReportingContext> receiver_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/frame/reporting_context_test.cc b/chromium/third_party/blink/renderer/core/frame/reporting_context_test.cc
index 4b7212311bd..7ae687c38cc 100644
--- a/chromium/third_party/blink/renderer/core/frame/reporting_context_test.cc
+++ b/chromium/third_party/blink/renderer/core/frame/reporting_context_test.cc
@@ -7,6 +7,7 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/thread_safe_browser_interface_broker_proxy.h"
#include "third_party/blink/renderer/core/frame/deprecation_report_body.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/report.h"
#include "third_party/blink/renderer/core/testing/page_test_base.h"
#include "third_party/blink/renderer/platform/testing/histogram_tester.h"
@@ -134,7 +135,7 @@ TEST_F(ReportingContextTest, CountQueuedReports) {
// Send the deprecation report to the Reporting API and any
// ReportingObservers.
- ReportingContext::From(dummy_page_holder->GetDocument().ToExecutionContext())
+ ReportingContext::From(dummy_page_holder->GetFrame().DomWindow())
->QueueReport(report);
// tester.ExpectTotalCount("Blink.UseCounter.Features.DeprecationReport", 1);
// The potential violation for an already recorded violation does not count
@@ -143,7 +144,7 @@ TEST_F(ReportingContextTest, CountQueuedReports) {
TEST_F(ReportingContextTest, DeprecationReportContent) {
auto dummy_page_holder = std::make_unique<DummyPageHolder>();
- auto& doc = dummy_page_holder->GetDocument();
+ auto* win = dummy_page_holder->GetFrame().DomWindow();
base::RunLoop run_loop;
MockReportingServiceProxy reporting_service(
*Platform::Current()->GetBrowserInterfaceBroker(),
@@ -151,9 +152,9 @@ TEST_F(ReportingContextTest, DeprecationReportContent) {
auto* body = MakeGarbageCollected<DeprecationReportBody>(
"FeatureId", base::Time::FromJsTime(1000), "Test report");
- auto* report =
- MakeGarbageCollected<Report>("deprecation", doc.Url().GetString(), body);
- ReportingContext::From(doc.ToExecutionContext())->QueueReport(report);
+ auto* report = MakeGarbageCollected<Report>(
+ "deprecation", win->document()->Url().GetString(), body);
+ ReportingContext::From(win)->QueueReport(report);
run_loop.Run();
EXPECT_TRUE(reporting_service.DeprecationReportAnticipatedRemoval());
diff --git a/chromium/third_party/blink/renderer/core/frame/reporting_observer.idl b/chromium/third_party/blink/renderer/core/frame/reporting_observer.idl
index 134e31d61ab..03017d16102 100644
--- a/chromium/third_party/blink/renderer/core/frame/reporting_observer.idl
+++ b/chromium/third_party/blink/renderer/core/frame/reporting_observer.idl
@@ -7,7 +7,8 @@
callback ReportingObserverCallback = void (sequence<Report> reports, ReportingObserver observer);
[
- ActiveScriptWrappable
+ ActiveScriptWrappable,
+ Exposed=(Window,Worker)
] interface ReportingObserver {
[CallWith=ExecutionContext] constructor(ReportingObserverCallback callback, optional ReportingObserverOptions options = {});
void observe();
diff --git a/chromium/third_party/blink/renderer/core/frame/sandbox_flags.cc b/chromium/third_party/blink/renderer/core/frame/sandbox_flags.cc
index 218f0234c33..8479d77988e 100644
--- a/chromium/third_party/blink/renderer/core/frame/sandbox_flags.cc
+++ b/chromium/third_party/blink/renderer/core/frame/sandbox_flags.cc
@@ -26,38 +26,36 @@
#include "third_party/blink/renderer/core/frame/sandbox_flags.h"
-#include "third_party/blink/public/common/frame/sandbox_flags.h"
+#include "services/network/public/cpp/web_sandbox_flags.h"
+#include "services/network/public/mojom/web_sandbox_flags.mojom-blink.h"
#include "third_party/blink/public/mojom/feature_policy/feature_policy.mojom-blink.h"
#include "third_party/blink/renderer/core/feature_policy/feature_policy_parser.h"
-#include "third_party/blink/renderer/core/html/html_iframe_element.h"
-#include "third_party/blink/renderer/core/html/parser/html_parser_idioms.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/text/string_builder.h"
-#include "third_party/blink/renderer/platform/wtf/vector.h"
namespace blink {
const SandboxFlagFeaturePolicyPairs& SandboxFlagsWithFeaturePolicies() {
- DEFINE_STATIC_LOCAL(SandboxFlagFeaturePolicyPairs, array,
- ({{mojom::blink::WebSandboxFlags::kTopNavigation,
- mojom::blink::FeaturePolicyFeature::kTopNavigation},
- {mojom::blink::WebSandboxFlags::kForms,
- mojom::blink::FeaturePolicyFeature::kFormSubmission},
- {mojom::blink::WebSandboxFlags::kScripts,
- mojom::blink::FeaturePolicyFeature::kScript},
- {mojom::blink::WebSandboxFlags::kPopups,
- mojom::blink::FeaturePolicyFeature::kPopups},
- {mojom::blink::WebSandboxFlags::kPointerLock,
- mojom::blink::FeaturePolicyFeature::kPointerLock},
- {mojom::blink::WebSandboxFlags::kModals,
- mojom::blink::FeaturePolicyFeature::kModals},
- {mojom::blink::WebSandboxFlags::kOrientationLock,
- mojom::blink::FeaturePolicyFeature::kOrientationLock},
- {mojom::blink::WebSandboxFlags::kPresentationController,
- mojom::blink::FeaturePolicyFeature::kPresentation},
- {mojom::blink::WebSandboxFlags::kDownloads,
- mojom::blink::FeaturePolicyFeature::kDownloads}}));
+ DEFINE_STATIC_LOCAL(
+ SandboxFlagFeaturePolicyPairs, array,
+ ({
+ {network::mojom::blink::WebSandboxFlags::kTopNavigation,
+ mojom::blink::FeaturePolicyFeature::kTopNavigation},
+ {network::mojom::blink::WebSandboxFlags::kForms,
+ mojom::blink::FeaturePolicyFeature::kFormSubmission},
+ {network::mojom::blink::WebSandboxFlags::kScripts,
+ mojom::blink::FeaturePolicyFeature::kScript},
+ {network::mojom::blink::WebSandboxFlags::kPopups,
+ mojom::blink::FeaturePolicyFeature::kPopups},
+ {network::mojom::blink::WebSandboxFlags::kPointerLock,
+ mojom::blink::FeaturePolicyFeature::kPointerLock},
+ {network::mojom::blink::WebSandboxFlags::kModals,
+ mojom::blink::FeaturePolicyFeature::kModals},
+ {network::mojom::blink::WebSandboxFlags::kOrientationLock,
+ mojom::blink::FeaturePolicyFeature::kOrientationLock},
+ {network::mojom::blink::WebSandboxFlags::kPresentationController,
+ mojom::blink::FeaturePolicyFeature::kPresentation},
+ {network::mojom::blink::WebSandboxFlags::kDownloads,
+ mojom::blink::FeaturePolicyFeature::kDownloads},
+ }));
return array;
}
@@ -65,95 +63,32 @@ const SandboxFlagFeaturePolicyPairs& SandboxFlagsWithFeaturePolicies() {
// corresponding feature policies. With FeaturePolicyForSandbox, these flags
// are always removed from the set of sandbox flags set for a sandboxed
// <iframe> (those sandbox flags are now contained in the |ContainerPolicy|).
-mojom::blink::WebSandboxFlags SandboxFlagsImplementedByFeaturePolicy() {
- DEFINE_STATIC_LOCAL(mojom::blink::WebSandboxFlags, mask,
- (mojom::blink::WebSandboxFlags::kNone));
- if (mask == mojom::blink::WebSandboxFlags::kNone) {
+network::mojom::blink::WebSandboxFlags
+SandboxFlagsImplementedByFeaturePolicy() {
+ DEFINE_STATIC_LOCAL(network::mojom::blink::WebSandboxFlags, mask,
+ (network::mojom::blink::WebSandboxFlags::kNone));
+ if (mask == network::mojom::blink::WebSandboxFlags::kNone) {
for (const auto& pair : SandboxFlagsWithFeaturePolicies())
mask |= pair.first;
}
return mask;
}
-mojom::blink::WebSandboxFlags ParseSandboxPolicy(
- const SpaceSplitString& policy,
- String& invalid_tokens_error_message) {
- // http://www.w3.org/TR/html5/the-iframe-element.html#attr-iframe-sandbox
- // Parse the unordered set of unique space-separated tokens.
- mojom::blink::WebSandboxFlags flags = mojom::blink::WebSandboxFlags::kAll;
- unsigned length = policy.size();
- unsigned number_of_token_errors = 0;
- StringBuilder token_errors;
-
- for (unsigned index = 0; index < length; index++) {
- // Turn off the corresponding sandbox flag if it's set as "allowed".
- String sandbox_token(policy[index]);
- if (EqualIgnoringASCIICase(sandbox_token, "allow-same-origin")) {
- flags = flags & ~mojom::blink::WebSandboxFlags::kOrigin;
- } else if (EqualIgnoringASCIICase(sandbox_token, "allow-forms")) {
- flags = flags & ~mojom::blink::WebSandboxFlags::kForms;
- } else if (EqualIgnoringASCIICase(sandbox_token, "allow-scripts")) {
- flags = flags & ~mojom::blink::WebSandboxFlags::kScripts;
- flags = flags & ~mojom::blink::WebSandboxFlags::kAutomaticFeatures;
- } else if (EqualIgnoringASCIICase(sandbox_token, "allow-top-navigation")) {
- flags = flags & ~mojom::blink::WebSandboxFlags::kTopNavigation;
- } else if (EqualIgnoringASCIICase(sandbox_token, "allow-popups")) {
- flags = flags & ~mojom::blink::WebSandboxFlags::kPopups;
- } else if (EqualIgnoringASCIICase(sandbox_token, "allow-pointer-lock")) {
- flags = flags & ~mojom::blink::WebSandboxFlags::kPointerLock;
- } else if (EqualIgnoringASCIICase(sandbox_token,
- "allow-orientation-lock")) {
- flags = flags & ~mojom::blink::WebSandboxFlags::kOrientationLock;
- } else if (EqualIgnoringASCIICase(sandbox_token,
- "allow-popups-to-escape-sandbox")) {
- flags = flags & ~mojom::blink::WebSandboxFlags::
- kPropagatesToAuxiliaryBrowsingContexts;
- } else if (EqualIgnoringASCIICase(sandbox_token, "allow-modals")) {
- flags = flags & ~mojom::blink::WebSandboxFlags::kModals;
- } else if (EqualIgnoringASCIICase(sandbox_token, "allow-presentation")) {
- flags = flags & ~mojom::blink::WebSandboxFlags::kPresentationController;
- } else if (EqualIgnoringASCIICase(
- sandbox_token, "allow-top-navigation-by-user-activation")) {
- flags = flags &
- ~mojom::blink::WebSandboxFlags::kTopNavigationByUserActivation;
- } else if (EqualIgnoringASCIICase(sandbox_token, "allow-downloads")) {
- flags = flags & ~mojom::blink::WebSandboxFlags::kDownloads;
- } else if (RuntimeEnabledFeatures::StorageAccessAPIEnabled() &&
- EqualIgnoringASCIICase(
- sandbox_token, "allow-storage-access-by-user-activation")) {
- flags = flags &
- ~mojom::blink::WebSandboxFlags::kStorageAccessByUserActivation;
- } else {
- token_errors.Append(token_errors.IsEmpty() ? "'" : ", '");
- token_errors.Append(sandbox_token);
- token_errors.Append("'");
- number_of_token_errors++;
- }
- }
-
- if (number_of_token_errors) {
- token_errors.Append(number_of_token_errors > 1
- ? " are invalid sandbox flags."
- : " is an invalid sandbox flag.");
- invalid_tokens_error_message = token_errors.ToString();
- }
-
- return flags;
-}
-
// Removes a certain set of flags from |sandbox_flags| for which we have feature
// policies implemented.
-mojom::blink::WebSandboxFlags GetSandboxFlagsNotImplementedAsFeaturePolicy(
- mojom::blink::WebSandboxFlags sandbox_flags) {
+network::mojom::blink::WebSandboxFlags
+GetSandboxFlagsNotImplementedAsFeaturePolicy(
+ network::mojom::blink::WebSandboxFlags sandbox_flags) {
// Punch all the sandbox flags which are converted to feature policy.
return sandbox_flags & ~SandboxFlagsImplementedByFeaturePolicy();
}
void ApplySandboxFlagsToParsedFeaturePolicy(
- mojom::blink::WebSandboxFlags sandbox_flags,
+ network::mojom::blink::WebSandboxFlags sandbox_flags,
ParsedFeaturePolicy& parsed_feature_policy) {
for (const auto& pair : SandboxFlagsWithFeaturePolicies()) {
- if ((sandbox_flags & pair.first) != mojom::blink::WebSandboxFlags::kNone)
+ if ((sandbox_flags & pair.first) !=
+ network::mojom::blink::WebSandboxFlags::kNone)
DisallowFeatureIfNotPresent(pair.second, parsed_feature_policy);
}
}
diff --git a/chromium/third_party/blink/renderer/core/frame/sandbox_flags.h b/chromium/third_party/blink/renderer/core/frame/sandbox_flags.h
index 817d836fdf0..8bbf7a95cbc 100644
--- a/chromium/third_party/blink/renderer/core/frame/sandbox_flags.h
+++ b/chromium/third_party/blink/renderer/core/frame/sandbox_flags.h
@@ -27,16 +27,14 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_SANDBOX_FLAGS_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_SANDBOX_FLAGS_H_
+#include "services/network/public/mojom/web_sandbox_flags.mojom-blink-forward.h"
#include "third_party/blink/public/common/feature_policy/feature_policy.h"
-#include "third_party/blink/public/common/frame/sandbox_flags.h"
-#include "third_party/blink/public/mojom/feature_policy/feature_policy.mojom-blink-forward.h"
#include "third_party/blink/public/mojom/feature_policy/feature_policy_feature.mojom-blink-forward.h"
-#include "third_party/blink/renderer/core/dom/space_split_string.h"
#include "third_party/blink/renderer/platform/wtf/forward.h"
namespace blink {
using SandboxFlagFeaturePolicyPairs =
- Vector<std::pair<mojom::blink::WebSandboxFlags,
+ Vector<std::pair<network::mojom::blink::WebSandboxFlags,
mojom::blink::FeaturePolicyFeature>>;
// Returns a vector of pairs of sandbox flags and the corresponding feature
@@ -44,21 +42,19 @@ using SandboxFlagFeaturePolicyPairs =
// yet migrated to using feature policies.
const SandboxFlagFeaturePolicyPairs& SandboxFlagsWithFeaturePolicies();
-mojom::blink::WebSandboxFlags ParseSandboxPolicy(
- const SpaceSplitString& policy,
- String& invalid_tokens_error_message);
-
// With FeaturePolicyForSandbox most sandbox flags will be represented with
// features. This method returns the part of sandbox flags which were not mapped
// to corresponding features.
-mojom::blink::WebSandboxFlags GetSandboxFlagsNotImplementedAsFeaturePolicy(
- mojom::blink::WebSandboxFlags);
+network::mojom::blink::WebSandboxFlags
+ GetSandboxFlagsNotImplementedAsFeaturePolicy(
+ network::mojom::blink::WebSandboxFlags);
// Applies the sandbox flags as parsed feature policies; If a flag is present
// both in the provided flags and in the parsed feature as a feature policy,
// the parsed policy takes precedence.
-void ApplySandboxFlagsToParsedFeaturePolicy(mojom::blink::WebSandboxFlags,
- ParsedFeaturePolicy&);
+void ApplySandboxFlagsToParsedFeaturePolicy(
+ network::mojom::blink::WebSandboxFlags,
+ ParsedFeaturePolicy&);
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/frame/scheduling.cc b/chromium/third_party/blink/renderer/core/frame/scheduling.cc
index cd659ee2522..d270b559c30 100644
--- a/chromium/third_party/blink/renderer/core/frame/scheduling.cc
+++ b/chromium/third_party/blink/renderer/core/frame/scheduling.cc
@@ -5,61 +5,30 @@
#include "third_party/blink/renderer/core/frame/scheduling.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
-#include "third_party/blink/renderer/core/inspector/console_message.h"
-#include "third_party/blink/renderer/platform/heap/heap.h"
+#include "third_party/blink/renderer/core/frame/is_input_pending_options.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/scheduler/main_thread/pending_user_input.h"
-#include "third_party/blink/renderer/platform/scheduler/public/pending_user_input_type.h"
#include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h"
-#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
-#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
namespace blink {
bool Scheduling::isInputPending(ScriptState* script_state,
- const Vector<String>& input_types) const {
+ const IsInputPendingOptions* options) const {
DCHECK(RuntimeEnabledFeatures::ExperimentalIsInputPendingEnabled(
ExecutionContext::From(script_state)));
- if (!Platform::Current()->IsLockedToSite()) {
- // As we're interested in checking pending events for as many frames as we
- // can on the main thread, restrict the API to the case where all frames in
- // a process are part of the same site to avoid leaking cross-site inputs.
- ExecutionContext::From(script_state)
- ->AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>(
- mojom::ConsoleMessageSource::kJavaScript,
- mojom::ConsoleMessageLevel::kWarning,
- "isInputPending requires site-per-process (crbug.com/910421)."));
+ auto* frame = LocalDOMWindow::From(script_state)->GetFrame();
+ if (!frame)
return false;
- }
auto* scheduler = ThreadScheduler::Current();
- auto input_info = scheduler->GetPendingUserInputInfo();
- if (input_types.size() == 0) {
- // If unspecified, return true if any input type is pending.
- return input_info.HasPendingInputType(
- scheduler::PendingUserInputType::kAny);
- }
+ auto info = scheduler->GetPendingUserInputInfo(options->includeContinuous());
- bool has_pending_input = false;
- for (const String& input_type_string : input_types) {
- const auto pending_input_type = scheduler::PendingUserInput::TypeFromString(
- AtomicString(input_type_string));
- if (pending_input_type == scheduler::PendingUserInputType::kNone) {
- StringBuilder message;
- message.Append("Unknown input event type \"");
- message.Append(input_type_string);
- message.Append("\". Skipping.");
- ExecutionContext::From(script_state)
- ->AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>(
- mojom::ConsoleMessageSource::kJavaScript,
- mojom::ConsoleMessageLevel::kWarning, message.ToString()));
- }
-
- if (!has_pending_input)
- has_pending_input |= input_info.HasPendingInputType(pending_input_type);
- }
- return has_pending_input;
+ // TODO(acomminos): Attribution first requires a reverse mapping between
+ // cc::ElementId instances and their underlying Document* objects.
+ (void)info;
+ return false;
}
bool Scheduling::isFramePending() const {
diff --git a/chromium/third_party/blink/renderer/core/frame/scheduling.h b/chromium/third_party/blink/renderer/core/frame/scheduling.h
index 55df6f89981..b2f35f168d7 100644
--- a/chromium/third_party/blink/renderer/core/frame/scheduling.h
+++ b/chromium/third_party/blink/renderer/core/frame/scheduling.h
@@ -12,12 +12,14 @@
namespace blink {
+class IsInputPendingOptions;
+
// Low-level scheduling primitives for JS scheduler implementations.
class Scheduling : public ScriptWrappable {
DEFINE_WRAPPERTYPEINFO();
public:
- bool isInputPending(ScriptState*, const Vector<String>& input_types) const;
+ bool isInputPending(ScriptState*, const IsInputPendingOptions* options) const;
bool isFramePending() const;
};
diff --git a/chromium/third_party/blink/renderer/core/frame/scheduling.idl b/chromium/third_party/blink/renderer/core/frame/scheduling.idl
index c1ae6538e09..ea3bd840d17 100644
--- a/chromium/third_party/blink/renderer/core/frame/scheduling.idl
+++ b/chromium/third_party/blink/renderer/core/frame/scheduling.idl
@@ -2,9 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// https://github.com/tdresser/is-input-pending
-[RuntimeEnabled=ExperimentalIsInputPending]
-interface Scheduling {
+// https://github.com/WICG/is-input-pending
+[
+ Exposed=Window,
+ RuntimeEnabled=ExperimentalIsInputPending
+] interface Scheduling {
[RuntimeEnabled=ExperimentalIsInputPending] boolean isFramePending();
- [CallWith=ScriptState, MeasureAs=SchedulingIsInputPending, RuntimeEnabled=ExperimentalIsInputPending] boolean isInputPending(optional sequence<DOMString> inputTypes = []);
+ [CallWith=ScriptState, MeasureAs=SchedulingIsInputPending, RuntimeEnabled=ExperimentalIsInputPending] boolean isInputPending(IsInputPendingOptions options);
};
diff --git a/chromium/third_party/blink/renderer/core/frame/screen.cc b/chromium/third_party/blink/renderer/core/frame/screen.cc
index 835eb382387..4410029341a 100644
--- a/chromium/third_party/blink/renderer/core/frame/screen.cc
+++ b/chromium/third_party/blink/renderer/core/frame/screen.cc
@@ -46,11 +46,11 @@ WebScreenInfo GetScreenInfo(LocalFrame& frame) {
} // namespace
-Screen::Screen(LocalFrame* frame) : DOMWindowClient(frame) {}
+Screen::Screen(LocalFrame* frame) : ExecutionContextClient(frame) {}
int Screen::height() const {
if (display_) {
- DCHECK(RuntimeEnabledFeatures::ScreenEnumerationEnabled());
+ DCHECK(RuntimeEnabledFeatures::WindowPlacementEnabled());
return display_->bounds.height();
}
LocalFrame* frame = GetFrame();
@@ -67,7 +67,7 @@ int Screen::height() const {
int Screen::width() const {
if (display_) {
- DCHECK(RuntimeEnabledFeatures::ScreenEnumerationEnabled());
+ DCHECK(RuntimeEnabledFeatures::WindowPlacementEnabled());
return display_->bounds.width();
}
LocalFrame* frame = GetFrame();
@@ -84,7 +84,7 @@ int Screen::width() const {
unsigned Screen::colorDepth() const {
if (display_) {
- DCHECK(RuntimeEnabledFeatures::ScreenEnumerationEnabled());
+ DCHECK(RuntimeEnabledFeatures::WindowPlacementEnabled());
return display_->color_depth;
}
LocalFrame* frame = GetFrame();
@@ -99,7 +99,7 @@ unsigned Screen::pixelDepth() const {
int Screen::availLeft() const {
if (display_) {
- DCHECK(RuntimeEnabledFeatures::ScreenEnumerationEnabled());
+ DCHECK(RuntimeEnabledFeatures::WindowPlacementEnabled());
return display_->work_area.x();
}
LocalFrame* frame = GetFrame();
@@ -116,7 +116,7 @@ int Screen::availLeft() const {
int Screen::availTop() const {
if (display_) {
- DCHECK(RuntimeEnabledFeatures::ScreenEnumerationEnabled());
+ DCHECK(RuntimeEnabledFeatures::WindowPlacementEnabled());
return display_->work_area.y();
}
LocalFrame* frame = GetFrame();
@@ -133,7 +133,7 @@ int Screen::availTop() const {
int Screen::availHeight() const {
if (display_) {
- DCHECK(RuntimeEnabledFeatures::ScreenEnumerationEnabled());
+ DCHECK(RuntimeEnabledFeatures::WindowPlacementEnabled());
return display_->work_area.height();
}
LocalFrame* frame = GetFrame();
@@ -150,7 +150,7 @@ int Screen::availHeight() const {
int Screen::availWidth() const {
if (display_) {
- DCHECK(RuntimeEnabledFeatures::ScreenEnumerationEnabled());
+ DCHECK(RuntimeEnabledFeatures::WindowPlacementEnabled());
return display_->work_area.width();
}
LocalFrame* frame = GetFrame();
@@ -167,21 +167,23 @@ int Screen::availWidth() const {
void Screen::Trace(Visitor* visitor) {
ScriptWrappable::Trace(visitor);
- DOMWindowClient::Trace(visitor);
+ ExecutionContextClient::Trace(visitor);
Supplementable<Screen>::Trace(visitor);
}
Screen::Screen(display::mojom::blink::DisplayPtr display,
bool internal,
- bool primary)
- : DOMWindowClient(static_cast<LocalFrame*>(nullptr)),
+ bool primary,
+ const String& id)
+ : ExecutionContextClient(static_cast<LocalFrame*>(nullptr)),
display_(std::move(display)),
internal_(internal),
- primary_(primary) {}
+ primary_(primary),
+ id_(id) {}
int Screen::left() const {
if (display_) {
- DCHECK(RuntimeEnabledFeatures::ScreenEnumerationEnabled());
+ DCHECK(RuntimeEnabledFeatures::WindowPlacementEnabled());
return display_->bounds.x();
}
LocalFrame* frame = GetFrame();
@@ -198,7 +200,7 @@ int Screen::left() const {
int Screen::top() const {
if (display_) {
- DCHECK(RuntimeEnabledFeatures::ScreenEnumerationEnabled());
+ DCHECK(RuntimeEnabledFeatures::WindowPlacementEnabled());
return display_->bounds.y();
}
LocalFrame* frame = GetFrame();
@@ -215,7 +217,7 @@ int Screen::top() const {
bool Screen::internal() const {
if (display_) {
- DCHECK(RuntimeEnabledFeatures::ScreenEnumerationEnabled());
+ DCHECK(RuntimeEnabledFeatures::WindowPlacementEnabled());
return internal_.has_value() && internal_.value();
}
// TODO(http://crbug.com/994889): Implement this for |window.screen|?
@@ -225,7 +227,7 @@ bool Screen::internal() const {
bool Screen::primary() const {
if (display_) {
- DCHECK(RuntimeEnabledFeatures::ScreenEnumerationEnabled());
+ DCHECK(RuntimeEnabledFeatures::WindowPlacementEnabled());
return primary_.has_value() && primary_.value();
}
// TODO(http://crbug.com/994889): Implement this for |window.screen|?
@@ -235,7 +237,7 @@ bool Screen::primary() const {
float Screen::scaleFactor() const {
if (display_) {
- DCHECK(RuntimeEnabledFeatures::ScreenEnumerationEnabled());
+ DCHECK(RuntimeEnabledFeatures::WindowPlacementEnabled());
return display_->device_scale_factor;
}
LocalFrame* frame = GetFrame();
@@ -244,19 +246,30 @@ float Screen::scaleFactor() const {
return GetScreenInfo(*frame).device_scale_factor;
}
-const String Screen::name() const {
- // TODO(http://crbug.com/994889): Implement this.
- NOTIMPLEMENTED_LOG_ONCE();
+const String Screen::id() const {
if (display_) {
- DCHECK(RuntimeEnabledFeatures::ScreenEnumerationEnabled());
- return "Generic Screen";
+ DCHECK(RuntimeEnabledFeatures::WindowPlacementEnabled());
+ return id_;
}
+ // TODO(http://crbug.com/994889): Implement this for |window.screen|?
+ NOTIMPLEMENTED_LOG_ONCE();
return String();
}
+bool Screen::touchSupport() const {
+ if (display_) {
+ DCHECK(RuntimeEnabledFeatures::WindowPlacementEnabled());
+ return display_->touch_support ==
+ display::mojom::blink::TouchSupport::AVAILABLE;
+ }
+ // TODO(http://crbug.com/994889): Implement this for |window.screen|?
+ NOTIMPLEMENTED_LOG_ONCE();
+ return false;
+}
+
int64_t Screen::DisplayId() const {
if (display_) {
- DCHECK(RuntimeEnabledFeatures::ScreenEnumerationEnabled());
+ DCHECK(RuntimeEnabledFeatures::WindowPlacementEnabled());
return display_->id;
}
return kInvalidDisplayId;
diff --git a/chromium/third_party/blink/renderer/core/frame/screen.h b/chromium/third_party/blink/renderer/core/frame/screen.h
index 8503ee5f9ef..57b9235cf77 100644
--- a/chromium/third_party/blink/renderer/core/frame/screen.h
+++ b/chromium/third_party/blink/renderer/core/frame/screen.h
@@ -43,7 +43,7 @@ namespace blink {
class LocalFrame;
class CORE_EXPORT Screen final : public ScriptWrappable,
- public DOMWindowClient,
+ public ExecutionContextClient,
public Supplementable<Screen> {
DEFINE_WRAPPERTYPEINFO();
USING_GARBAGE_COLLECTED_MIXIN(Screen);
@@ -67,13 +67,15 @@ class CORE_EXPORT Screen final : public ScriptWrappable,
// TODO(msw): Resolve different info sources, caching, and lifetimes.
Screen(display::mojom::blink::DisplayPtr display,
bool internal,
- bool primary);
+ bool primary,
+ const String& id);
int left() const;
int top() const;
bool internal() const;
bool primary() const;
float scaleFactor() const;
- const String name() const;
+ const String id() const;
+ bool touchSupport() const;
// Not web-exposed; for internal usage only.
static constexpr int64_t kInvalidDisplayId = -1;
@@ -92,6 +94,10 @@ class CORE_EXPORT Screen final : public ScriptWrappable,
// value provided upon construction. This member is only valid for Screen
// objects obtained via the experimental Screen Enumeration API.
const base::Optional<bool> primary_;
+ // A web-exposed device id; it is a static value provided upon construction.
+ // This member is only valid for Screen objects obtained via the experimental
+ // Screen Enumeration API.
+ const String id_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/frame/screen.idl b/chromium/third_party/blink/renderer/core/frame/screen.idl
index d9f328eeb06..9a5e18dbb72 100644
--- a/chromium/third_party/blink/renderer/core/frame/screen.idl
+++ b/chromium/third_party/blink/renderer/core/frame/screen.idl
@@ -44,10 +44,11 @@
// Proposed
// https://github.com/webscreens/screen-enumeration
- [RuntimeEnabled=ScreenEnumeration] readonly attribute long left;
- [RuntimeEnabled=ScreenEnumeration] readonly attribute long top;
- [RuntimeEnabled=ScreenEnumeration] readonly attribute boolean internal;
- [RuntimeEnabled=ScreenEnumeration] readonly attribute boolean primary;
- [RuntimeEnabled=ScreenEnumeration] readonly attribute float scaleFactor;
- [RuntimeEnabled=ScreenEnumeration] readonly attribute DOMString name;
+ [RuntimeEnabled=WindowPlacement] readonly attribute long left;
+ [RuntimeEnabled=WindowPlacement] readonly attribute long top;
+ [RuntimeEnabled=WindowPlacement] readonly attribute boolean internal;
+ [RuntimeEnabled=WindowPlacement] readonly attribute boolean primary;
+ [RuntimeEnabled=WindowPlacement] readonly attribute float scaleFactor;
+ [RuntimeEnabled=WindowPlacement] readonly attribute DOMString id;
+ [RuntimeEnabled=WindowPlacement] readonly attribute boolean touchSupport;
};
diff --git a/chromium/third_party/blink/renderer/core/frame/screen_orientation_controller.cc b/chromium/third_party/blink/renderer/core/frame/screen_orientation_controller.cc
deleted file mode 100644
index a8ff1b8a489..00000000000
--- a/chromium/third_party/blink/renderer/core/frame/screen_orientation_controller.cc
+++ /dev/null
@@ -1,33 +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/core/frame/screen_orientation_controller.h"
-
-namespace blink {
-
-ScreenOrientationController::ScreenOrientationController(LocalFrame& frame)
- : Supplement<LocalFrame>(frame) {}
-
-// static
-ScreenOrientationController* ScreenOrientationController::From(
- LocalFrame& frame) {
- return Supplement<LocalFrame>::From<ScreenOrientationController>(frame);
-}
-
-void ScreenOrientationController::Trace(Visitor* visitor) {
- Supplement<LocalFrame>::Trace(visitor);
-}
-
-// static
-void ScreenOrientationController::ProvideTo(
- LocalFrame& frame,
- ScreenOrientationController* controller) {
- Supplement<LocalFrame>::ProvideTo(frame, controller);
-}
-
-// static
-const char ScreenOrientationController::kSupplementName[] =
- "ScreenOrientationController";
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/frame/screen_orientation_controller.h b/chromium/third_party/blink/renderer/core/frame/screen_orientation_controller.h
deleted file mode 100644
index fdda50f2e99..00000000000
--- a/chromium/third_party/blink/renderer/core/frame/screen_orientation_controller.h
+++ /dev/null
@@ -1,57 +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_CORE_FRAME_SCREEN_ORIENTATION_CONTROLLER_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_SCREEN_ORIENTATION_CONTROLLER_H_
-
-#include "third_party/blink/public/common/screen_orientation/web_screen_orientation_lock_type.h"
-#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/core/frame/local_frame.h"
-#include "third_party/blink/renderer/platform/supplementable.h"
-
-namespace blink {
-
-class WebLockOrientationCallback;
-
-// ScreenOrientationController allows to manipulate screen orientation in Blink
-// outside of the screen_orientation/ modules. It is an interface that the
-// module will implement and add a provider for.
-// Callers of ScreenOrientationController::from() should always assume the
-// returned pointer can be nullptr.
-class CORE_EXPORT ScreenOrientationController
- : public GarbageCollected<ScreenOrientationController>,
- public Supplement<LocalFrame> {
- USING_GARBAGE_COLLECTED_MIXIN(ScreenOrientationController);
-
- public:
- static const char kSupplementName[];
-
- virtual ~ScreenOrientationController() = default;
-
- static ScreenOrientationController* From(LocalFrame&);
-
- virtual void NotifyOrientationChanged() = 0;
-
- virtual void lock(WebScreenOrientationLockType,
- std::unique_ptr<WebLockOrientationCallback>) = 0;
- virtual void unlock() = 0;
-
- // Returns whether a lock() call was made without an unlock() call. Others
- // frames might have changed the lock state so this should only be used to
- // know whether the current frame made an attempt to lock without explicitly
- // unlocking.
- virtual bool MaybeHasActiveLock() const = 0;
-
- void Trace(Visitor*) override;
-
- protected:
- explicit ScreenOrientationController(LocalFrame&);
- // To be called by an ScreenOrientationController to register its
- // implementation.
- static void ProvideTo(LocalFrame&, ScreenOrientationController*);
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_SCREEN_ORIENTATION_CONTROLLER_H_
diff --git a/chromium/third_party/blink/renderer/core/frame/settings.json5 b/chromium/third_party/blink/renderer/core/frame/settings.json5
index 6d0831608f3..e6ab013ef0e 100644
--- a/chromium/third_party/blink/renderer/core/frame/settings.json5
+++ b/chromium/third_party/blink/renderer/core/frame/settings.json5
@@ -1035,22 +1035,22 @@
},
{
name: "lazyImageFirstKFullyLoadSlow2G",
- initial: 12,
+ initial: 0,
type: "int",
},
{
name: "lazyImageFirstKFullyLoad2G",
- initial: 10,
+ initial: 0,
type: "int",
},
{
name: "lazyImageFirstKFullyLoad3G",
- initial: 8,
+ initial: 0,
type: "int",
},
{
name: "lazyImageFirstKFullyLoad4G",
- initial: 6,
+ initial: 0,
type: "int",
},
@@ -1082,5 +1082,12 @@
invalidate: "MediaQuery",
type: "NavigationControls",
},
+
+ {
+ name: "accessibilityAlwaysShowFocus",
+ initial: false,
+ invalidate: "Style",
+ type: "bool"
+ }
],
}
diff --git a/chromium/third_party/blink/renderer/core/frame/ua_data_values.idl b/chromium/third_party/blink/renderer/core/frame/ua_data_values.idl
index 3def0d4d529..095981d5ffc 100644
--- a/chromium/third_party/blink/renderer/core/frame/ua_data_values.idl
+++ b/chromium/third_party/blink/renderer/core/frame/ua_data_values.idl
@@ -5,9 +5,9 @@
// https://github.com/WICG/ua-client-hints
dictionary UADataValues {
- DOMString platform = "";
- DOMString platformVersion = "";
- DOMString architecture = "";
- DOMString model = "";
- DOMString uaFullVersion = "";
+ DOMString platform;
+ DOMString platformVersion;
+ DOMString architecture;
+ DOMString model;
+ DOMString uaFullVersion;
};
diff --git a/chromium/third_party/blink/renderer/core/frame/visual_viewport.cc b/chromium/third_party/blink/renderer/core/frame/visual_viewport.cc
index 0d3977949cd..74903f8f5ba 100644
--- a/chromium/third_party/blink/renderer/core/frame/visual_viewport.cc
+++ b/chromium/third_party/blink/renderer/core/frame/visual_viewport.cc
@@ -34,7 +34,7 @@
#include "base/metrics/histogram_functions.h"
#include "cc/input/main_thread_scrolling_reason.h"
-#include "cc/layers/scrollbar_layer_base.h"
+#include "cc/layers/solid_color_scrollbar_layer.h"
#include "third_party/blink/public/mojom/scroll/scroll_into_view_params.mojom-blink.h"
#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
@@ -630,9 +630,6 @@ void VisualViewport::UpdateScrollbarLayer(ScrollbarOrientation orientation) {
scoped_refptr<cc::ScrollbarLayerBase>& scrollbar_layer =
is_horizontal ? scrollbar_layer_horizontal_ : scrollbar_layer_vertical_;
if (!scrollbar_layer) {
- ScrollingCoordinator* coordinator = GetPage().GetScrollingCoordinator();
- DCHECK(coordinator);
-
auto& theme = ScrollbarThemeOverlayMobile::GetInstance();
int thumb_thickness = clampTo<int>(
std::floor(GetPage().GetChromeClient().WindowToViewportScalar(
@@ -640,9 +637,12 @@ void VisualViewport::UpdateScrollbarLayer(ScrollbarOrientation orientation) {
int scrollbar_margin = clampTo<int>(
std::floor(GetPage().GetChromeClient().WindowToViewportScalar(
MainFrame(), theme.ScrollbarMargin())));
- scrollbar_layer = coordinator->CreateSolidColorScrollbarLayer(
- orientation, thumb_thickness, scrollbar_margin, false,
- GetScrollbarElementId(orientation));
+ cc::ScrollbarOrientation cc_orientation =
+ orientation == kHorizontalScrollbar ? cc::HORIZONTAL : cc::VERTICAL;
+ scrollbar_layer = cc::SolidColorScrollbarLayer::Create(
+ cc_orientation, thumb_thickness, scrollbar_margin,
+ /*is_left_side_vertical_scrollbar*/ false);
+ scrollbar_layer->SetElementId(GetScrollbarElementId(orientation));
scrollbar_layer->SetScrollElementId(scroll_layer_->element_id());
scrollbar_layer->SetIsDrawable(true);
}
diff --git a/chromium/third_party/blink/renderer/core/frame/visual_viewport.idl b/chromium/third_party/blink/renderer/core/frame/visual_viewport.idl
index 4d64ea5347d..6aedf344bc9 100644
--- a/chromium/third_party/blink/renderer/core/frame/visual_viewport.idl
+++ b/chromium/third_party/blink/renderer/core/frame/visual_viewport.idl
@@ -27,6 +27,7 @@
// WICG proposal: https://github.com/WICG/ViewportAPI
[
+ Exposed=Window,
ImplementedAs=DOMVisualViewport
] interface VisualViewport : EventTarget {
[HighEntropy, Measure] readonly attribute double offsetLeft;
diff --git a/chromium/third_party/blink/renderer/core/frame/visual_viewport_test.cc b/chromium/third_party/blink/renderer/core/frame/visual_viewport_test.cc
index c0d594da78d..5fc2bfe737b 100644
--- a/chromium/third_party/blink/renderer/core/frame/visual_viewport_test.cc
+++ b/chromium/third_party/blink/renderer/core/frame/visual_viewport_test.cc
@@ -13,9 +13,9 @@
#include "cc/trees/transform_node.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/input/web_coalesced_input_event.h"
#include "third_party/blink/public/common/input/web_input_event.h"
#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h"
-#include "third_party/blink/public/platform/web_coalesced_input_event.h"
#include "third_party/blink/public/platform/web_url_loader_mock_factory.h"
#include "third_party/blink/public/web/web_ax_context.h"
#include "third_party/blink/public/web/web_context_menu_data.h"
@@ -1135,7 +1135,7 @@ TEST_P(VisualViewportTest, TestContextMenuShownInCorrectLocation) {
RegisterMockedHttpURLLoad("200-by-300.html");
NavigateTo(base_url_ + "200-by-300.html");
- WebMouseEvent mouse_down_event(WebInputEvent::kMouseDown,
+ WebMouseEvent mouse_down_event(WebInputEvent::Type::kMouseDown,
WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests());
mouse_down_event.SetPositionInWidget(10, 10);
@@ -1145,7 +1145,7 @@ TEST_P(VisualViewportTest, TestContextMenuShownInCorrectLocation) {
// Corresponding release event (Windows shows context menu on release).
WebMouseEvent mouse_up_event(mouse_down_event);
- mouse_up_event.SetType(WebInputEvent::kMouseUp);
+ mouse_up_event.SetType(WebInputEvent::Type::kMouseUp);
WebLocalFrameClient* old_client = WebView()->MainFrameImpl()->Client();
VisualViewportMockWebFrameClient mock_web_frame_client;
@@ -1157,14 +1157,14 @@ TEST_P(VisualViewportTest, TestContextMenuShownInCorrectLocation) {
// Do a sanity check with no scale applied.
WebView()->MainFrameImpl()->SetClient(&mock_web_frame_client);
WebView()->MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(mouse_down_event));
+ WebCoalescedInputEvent(mouse_down_event, ui::LatencyInfo()));
WebView()->MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(mouse_up_event));
+ WebCoalescedInputEvent(mouse_up_event, ui::LatencyInfo()));
Mock::VerifyAndClearExpectations(&mock_web_frame_client);
mouse_down_event.button = WebMouseEvent::Button::kLeft;
WebView()->MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(mouse_down_event));
+ WebCoalescedInputEvent(mouse_down_event, ui::LatencyInfo()));
// Now pinch zoom into the page and move the visual viewport. The context menu
// should still appear at the location of the event, relative to the WebView.
@@ -1179,9 +1179,9 @@ TEST_P(VisualViewportTest, TestContextMenuShownInCorrectLocation) {
mouse_down_event.button = WebMouseEvent::Button::kRight;
WebView()->MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(mouse_down_event));
+ WebCoalescedInputEvent(mouse_down_event, ui::LatencyInfo()));
WebView()->MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(mouse_up_event));
+ WebCoalescedInputEvent(mouse_up_event, ui::LatencyInfo()));
// Reset the old client so destruction can occur naturally.
WebView()->MainFrameImpl()->SetClient(old_client);
@@ -1899,7 +1899,7 @@ TEST_P(VisualViewportTest, SlowScrollAfterImplScroll) {
// Send a scroll event on the main thread path.
WebGestureEvent gsb(
- WebInputEvent::kGestureScrollBegin, WebInputEvent::kNoModifiers,
+ WebInputEvent::Type::kGestureScrollBegin, WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests(), WebGestureDevice::kTouchpad);
gsb.SetFrameScale(1);
gsb.data.scroll_begin.delta_x_hint = -50;
@@ -1909,7 +1909,7 @@ TEST_P(VisualViewportTest, SlowScrollAfterImplScroll) {
GetFrame()->GetEventHandler().HandleGestureEvent(gsb);
WebGestureEvent gsu(
- WebInputEvent::kGestureScrollUpdate, WebInputEvent::kNoModifiers,
+ WebInputEvent::Type::kGestureScrollUpdate, WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests(), WebGestureDevice::kTouchpad);
gsu.SetFrameScale(1);
gsu.data.scroll_update.delta_x = -50;
@@ -2654,7 +2654,7 @@ TEST_P(VisualViewportTest, PaintScrollbar) {
auto check_scrollbar = [](const cc::Layer* scrollbar, float scale) {
EXPECT_TRUE(scrollbar->DrawsContent());
EXPECT_FALSE(scrollbar->HitTestable());
- EXPECT_TRUE(scrollbar->is_scrollbar());
+ EXPECT_TRUE(scrollbar->IsScrollbarLayerForTesting());
EXPECT_EQ(
cc::VERTICAL,
static_cast<const cc::ScrollbarLayerBase*>(scrollbar)->orientation());
diff --git a/chromium/third_party/blink/renderer/core/frame/web_frame_widget_base.cc b/chromium/third_party/blink/renderer/core/frame/web_frame_widget_base.cc
index cce5caed45a..b39722bc337 100644
--- a/chromium/third_party/blink/renderer/core/frame/web_frame_widget_base.cc
+++ b/chromium/third_party/blink/renderer/core/frame/web_frame_widget_base.cc
@@ -12,7 +12,9 @@
#include "base/time/time.h"
#include "cc/trees/layer_tree_host.h"
#include "cc/trees/swap_promise.h"
+#include "cc/trees/ukm_manager.h"
#include "third_party/blink/public/platform/platform.h"
+#include "third_party/blink/public/platform/scheduler/web_render_widget_scheduling_state.h"
#include "third_party/blink/public/web/web_local_frame.h"
#include "third_party/blink/public/web/web_widget_client.h"
#include "third_party/blink/renderer/core/dom/element.h"
@@ -96,12 +98,15 @@ void WebFrameWidgetBase::BindLocalRoot(WebLocalFrame& local_root) {
&WebFrameWidgetBase::RequestAnimationAfterDelayTimerFired));
}
-void WebFrameWidgetBase::Close() {
+void WebFrameWidgetBase::Close(
+ scoped_refptr<base::SingleThreadTaskRunner> cleanup_runner,
+ base::OnceCallback<void()> cleanup_task) {
mutator_dispatcher_ = nullptr;
local_root_->SetFrameWidget(nullptr);
local_root_ = nullptr;
client_ = nullptr;
request_animation_after_delay_timer_.reset();
+ widget_base_->Shutdown(std::move(cleanup_runner), std::move(cleanup_task));
widget_base_.reset();
receiver_.reset();
}
@@ -252,7 +257,7 @@ void WebFrameWidgetBase::DragSourceEndedAt(const gfx::PointF& point_in_viewport,
FloatPoint(point_in_viewport)));
WebMouseEvent fake_mouse_move(
- WebInputEvent::kMouseMove, point_in_root_frame, screen_point,
+ WebInputEvent::Type::kMouseMove, point_in_root_frame, screen_point,
WebPointerProperties::Button::kLeft, 0, WebInputEvent::kNoModifiers,
base::TimeTicks::Now());
fake_mouse_move.SetFrameScale(1);
@@ -368,6 +373,11 @@ Page* WebFrameWidgetBase::GetPage() const {
return View()->GetPage();
}
+const mojo::AssociatedRemote<mojom::blink::FrameWidgetHost>&
+WebFrameWidgetBase::GetAssociatedFrameWidgetHost() const {
+ return frame_widget_host_;
+}
+
void WebFrameWidgetBase::DidAcquirePointerLock() {
GetPage()->GetPointerLockController().DidAcquirePointerLock();
@@ -436,6 +446,40 @@ void WebFrameWidgetBase::RequestBeginMainFrameNotExpected(bool request) {
widget_base_->LayerTreeHost()->RequestBeginMainFrameNotExpected(request);
}
+void WebFrameWidgetBase::EndCommitCompositorFrame(
+ base::TimeTicks commit_start_time) {
+ Client()->DidCommitCompositorFrame(commit_start_time);
+}
+
+void WebFrameWidgetBase::DidCommitAndDrawCompositorFrame() {
+ Client()->DidCommitAndDrawCompositorFrame();
+}
+
+void WebFrameWidgetBase::OnDeferMainFrameUpdatesChanged(bool defer) {
+ Client()->OnDeferMainFrameUpdatesChanged(defer);
+}
+
+void WebFrameWidgetBase::OnDeferCommitsChanged(bool defer) {
+ Client()->OnDeferCommitsChanged(defer);
+}
+
+void WebFrameWidgetBase::RequestNewLayerTreeFrameSink(
+ LayerTreeFrameSinkCallback callback) {
+ Client()->RequestNewLayerTreeFrameSink(std::move(callback));
+}
+
+void WebFrameWidgetBase::DidCompletePageScaleAnimation() {
+ Client()->DidCompletePageScaleAnimation();
+}
+
+void WebFrameWidgetBase::DidBeginMainFrame() {
+ Client()->DidBeginMainFrame();
+}
+
+void WebFrameWidgetBase::WillBeginMainFrame() {
+ Client()->WillBeginMainFrame();
+}
+
int WebFrameWidgetBase::GetLayerTreeId() {
if (!View()->does_composite())
return 0;
@@ -451,6 +495,26 @@ void WebFrameWidgetBase::SetEventListenerProperties(
cc::EventListenerProperties listener_properties) {
widget_base_->LayerTreeHost()->SetEventListenerProperties(
listener_class, listener_properties);
+
+ if (listener_class == cc::EventListenerClass::kTouchStartOrMove ||
+ listener_class == cc::EventListenerClass::kTouchEndOrCancel) {
+ bool has_touch_handlers =
+ EventListenerProperties(cc::EventListenerClass::kTouchStartOrMove) !=
+ cc::EventListenerProperties::kNone ||
+ EventListenerProperties(cc::EventListenerClass::kTouchEndOrCancel) !=
+ cc::EventListenerProperties::kNone;
+ if (!has_touch_handlers_ || *has_touch_handlers_ != has_touch_handlers) {
+ has_touch_handlers_ = has_touch_handlers;
+
+ // Can be NULL when running tests.
+ if (auto* scheduler_state = widget_base_->RendererWidgetSchedulingState())
+ scheduler_state->SetHasTouchHandler(has_touch_handlers);
+ frame_widget_host_->SetHasTouchEventHandlers(has_touch_handlers);
+ }
+ } else if (listener_class == cc::EventListenerClass::kPointerRawUpdate) {
+ client_->SetHasPointerRawUpdateEventHandlers(
+ listener_properties != cc::EventListenerProperties::kNone);
+ }
}
cc::EventListenerProperties WebFrameWidgetBase::EventListenerProperties(
@@ -459,6 +523,10 @@ cc::EventListenerProperties WebFrameWidgetBase::EventListenerProperties(
listener_class);
}
+mojom::blink::DisplayMode WebFrameWidgetBase::DisplayMode() const {
+ return display_mode_;
+}
+
void WebFrameWidgetBase::StartDeferringCommits(base::TimeDelta timeout) {
if (!View()->does_composite())
return;
@@ -514,7 +582,7 @@ void WebFrameWidgetBase::PointerLockMouseEvent(
AtomicString event_type;
switch (input_event.GetType()) {
- case WebInputEvent::kMouseDown:
+ case WebInputEvent::Type::kMouseDown:
event_type = event_type_names::kMousedown;
if (!GetPage() || !GetPage()->GetPointerLockController().GetElement())
break;
@@ -524,10 +592,10 @@ void WebFrameWidgetBase::PointerLockMouseEvent(
->GetDocument()
.GetFrame());
break;
- case WebInputEvent::kMouseUp:
+ case WebInputEvent::Type::kMouseUp:
event_type = event_type_names::kMouseup;
break;
- case WebInputEvent::kMouseMove:
+ case WebInputEvent::Type::kMouseMove:
event_type = event_type_names::kMousemove;
break;
default:
@@ -581,34 +649,26 @@ WebLocalFrame* WebFrameWidgetBase::FocusedWebLocalFrameInWidget() const {
return WebLocalFrameImpl::FromFrame(FocusedLocalFrameInWidget());
}
-void WebFrameWidgetBase::SetCompositorHosts(cc::LayerTreeHost* layer_tree_host,
- cc::AnimationHost* animation_host) {
- widget_base_->SetCompositorHosts(layer_tree_host, animation_host);
+cc::LayerTreeHost* WebFrameWidgetBase::InitializeCompositing(
+ cc::TaskGraphRunner* task_graph_runner,
+ const cc::LayerTreeSettings& settings,
+ std::unique_ptr<cc::UkmRecorderFactory> ukm_recorder_factory) {
+ widget_base_->InitializeCompositing(task_graph_runner, settings,
+ std::move(ukm_recorder_factory));
GetPage()->AnimationHostInitialized(*AnimationHost(),
GetLocalFrameViewForAnimationScrolling());
+ return widget_base_->LayerTreeHost();
}
void WebFrameWidgetBase::SetCompositorVisible(bool visible) {
widget_base_->SetCompositorVisible(visible);
}
-void WebFrameWidgetBase::UpdateVisualState() {
- widget_base_->UpdateVisualState();
-}
-
void WebFrameWidgetBase::RecordTimeToFirstActivePaint(
base::TimeDelta duration) {
Client()->RecordTimeToFirstActivePaint(duration);
}
-void WebFrameWidgetBase::BeginFrame(base::TimeTicks frame_time) {
- widget_base_->BeginMainFrame(frame_time);
-}
-
-void WebFrameWidgetBase::WillBeginCompositorFrame() {
- widget_base_->WillBeginCompositorFrame();
-}
-
void WebFrameWidgetBase::DispatchRafAlignedInput(base::TimeTicks frame_time) {
base::TimeTicks raf_aligned_input_start_time;
if (LocalRootImpl() && WidgetBase::ShouldRecordBeginMainFrameMetrics()) {
@@ -626,10 +686,32 @@ void WebFrameWidgetBase::DispatchRafAlignedInput(base::TimeTicks frame_time) {
void WebFrameWidgetBase::ApplyViewportChangesForTesting(
const ApplyViewportChangesArgs& args) {
- // TODO(dtapuska): Temporarily just call ApplyViewportChanges.
- // ApplyViewportChanges will eventually be removed when compositing moves into
- // |widget_base_|.
- ApplyViewportChanges(args);
+ widget_base_->ApplyViewportChanges(args);
+}
+
+void WebFrameWidgetBase::SetDisplayMode(mojom::blink::DisplayMode mode) {
+ if (mode != display_mode_) {
+ display_mode_ = mode;
+ LocalFrame* frame = LocalRootImpl()->GetFrame();
+ frame->MediaQueryAffectingValueChangedForLocalSubtree(
+ MediaValueChange::kOther);
+ }
+}
+
+void WebFrameWidgetBase::SetCursor(const ui::Cursor& cursor) {
+ widget_base_->SetCursor(cursor);
+}
+
+void WebFrameWidgetBase::AutoscrollStart(const gfx::PointF& position) {
+ GetAssociatedFrameWidgetHost()->AutoscrollStart(std::move(position));
+}
+
+void WebFrameWidgetBase::AutoscrollFling(const gfx::Vector2dF& velocity) {
+ GetAssociatedFrameWidgetHost()->AutoscrollFling(std::move(velocity));
+}
+
+void WebFrameWidgetBase::AutoscrollEnd() {
+ GetAssociatedFrameWidgetHost()->AutoscrollEnd();
}
void WebFrameWidgetBase::RequestAnimationAfterDelay(
@@ -761,8 +843,8 @@ class ReportTimeSwapPromise : public cc::SwapPromise {
int frame_token) {
// If the widget was collected or the widget wasn't collected yet, but
// it was closed don't schedule a presentation callback.
- if (widget && widget->Client()) {
- widget->Client()->AddPresentationCallback(
+ if (widget && widget->widget_base_) {
+ widget->widget_base_->AddPresentationCallback(
frame_token,
WTF::Bind(&RunCallbackAfterPresentation,
std::move(presentation_time_callback), swap_time));
@@ -832,4 +914,9 @@ void WebFrameWidgetBase::NotifySwapAndPresentationTime(
this));
}
+scheduler::WebRenderWidgetSchedulingState*
+WebFrameWidgetBase::RendererWidgetSchedulingState() {
+ return widget_base_->RendererWidgetSchedulingState();
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/frame/web_frame_widget_base.h b/chromium/third_party/blink/renderer/core/frame/web_frame_widget_base.h
index 2663b0e651d..9cfb36d4718 100644
--- a/chromium/third_party/blink/renderer/core/frame/web_frame_widget_base.h
+++ b/chromium/third_party/blink/renderer/core/frame/web_frame_widget_base.h
@@ -13,10 +13,11 @@
#include "mojo/public/cpp/bindings/associated_receiver.h"
#include "mojo/public/cpp/bindings/associated_remote.h"
#include "services/network/public/mojom/referrer_policy.mojom-blink-forward.h"
+#include "third_party/blink/public/common/input/web_coalesced_input_event.h"
#include "third_party/blink/public/common/input/web_gesture_device.h"
+#include "third_party/blink/public/mojom/manifest/display_mode.mojom-blink.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/public/platform/web_coalesced_input_event.h"
#include "third_party/blink/public/platform/web_drag_data.h"
#include "third_party/blink/public/web/web_frame_widget.h"
#include "third_party/blink/renderer/core/clipboard/data_object.h"
@@ -44,7 +45,6 @@ class PaintWorkletPaintDispatcher;
class WebLocalFrameImpl;
class WebViewImpl;
class WidgetBase;
-struct IntrinsicSizingInfo;
class CORE_EXPORT WebFrameWidgetBase
: public GarbageCollected<WebFrameWidgetBase>,
@@ -76,7 +76,12 @@ class CORE_EXPORT WebFrameWidgetBase
void BindLocalRoot(WebLocalFrame&);
virtual bool ForSubframe() const = 0;
- virtual void IntrinsicSizingInfoChanged(const IntrinsicSizingInfo&) {}
+ virtual void IntrinsicSizingInfoChanged(
+ mojom::blink::IntrinsicSizingInfoPtr) {}
+
+ void AutoscrollStart(const gfx::PointF& position);
+ void AutoscrollFling(const gfx::Vector2dF& position);
+ void AutoscrollEnd();
// Creates or returns cached mutator dispatcher. This usually requires a
// round trip to the compositor. The returned WeakPtr must only be
@@ -91,7 +96,7 @@ class CORE_EXPORT WebFrameWidgetBase
base::WeakPtr<PaintWorkletPaintDispatcher> EnsureCompositorPaintDispatcher(
scoped_refptr<base::SingleThreadTaskRunner>* paint_task_runner);
- virtual HitTestResult CoreHitTestResultAt(const gfx::Point&) = 0;
+ virtual HitTestResult CoreHitTestResultAt(const gfx::PointF&) = 0;
// FrameWidget implementation.
WebWidgetClient* Client() const final { return client_; }
@@ -111,9 +116,9 @@ class CORE_EXPORT WebFrameWidgetBase
cc::EventListenerProperties) final;
cc::EventListenerProperties EventListenerProperties(
cc::EventListenerClass) const final;
+ mojom::blink::DisplayMode DisplayMode() const override;
// WebFrameWidget implementation.
- void Close() override;
WebLocalFrame* LocalRoot() const override;
WebDragOperation DragTargetDragEnter(const WebDragData&,
const gfx::PointF& point_in_viewport,
@@ -140,12 +145,13 @@ class CORE_EXPORT WebFrameWidgetBase
cc::ElementId scroll_latched_element_id) override;
WebLocalFrame* FocusedWebLocalFrameInWidget() const override;
- void SetCompositorHosts(cc::LayerTreeHost*, cc::AnimationHost*) override;
void ApplyViewportChangesForTesting(
const ApplyViewportChangesArgs& args) override;
void NotifySwapAndPresentationTime(
WebReportTimeCallback swap_callback,
WebReportTimeCallback presentation_callback) override;
+ scheduler::WebRenderWidgetSchedulingState* RendererWidgetSchedulingState()
+ override;
// Called when a drag-n-drop operation should begin.
void StartDragging(network::mojom::ReferrerPolicy,
@@ -159,23 +165,53 @@ class CORE_EXPORT WebFrameWidgetBase
static bool IgnoreInputEvents() { return ignore_input_events_; }
// WebWidget methods.
+ cc::LayerTreeHost* InitializeCompositing(
+ cc::TaskGraphRunner* task_graph_runner,
+ const cc::LayerTreeSettings& settings,
+ std::unique_ptr<cc::UkmRecorderFactory> ukm_recorder_factory) override;
+ void Close(scoped_refptr<base::SingleThreadTaskRunner> cleanup_runner,
+ base::OnceCallback<void()> cleanup_task) override;
void DidAcquirePointerLock() override;
void DidNotAcquirePointerLock() override;
void DidLosePointerLock() override;
void ShowContextMenu(WebMenuSourceType) override;
- void BeginFrame(base::TimeTicks frame_time) final;
void SetCompositorVisible(bool visible) override;
- void UpdateVisualState() override;
- void WillBeginCompositorFrame() final;
+ void SetDisplayMode(mojom::blink::DisplayMode) override;
+ void SetCursor(const ui::Cursor& cursor) override;
// WidgetBaseClient methods.
void DispatchRafAlignedInput(base::TimeTicks frame_time) override;
void RecordTimeToFirstActivePaint(base::TimeDelta duration) override;
+ void EndCommitCompositorFrame(base::TimeTicks commit_start_time) override;
+ void DidCommitAndDrawCompositorFrame() override;
+ void OnDeferMainFrameUpdatesChanged(bool defer) override;
+ void OnDeferCommitsChanged(bool defer) override;
+ void RequestNewLayerTreeFrameSink(
+ LayerTreeFrameSinkCallback callback) override;
+ void DidCompletePageScaleAnimation() override;
+ void DidBeginMainFrame() override;
+ void WillBeginMainFrame() override;
// mojom::blink::FrameWidget methods.
void DragSourceSystemDragEnded() override;
void SetBackgroundOpaque(bool opaque) override;
+ // Sets the inherited effective touch action on an out-of-process iframe.
+ void SetInheritedEffectiveTouchActionForSubFrame(
+ WebTouchAction touch_action) override {}
+
+ // Toggles render throttling for an out-of-process iframe. Local frames are
+ // throttled based on their visibility in the viewport, but remote frames
+ // have to have throttling information propagated from parent to child
+ // across processes.
+ void UpdateRenderThrottlingStatusForSubFrame(
+ bool is_throttled,
+ bool subtree_throttled) override {}
+
+ // Sets the inert bit on an out-of-process iframe, causing it to ignore
+ // input.
+ void SetIsInertForSubFrame(bool inert) override {}
+
// Called when the FrameView for this Widget's local root is created.
virtual void DidCreateLocalRootView() {}
@@ -265,6 +301,9 @@ class CORE_EXPORT WebFrameWidgetBase
// the page is shutting down, but will be valid at all other times.
Page* GetPage() const;
+ const mojo::AssociatedRemote<mojom::blink::FrameWidgetHost>&
+ GetAssociatedFrameWidgetHost() const;
+
// Helper function to process events while pointer locked.
void PointerLockMouseEvent(const WebCoalescedInputEvent&);
@@ -296,6 +335,8 @@ class CORE_EXPORT WebFrameWidgetBase
void CancelDrag();
void RequestAnimationAfterDelayTimerFired(TimerBase*);
+ static bool ignore_input_events_;
+
WebWidgetClient* client_;
// WebFrameWidget is associated with a subtree of the frame tree,
@@ -303,7 +344,7 @@ class CORE_EXPORT WebFrameWidgetBase
// points to the root of that subtree.
Member<WebLocalFrameImpl> local_root_;
- static bool ignore_input_events_;
+ mojom::blink::DisplayMode display_mode_;
// This is owned by the LayerTreeHostImpl, and should only be used on the
// compositor thread, so we keep the TaskRunner where you post tasks to
@@ -325,7 +366,12 @@ class CORE_EXPORT WebFrameWidgetBase
mojo::AssociatedRemote<mojom::blink::FrameWidgetHost> frame_widget_host_;
mojo::AssociatedReceiver<mojom::blink::FrameWidget> receiver_;
+ // Different consumers in the browser process makes different assumptions, so
+ // must always send the first IPC regardless of value.
+ base::Optional<bool> has_touch_handlers_;
+
friend class WebViewImpl;
+ friend class ReportTimeSwapPromise;
};
template <>
diff --git a/chromium/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc b/chromium/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc
index dd8f1641e16..12628872674 100644
--- a/chromium/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc
+++ b/chromium/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc
@@ -37,6 +37,7 @@
#include "base/optional.h"
#include "build/build_config.h"
#include "cc/layers/picture_layer.h"
+#include "third_party/blink/public/mojom/frame/intrinsic_sizing_info.mojom-blink.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/web/web_autofill_client.h"
#include "third_party/blink/public/web/web_element.h"
@@ -194,10 +195,12 @@ void WebFrameWidgetImpl::Trace(Visitor* visitor) {
// WebWidget ------------------------------------------------------------------
-void WebFrameWidgetImpl::Close() {
+void WebFrameWidgetImpl::Close(
+ scoped_refptr<base::SingleThreadTaskRunner> cleanup_runner,
+ base::OnceCallback<void()> cleanup_task) {
GetPage()->WillCloseAnimationHost(LocalRootImpl()->GetFrame()->View());
- WebFrameWidgetBase::Close();
+ WebFrameWidgetBase::Close(std::move(cleanup_runner), std::move(cleanup_task));
self_keep_alive_.Clear();
}
@@ -310,8 +313,9 @@ void WebFrameWidgetImpl::BeginMainFrame(base::TimeTicks last_frame_time) {
GetPage()->GetValidationMessageClient().LayoutOverlay();
}
-void WebFrameWidgetImpl::DidBeginFrame() {
+void WebFrameWidgetImpl::DidBeginMainFrame() {
DCHECK(LocalRootImpl()->GetFrame());
+ WebFrameWidgetBase::DidBeginMainFrame();
PageWidgetDelegate::DidBeginFrame(*LocalRootImpl()->GetFrame());
}
@@ -393,6 +397,7 @@ void WebFrameWidgetImpl::UpdateLifecycle(WebLifecycleUpdate requested_update,
LocalRootImpl()->GetFrame()->GetDocument()->Lifecycle());
PageWidgetDelegate::UpdateLifecycle(*GetPage(), *LocalRootImpl()->GetFrame(),
requested_update, reason);
+ View()->UpdatePagePopup();
}
void WebFrameWidgetImpl::ThemeChanged() {
@@ -402,7 +407,7 @@ void WebFrameWidgetImpl::ThemeChanged() {
view->InvalidateRect(damaged_rect);
}
-WebHitTestResult WebFrameWidgetImpl::HitTestResultAt(const gfx::Point& point) {
+WebHitTestResult WebFrameWidgetImpl::HitTestResultAt(const gfx::PointF& point) {
return CoreHitTestResultAt(point);
}
@@ -474,25 +479,25 @@ WebInputEventResult WebFrameWidgetImpl::HandleInputEvent(
HTMLPlugInElement* target = mouse_capture_element_;
// Not all platforms call mouseCaptureLost() directly.
- if (input_event.GetType() == WebInputEvent::kMouseUp)
+ if (input_event.GetType() == WebInputEvent::Type::kMouseUp)
MouseCaptureLost();
AtomicString event_type;
switch (input_event.GetType()) {
- case WebInputEvent::kMouseEnter:
+ case WebInputEvent::Type::kMouseEnter:
event_type = event_type_names::kMouseover;
break;
- case WebInputEvent::kMouseMove:
+ case WebInputEvent::Type::kMouseMove:
event_type = event_type_names::kMousemove;
break;
- case WebInputEvent::kMouseLeave:
+ case WebInputEvent::Type::kMouseLeave:
event_type = event_type_names::kMouseout;
break;
- case WebInputEvent::kMouseDown:
+ case WebInputEvent::Type::kMouseDown:
event_type = event_type_names::kMousedown;
LocalFrame::NotifyUserActivation(target->GetDocument().GetFrame());
break;
- case WebInputEvent::kMouseUp:
+ case WebInputEvent::Type::kMouseUp:
event_type = event_type_names::kMouseup;
break;
default:
@@ -523,11 +528,6 @@ void WebFrameWidgetImpl::SetCursorVisibilityState(bool is_visible) {
GetPage()->SetIsCursorVisible(is_visible);
}
-void WebFrameWidgetImpl::OnFallbackCursorModeToggled(bool is_on) {
- // TODO(crbug.com/944575) Should support oopif.
- NOTREACHED();
-}
-
void WebFrameWidgetImpl::DidDetachLocalFrameTree() {}
WebInputMethodController*
@@ -554,13 +554,9 @@ bool WebFrameWidgetImpl::ScrollFocusedEditableElementIntoView() {
}
void WebFrameWidgetImpl::IntrinsicSizingInfoChanged(
- const IntrinsicSizingInfo& sizing_info) {
- WebIntrinsicSizingInfo web_sizing_info;
- web_sizing_info.size = sizing_info.size;
- web_sizing_info.aspect_ratio = sizing_info.aspect_ratio;
- web_sizing_info.has_width = sizing_info.has_width;
- web_sizing_info.has_height = sizing_info.has_height;
- Client()->IntrinsicSizingInfoChanged(web_sizing_info);
+ mojom::blink::IntrinsicSizingInfoPtr sizing_info) {
+ GetAssociatedFrameWidgetHost()->IntrinsicSizingInfoChanged(
+ std::move(sizing_info));
}
void WebFrameWidgetImpl::MouseCaptureLost() {
@@ -646,21 +642,22 @@ void WebFrameWidgetImpl::SetRemoteViewportIntersection(
intersection_state);
}
-void WebFrameWidgetImpl::SetIsInert(bool inert) {
+void WebFrameWidgetImpl::SetIsInertForSubFrame(bool inert) {
DCHECK(LocalRootImpl()->Parent());
DCHECK(LocalRootImpl()->Parent()->IsWebRemoteFrame());
LocalRootImpl()->GetFrame()->SetIsInert(inert);
}
-void WebFrameWidgetImpl::SetInheritedEffectiveTouchAction(
+void WebFrameWidgetImpl::SetInheritedEffectiveTouchActionForSubFrame(
TouchAction touch_action) {
DCHECK(LocalRootImpl()->Parent());
DCHECK(LocalRootImpl()->Parent()->IsWebRemoteFrame());
LocalRootImpl()->GetFrame()->SetInheritedEffectiveTouchAction(touch_action);
}
-void WebFrameWidgetImpl::UpdateRenderThrottlingStatus(bool is_throttled,
- bool subtree_throttled) {
+void WebFrameWidgetImpl::UpdateRenderThrottlingStatusForSubFrame(
+ bool is_throttled,
+ bool subtree_throttled) {
DCHECK(LocalRootImpl()->Parent());
DCHECK(LocalRootImpl()->Parent()->IsWebRemoteFrame());
LocalRootImpl()->GetFrameView()->UpdateRenderThrottlingStatus(
@@ -745,12 +742,10 @@ void WebFrameWidgetImpl::MouseContextMenu(const WebMouseEvent& event) {
WebMouseEvent transformed_event =
TransformWebMouseEvent(LocalRootImpl()->GetFrameView(), event);
transformed_event.menu_source_type = kMenuSourceMouse;
- IntPoint position_in_root_frame =
- FlooredIntPoint(transformed_event.PositionInRootFrame());
// Find the right target frame. See issue 1186900.
- HitTestResult result =
- HitTestResultForRootFramePos(PhysicalOffset(position_in_root_frame));
+ HitTestResult result = HitTestResultForRootFramePos(
+ FloatPoint(transformed_event.PositionInRootFrame()));
Frame* target_frame;
if (result.InnerNodeOrImageMapImage())
target_frame = result.InnerNodeOrImageMapImage()->GetDocument().GetFrame();
@@ -805,12 +800,12 @@ WebInputEventResult WebFrameWidgetImpl::HandleGestureEvent(
WebViewImpl* view_impl = View();
switch (event.GetType()) {
- case WebInputEvent::kGestureScrollBegin:
- case WebInputEvent::kGestureScrollEnd:
- case WebInputEvent::kGestureScrollUpdate:
- case WebInputEvent::kGestureTap:
- case WebInputEvent::kGestureTapUnconfirmed:
- case WebInputEvent::kGestureTapDown:
+ case WebInputEvent::Type::kGestureScrollBegin:
+ case WebInputEvent::Type::kGestureScrollEnd:
+ case WebInputEvent::Type::kGestureScrollUpdate:
+ case WebInputEvent::Type::kGestureTap:
+ case WebInputEvent::Type::kGestureTapUnconfirmed:
+ case WebInputEvent::Type::kGestureTapDown:
// Touch pinch zoom and scroll on the page (outside of a popup) must hide
// the popup. In case of a touch scroll or pinch zoom, this function is
// called with GestureTapDown rather than a GSB/GSU/GSE or GPB/GPU/GPE.
@@ -822,10 +817,10 @@ WebInputEventResult WebFrameWidgetImpl::HandleGestureEvent(
// case to do so.
View()->CancelPagePopup();
break;
- case WebInputEvent::kGestureTapCancel:
- case WebInputEvent::kGestureShowPress:
+ case WebInputEvent::Type::kGestureTapCancel:
+ case WebInputEvent::Type::kGestureShowPress:
break;
- case WebInputEvent::kGestureDoubleTap:
+ case WebInputEvent::Type::kGestureDoubleTap:
if (GetPage()->GetChromeClient().DoubleTapToZoomEnabled() &&
view_impl->MinimumPageScaleFactor() !=
view_impl->MaximumPageScaleFactor()) {
@@ -834,22 +829,21 @@ WebInputEventResult WebFrameWidgetImpl::HandleGestureEvent(
TransformWebGestureEvent(frame->View(), event);
IntPoint pos_in_local_frame_root =
FlooredIntPoint(scaled_event.PositionInRootFrame());
- WebRect block_bounds =
- ComputeBlockBound(pos_in_local_frame_root, false);
+ auto block_bounds =
+ gfx::Rect(ComputeBlockBound(pos_in_local_frame_root, false));
// This sends the tap point and bounds to the main frame renderer via
// the browser, where their coordinates will be transformed into the
// main frame's coordinate space.
- Client()->AnimateDoubleTapZoomInMainFrame(pos_in_local_frame_root,
- block_bounds);
+ GetAssociatedFrameWidgetHost()->AnimateDoubleTapZoomInMainFrame(
+ pos_in_local_frame_root, block_bounds);
}
event_result = WebInputEventResult::kHandledSystem;
Client()->DidHandleGestureEvent(event, event_cancelled);
return event_result;
- break;
- case WebInputEvent::kGestureTwoFingerTap:
- case WebInputEvent::kGestureLongPress:
- case WebInputEvent::kGestureLongTap:
+ case WebInputEvent::Type::kGestureTwoFingerTap:
+ case WebInputEvent::Type::kGestureLongPress:
+ case WebInputEvent::Type::kGestureLongTap:
GetPage()->GetContextMenuController().ClearContextMenu();
maybe_context_menu_scope.emplace();
break;
@@ -873,9 +867,9 @@ LocalFrameView* WebFrameWidgetImpl::GetLocalFrameViewForAnimationScrolling() {
WebInputEventResult WebFrameWidgetImpl::HandleKeyEvent(
const WebKeyboardEvent& event) {
- DCHECK((event.GetType() == WebInputEvent::kRawKeyDown) ||
- (event.GetType() == WebInputEvent::kKeyDown) ||
- (event.GetType() == WebInputEvent::kKeyUp));
+ DCHECK((event.GetType() == WebInputEvent::Type::kRawKeyDown) ||
+ (event.GetType() == WebInputEvent::Type::kKeyDown) ||
+ (event.GetType() == WebInputEvent::Type::kKeyUp));
// Please refer to the comments explaining the m_suppressNextKeypressEvent
// member.
@@ -890,7 +884,7 @@ WebInputEventResult WebFrameWidgetImpl::HandleKeyEvent(
scoped_refptr<WebPagePopupImpl> page_popup = View()->GetPagePopup();
if (page_popup) {
page_popup->HandleKeyEvent(event);
- if (event.GetType() == WebInputEvent::kRawKeyDown) {
+ if (event.GetType() == WebInputEvent::Type::kRawKeyDown) {
suppress_next_keypress_event_ = true;
}
return WebInputEventResult::kHandledSystem;
@@ -902,7 +896,7 @@ WebInputEventResult WebFrameWidgetImpl::HandleKeyEvent(
WebInputEventResult result = frame->GetEventHandler().KeyEvent(event);
if (result != WebInputEventResult::kNotHandled) {
- if (WebInputEvent::kRawKeyDown == event.GetType()) {
+ if (WebInputEvent::Type::kRawKeyDown == event.GetType()) {
// Suppress the next keypress event unless the focused node is a plugin
// node. (Flash needs these keypress events to handle non-US keyboards.)
Element* element = FocusedElement();
@@ -916,12 +910,12 @@ WebInputEventResult WebFrameWidgetImpl::HandleKeyEvent(
#if !defined(OS_MACOSX)
const WebInputEvent::Type kContextMenuKeyTriggeringEventType =
#if defined(OS_WIN)
- WebInputEvent::kKeyUp;
+ WebInputEvent::Type::kKeyUp;
#else
- WebInputEvent::kRawKeyDown;
+ WebInputEvent::Type::kRawKeyDown;
#endif
const WebInputEvent::Type kShiftF10TriggeringEventType =
- WebInputEvent::kRawKeyDown;
+ WebInputEvent::Type::kRawKeyDown;
bool is_unmodified_menu_key =
!(event.GetModifiers() & WebInputEvent::kInputModifiers) &&
@@ -942,7 +936,7 @@ WebInputEventResult WebFrameWidgetImpl::HandleKeyEvent(
WebInputEventResult WebFrameWidgetImpl::HandleCharEvent(
const WebKeyboardEvent& event) {
- DCHECK_EQ(event.GetType(), WebInputEvent::kChar);
+ DCHECK_EQ(event.GetType(), WebInputEvent::Type::kChar);
// Please refer to the comments explaining the m_suppressNextKeypressEvent
// member. The m_suppressNextKeypressEvent is set if the KeyDown is
@@ -1031,23 +1025,24 @@ void WebFrameWidgetImpl::SetRootLayer(scoped_refptr<cc::Layer> layer) {
}
HitTestResult WebFrameWidgetImpl::CoreHitTestResultAt(
- const gfx::Point& point_in_viewport) {
+ const gfx::PointF& point_in_viewport) {
DocumentLifecycle::AllowThrottlingScope throttling_scope(
LocalRootImpl()->GetFrame()->GetDocument()->Lifecycle());
LocalFrameView* view = LocalRootImpl()->GetFrameView();
- PhysicalOffset point_in_root_frame(
- view->ViewportToFrame(IntPoint(point_in_viewport)));
+ FloatPoint point_in_root_frame(
+ view->ViewportToFrame(FloatPoint(point_in_viewport)));
return HitTestResultForRootFramePos(point_in_root_frame);
}
void WebFrameWidgetImpl::ZoomToFindInPageRect(
const WebRect& rect_in_root_frame) {
- Client()->ZoomToFindInPageRectInMainFrame(rect_in_root_frame);
+ GetAssociatedFrameWidgetHost()->ZoomToFindInPageRectInMainFrame(
+ gfx::Rect(rect_in_root_frame));
}
HitTestResult WebFrameWidgetImpl::HitTestResultForRootFramePos(
- const PhysicalOffset& pos_in_root_frame) {
- PhysicalOffset doc_point =
+ const FloatPoint& pos_in_root_frame) {
+ FloatPoint doc_point =
LocalRootImpl()->GetFrame()->View()->ConvertFromRootFrame(
pos_in_root_frame);
HitTestLocation location(doc_point);
diff --git a/chromium/third_party/blink/renderer/core/frame/web_frame_widget_impl.h b/chromium/third_party/blink/renderer/core/frame/web_frame_widget_impl.h
index eb9c8bb7208..494c1d3f25e 100644
--- a/chromium/third_party/blink/renderer/core/frame/web_frame_widget_impl.h
+++ b/chromium/third_party/blink/renderer/core/frame/web_frame_widget_impl.h
@@ -37,8 +37,8 @@
#include "base/optional.h"
#include "base/single_thread_task_runner.h"
#include "base/util/type_safety/pass_key.h"
+#include "third_party/blink/public/common/input/web_coalesced_input_event.h"
#include "third_party/blink/public/mojom/scroll/scroll_into_view_params.mojom-blink-forward.h"
-#include "third_party/blink/public/platform/web_coalesced_input_event.h"
#include "third_party/blink/public/platform/web_size.h"
#include "third_party/blink/public/web/web_input_method_controller.h"
#include "third_party/blink/renderer/core/frame/web_frame_widget_base.h"
@@ -84,39 +84,28 @@ class WebFrameWidgetImpl final : public WebFrameWidgetBase,
~WebFrameWidgetImpl() override;
// WebWidget functions:
- void Close() override;
+ void Close(scoped_refptr<base::SingleThreadTaskRunner> cleanup_runner,
+ base::OnceCallback<void()> cleanup_task) override;
WebSize Size() override;
void Resize(const WebSize&) override;
void DidEnterFullscreen() override;
void DidExitFullscreen() override;
- void DidBeginFrame() override;
- void BeginUpdateLayers() override;
- void EndUpdateLayers() override;
- void BeginCommitCompositorFrame() override;
- void EndCommitCompositorFrame(base::TimeTicks commit_start_time) override;
- void RecordStartOfFrameMetrics() override;
- void RecordEndOfFrameMetrics(
- base::TimeTicks,
- cc::ActiveFrameSequenceTrackers trackers) override;
- std::unique_ptr<cc::BeginMainFrameMetrics> GetBeginMainFrameMetrics()
- override;
void UpdateLifecycle(WebLifecycleUpdate requested_update,
DocumentUpdateReason reason) override;
void ThemeChanged() override;
- WebHitTestResult HitTestResultAt(const gfx::Point&) override;
+ WebHitTestResult HitTestResultAt(const gfx::PointF&) override;
WebInputEventResult DispatchBufferedTouchEvents() override;
WebInputEventResult HandleInputEvent(const WebCoalescedInputEvent&) override;
void SetCursorVisibilityState(bool is_visible) override;
- void OnFallbackCursorModeToggled(bool is_on) override;
void MouseCaptureLost() override;
void SetFocus(bool enable) override;
bool SelectionBounds(WebRect& anchor, WebRect& focus) const override;
void SetRemoteViewportIntersection(const ViewportIntersectionState&) override;
- void SetIsInert(bool) override;
- void SetInheritedEffectiveTouchAction(TouchAction) override;
- void UpdateRenderThrottlingStatus(bool is_throttled,
- bool subtree_throttled) override;
+ void SetIsInertForSubFrame(bool) override;
+ void SetInheritedEffectiveTouchActionForSubFrame(TouchAction) override;
+ void UpdateRenderThrottlingStatusForSubFrame(bool is_throttled,
+ bool subtree_throttled) override;
WebURL GetURLForDebugTrace() override;
// WebFrameWidget implementation.
@@ -133,9 +122,10 @@ class WebFrameWidgetImpl final : public WebFrameWidgetBase,
// WebFrameWidgetBase overrides:
bool ForSubframe() const override { return true; }
- void IntrinsicSizingInfoChanged(const IntrinsicSizingInfo&) override;
+ void IntrinsicSizingInfoChanged(
+ mojom::blink::IntrinsicSizingInfoPtr) override;
void DidCreateLocalRootView() override;
- HitTestResult CoreHitTestResultAt(const gfx::Point&) override;
+ HitTestResult CoreHitTestResultAt(const gfx::PointF&) override;
void ZoomToFindInPageRect(const WebRect& rect_in_root_frame) override;
// FrameWidget overrides:
@@ -144,6 +134,17 @@ class WebFrameWidgetImpl final : public WebFrameWidgetBase,
// WidgetBaseClient overrides:
void BeginMainFrame(base::TimeTicks last_frame_time) override;
void SetSuppressFrameRequestsWorkaroundFor704763Only(bool) final;
+ void RecordStartOfFrameMetrics() override;
+ void RecordEndOfFrameMetrics(
+ base::TimeTicks,
+ cc::ActiveFrameSequenceTrackers trackers) override;
+ std::unique_ptr<cc::BeginMainFrameMetrics> GetBeginMainFrameMetrics()
+ override;
+ void BeginUpdateLayers() override;
+ void EndUpdateLayers() override;
+ void BeginCommitCompositorFrame() override;
+ void EndCommitCompositorFrame(base::TimeTicks commit_start_time) override;
+ void DidBeginMainFrame() override;
void UpdateMainFrameLayoutSize();
@@ -157,7 +158,7 @@ class WebFrameWidgetImpl final : public WebFrameWidgetBase,
// Perform a hit test for a point relative to the root frame of the page.
HitTestResult HitTestResultForRootFramePos(
- const PhysicalOffset& pos_in_root_frame);
+ const FloatPoint& pos_in_root_frame);
void UpdateLayerTreeViewport();
diff --git a/chromium/third_party/blink/renderer/core/frame/web_local_frame_impl.cc b/chromium/third_party/blink/renderer/core/frame/web_local_frame_impl.cc
index 2660078b0ed..64803c9f6c9 100644
--- a/chromium/third_party/blink/renderer/core/frame/web_local_frame_impl.cc
+++ b/chromium/third_party/blink/renderer/core/frame/web_local_frame_impl.cc
@@ -95,9 +95,13 @@
#include "build/build_config.h"
#include "mojo/public/cpp/bindings/pending_associated_receiver.h"
#include "mojo/public/cpp/bindings/pending_associated_remote.h"
-#include "third_party/blink/public/common/frame/frame_owner_element_type.h"
+#include "services/network/public/cpp/web_sandbox_flags.h"
+#include "services/network/public/mojom/web_sandbox_flags.mojom-blink.h"
+#include "third_party/blink/public/mojom/devtools/inspector_issue.mojom-blink.h"
#include "third_party/blink/public/mojom/feature_policy/feature_policy.mojom-blink.h"
+#include "third_party/blink/public/mojom/frame/frame_owner_element_type.mojom-blink.h"
#include "third_party/blink/public/mojom/frame/media_player_action.mojom-blink.h"
+#include "third_party/blink/public/mojom/frame/tree_scope_type.mojom-blink.h"
#include "third_party/blink/public/platform/interface_registry.h"
#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/public/platform/web_double_size.h"
@@ -115,7 +119,6 @@
#include "third_party/blink/public/web/web_console_message.h"
#include "third_party/blink/public/web/web_content_capture_client.h"
#include "third_party/blink/public/web/web_document.h"
-#include "third_party/blink/public/web/web_dom_message_event.h"
#include "third_party/blink/public/web/web_form_element.h"
#include "third_party/blink/public/web/web_frame_owner_properties.h"
#include "third_party/blink/public/web/web_history_item.h"
@@ -131,7 +134,6 @@
#include "third_party/blink/public/web/web_range.h"
#include "third_party/blink/public/web/web_script_source.h"
#include "third_party/blink/public/web/web_serialized_script_value.h"
-#include "third_party/blink/public/web/web_tree_scope_type.h"
#include "third_party/blink/renderer/bindings/core/v8/binding_security.h"
#include "third_party/blink/renderer/bindings/core/v8/isolated_world_csp.h"
#include "third_party/blink/renderer/bindings/core/v8/sanitize_script_errors.h"
@@ -142,6 +144,7 @@
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_gc_controller.h"
#include "third_party/blink/renderer/core/clipboard/clipboard_utilities.h"
+#include "third_party/blink/renderer/core/core_initializer.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/icon_url.h"
#include "third_party/blink/renderer/core/dom/node.h"
@@ -184,7 +187,6 @@
#include "third_party/blink/renderer/core/frame/pausable_script_executor.h"
#include "third_party/blink/renderer/core/frame/remote_frame.h"
#include "third_party/blink/renderer/core/frame/remote_frame_owner.h"
-#include "third_party/blink/renderer/core/frame/screen_orientation_controller.h"
#include "third_party/blink/renderer/core/frame/settings.h"
#include "third_party/blink/renderer/core/frame/smart_clip.h"
#include "third_party/blink/renderer/core/frame/visual_viewport.h"
@@ -210,7 +212,6 @@
#include "third_party/blink/renderer/core/input/context_menu_allowed_scope.h"
#include "third_party/blink/renderer/core/input/event_handler.h"
#include "third_party/blink/renderer/core/inspector/console_message.h"
-#include "third_party/blink/renderer/core/inspector/inspector_issue.h"
#include "third_party/blink/renderer/core/inspector/main_thread_debugger.h"
#include "third_party/blink/renderer/core/layout/hit_test_result.h"
#include "third_party/blink/renderer/core/layout/layout_embedded_content.h"
@@ -254,6 +255,7 @@
#include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_request.h"
#include "third_party/blink/renderer/platform/scheduler/public/frame_scheduler.h"
+#include "third_party/blink/renderer/platform/scheduler/public/scheduling_policy.h"
#include "third_party/blink/renderer/platform/text/text_direction.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
#include "third_party/blink/renderer/platform/weborigin/scheme_registry.h"
@@ -791,10 +793,8 @@ void WebLocalFrameImpl::SetIsolatedWorldInfo(int32_t world_id,
info.security_origin.Get()
? info.security_origin.Get()
->IsolatedCopy()
- ->GetOriginForAgentCluster(GetFrame()
- ->GetDocument()
- ->ToExecutionContext()
- ->GetAgentClusterID())
+ ->GetOriginForAgentCluster(
+ GetFrame()->DomWindow()->GetAgentClusterID())
: nullptr;
CHECK(info.content_security_policy.IsNull() || security_origin);
@@ -833,7 +833,7 @@ void WebLocalFrameImpl::CollectGarbageForTesting() {
return;
if (!GetFrame()->GetSettings()->GetScriptEnabled())
return;
- V8GCController::CollectAllGarbageForTesting(v8::Isolate::GetCurrent());
+ ThreadState::Current()->CollectAllGarbageForTesting();
}
v8::Local<v8::Value> WebLocalFrameImpl::ExecuteScriptAndReturnValue(
@@ -908,7 +908,7 @@ v8::MaybeLocal<v8::Value> WebLocalFrameImpl::CallFunctionEvenIfScriptDisabled(
v8::Local<v8::Value> argv[]) {
DCHECK(GetFrame());
return V8ScriptRunner::CallFunction(
- function, GetFrame()->GetDocument()->ToExecutionContext(), receiver, argc,
+ function, GetFrame()->DomWindow(), receiver, argc,
static_cast<v8::Local<v8::Value>*>(argv), ToIsolate(GetFrame()));
}
@@ -969,14 +969,6 @@ void WebLocalFrameImpl::StartNavigation(const WebURLRequest& request) {
WebFrameLoadType::kStandard);
}
-void WebLocalFrameImpl::StopLoading() {
- if (!GetFrame())
- return;
- // FIXME: Figure out what we should really do here. It seems like a bug
- // that FrameLoader::stopLoading doesn't call stopAllLoaders.
- GetFrame()->Loader().StopAllLoaders();
-}
-
WebDocumentLoader* WebLocalFrameImpl::GetDocumentLoader() const {
DCHECK(GetFrame());
return DocumentLoaderForDocLoader(GetFrame()->Loader().GetDocumentLoader());
@@ -1006,7 +998,11 @@ void WebLocalFrameImpl::SetReferrerForRequest(WebURLRequest& request,
WebAssociatedURLLoader* WebLocalFrameImpl::CreateAssociatedURLLoader(
const WebAssociatedURLLoaderOptions& options) {
- return new WebAssociatedURLLoaderImpl(GetFrame()->GetDocument(), options);
+ return new WebAssociatedURLLoaderImpl(GetFrame()->DomWindow(), options);
+}
+
+void WebLocalFrameImpl::StopLoading() {
+ GetFrame()->StopLoading();
}
void WebLocalFrameImpl::ReplaceSelection(const WebString& text) {
@@ -1056,19 +1052,6 @@ bool WebLocalFrameImpl::FirstRectForCharacterRange(
return true;
}
-size_t WebLocalFrameImpl::CharacterIndexForPoint(
- const gfx::Point& point_in_viewport) const {
- if (!GetFrame())
- return kNotFound;
-
- HitTestLocation location(
- GetFrame()->View()->ViewportToFrame(IntPoint(point_in_viewport)));
- HitTestResult result = GetFrame()->GetEventHandler().HitTestResultAtLocation(
- location, HitTestRequest::kReadOnly | HitTestRequest::kActive);
- return GetFrame()->Selection().CharacterIndexForPoint(
- result.RoundedPointInInnerNodeFrame());
-}
-
bool WebLocalFrameImpl::ExecuteCommand(const WebString& name) {
DCHECK(GetFrame());
@@ -1491,6 +1474,13 @@ void WebLocalFrameImpl::DispatchBeforePrintEvent() {
is_in_printing_ = true;
#endif
+ // Disable BackForwardCache when printing API is used for now. When the page
+ // navigates with BackForwardCache, we currently do not close the printing
+ // popup properly.
+ GetFrame()->GetFrameScheduler()->RegisterStickyFeature(
+ blink::SchedulingPolicy::Feature::kPrinting,
+ {blink::SchedulingPolicy::RecordMetricsForBackForwardCache()});
+
GetFrame()->GetDocument()->SetPrinting(Document::kBeforePrinting);
DispatchPrintEventRecursively(event_type_names::kBeforeprint);
}
@@ -1612,16 +1602,10 @@ PageSizeType WebLocalFrameImpl::GetPageSizeType(int page_index) {
return GetFrame()->GetDocument()->StyleForPage(page_index)->GetPageSizeType();
}
-void WebLocalFrameImpl::PageSizeAndMarginsInPixels(int page_index,
- WebDoubleSize& page_size,
- int& margin_top,
- int& margin_right,
- int& margin_bottom,
- int& margin_left) {
- DoubleSize size = page_size;
- GetFrame()->GetDocument()->PageSizeAndMarginsInPixels(
- page_index, size, margin_top, margin_right, margin_bottom, margin_left);
- page_size = size;
+void WebLocalFrameImpl::GetPageDescription(
+ int page_index,
+ WebPrintPageDescription* description) {
+ GetFrame()->GetDocument()->GetPageDescription(page_index, description);
}
void WebLocalFrameImpl::PrintPagesForTesting(
@@ -1640,42 +1624,52 @@ WebRect WebLocalFrameImpl::GetSelectionBoundsRectForTesting() const {
: WebRect();
}
+gfx::Point WebLocalFrameImpl::GetPositionInViewportForTesting() const {
+ LocalFrameView* view = GetFrameView();
+ return view->ConvertToRootFrame(IntPoint());
+}
+
// WebLocalFrameImpl public --------------------------------------------------
WebLocalFrame* WebLocalFrame::CreateMainFrame(
WebView* web_view,
WebLocalFrameClient* client,
InterfaceRegistry* interface_registry,
+ const base::UnguessableToken& frame_token,
WebFrame* opener,
const WebString& name,
- mojom::blink::WebSandboxFlags sandbox_flags,
+ network::mojom::blink::WebSandboxFlags sandbox_flags,
const FeaturePolicy::FeatureState& opener_feature_state) {
return WebLocalFrameImpl::CreateMainFrame(
- web_view, client, interface_registry, opener, name, sandbox_flags,
- opener_feature_state);
+ web_view, client, interface_registry, frame_token, opener, name,
+ sandbox_flags, opener_feature_state);
}
WebLocalFrame* WebLocalFrame::CreateProvisional(
WebLocalFrameClient* client,
InterfaceRegistry* interface_registry,
+ const base::UnguessableToken& frame_token,
WebFrame* previous_frame,
const FramePolicy& frame_policy,
const WebString& name) {
- return WebLocalFrameImpl::CreateProvisional(
- client, interface_registry, previous_frame, frame_policy, name);
+ return WebLocalFrameImpl::CreateProvisional(client, interface_registry,
+ frame_token, previous_frame,
+ frame_policy, name);
}
WebLocalFrameImpl* WebLocalFrameImpl::CreateMainFrame(
WebView* web_view,
WebLocalFrameClient* client,
InterfaceRegistry* interface_registry,
+ const base::UnguessableToken& frame_token,
WebFrame* opener,
const WebString& name,
- mojom::blink::WebSandboxFlags sandbox_flags,
+ network::mojom::blink::WebSandboxFlags sandbox_flags,
const FeaturePolicy::FeatureState& opener_feature_state) {
auto* frame = MakeGarbageCollected<WebLocalFrameImpl>(
- util::PassKey<WebLocalFrameImpl>(), WebTreeScopeType::kDocument, client,
- interface_registry);
+ util::PassKey<WebLocalFrameImpl>(),
+ mojom::blink::TreeScopeType::kDocument, client, interface_registry,
+ frame_token);
frame->SetOpener(opener);
Page& page = *static_cast<WebViewImpl*>(web_view)->GetPage();
DCHECK(!page.MainFrame());
@@ -1689,6 +1683,7 @@ WebLocalFrameImpl* WebLocalFrameImpl::CreateMainFrame(
WebLocalFrameImpl* WebLocalFrameImpl::CreateProvisional(
WebLocalFrameClient* client,
blink::InterfaceRegistry* interface_registry,
+ const base::UnguessableToken& frame_token,
WebFrame* previous_web_frame,
const FramePolicy& frame_policy,
const WebString& name) {
@@ -1697,13 +1692,14 @@ WebLocalFrameImpl* WebLocalFrameImpl::CreateProvisional(
DCHECK(name.IsEmpty() || name.Equals(previous_frame->Tree().GetName()));
auto* web_frame = MakeGarbageCollected<WebLocalFrameImpl>(
util::PassKey<WebLocalFrameImpl>(),
- previous_web_frame->InShadowTree() ? WebTreeScopeType::kShadow
- : WebTreeScopeType::kDocument,
- client, interface_registry);
+ previous_web_frame->InShadowTree()
+ ? mojom::blink::TreeScopeType::kShadow
+ : mojom::blink::TreeScopeType::kDocument,
+ client, interface_registry, frame_token);
web_frame->SetParent(previous_web_frame->Parent());
web_frame->SetOpener(previous_web_frame->Opener());
- mojom::blink::WebSandboxFlags sandbox_flags =
- mojom::blink::WebSandboxFlags::kNone;
+ network::mojom::blink::WebSandboxFlags sandbox_flags =
+ network::mojom::blink::WebSandboxFlags::kNone;
FeaturePolicy::FeatureState feature_state;
if (!previous_frame->Owner()) {
// Provisional main frames need to force sandbox flags. This is necessary
@@ -1743,21 +1739,24 @@ WebLocalFrameImpl* WebLocalFrameImpl::CreateProvisional(
}
WebLocalFrameImpl* WebLocalFrameImpl::CreateLocalChild(
- WebTreeScopeType scope,
+ mojom::blink::TreeScopeType scope,
WebLocalFrameClient* client,
- blink::InterfaceRegistry* interface_registry) {
+ blink::InterfaceRegistry* interface_registry,
+ const base::UnguessableToken& frame_token) {
auto* frame = MakeGarbageCollected<WebLocalFrameImpl>(
- util::PassKey<WebLocalFrameImpl>(), scope, client, interface_registry);
+ util::PassKey<WebLocalFrameImpl>(), scope, client, interface_registry,
+ frame_token);
AppendChild(frame);
return frame;
}
WebLocalFrameImpl::WebLocalFrameImpl(
util::PassKey<WebLocalFrameImpl>,
- WebTreeScopeType scope,
+ mojom::blink::TreeScopeType scope,
WebLocalFrameClient* client,
- blink::InterfaceRegistry* interface_registry)
- : WebNavigationControl(scope),
+ blink::InterfaceRegistry* interface_registry,
+ const base::UnguessableToken& frame_token)
+ : WebNavigationControl(scope, frame_token),
client_(client),
local_frame_client_(MakeGarbageCollected<LocalFrameClientImpl>(this)),
autofill_client_(nullptr),
@@ -1774,13 +1773,15 @@ WebLocalFrameImpl::WebLocalFrameImpl(
WebLocalFrameImpl::WebLocalFrameImpl(
util::PassKey<WebRemoteFrameImpl>,
- WebTreeScopeType scope,
+ mojom::blink::TreeScopeType scope,
WebLocalFrameClient* client,
- blink::InterfaceRegistry* interface_registry)
+ blink::InterfaceRegistry* interface_registry,
+ const base::UnguessableToken& frame_token)
: WebLocalFrameImpl(util::PassKey<WebLocalFrameImpl>(),
scope,
client,
- interface_registry) {}
+ interface_registry,
+ frame_token) {}
WebLocalFrameImpl::~WebLocalFrameImpl() {
// The widget for the frame, if any, must have already been closed.
@@ -1808,11 +1809,11 @@ void WebLocalFrameImpl::InitializeCoreFrame(
FrameOwner* owner,
const AtomicString& name,
WindowAgentFactory* window_agent_factory,
- mojom::blink::WebSandboxFlags sandbox_flags,
+ network::mojom::blink::WebSandboxFlags sandbox_flags,
const FeaturePolicy::FeatureState& opener_feature_state) {
- SetCoreFrame(MakeGarbageCollected<LocalFrame>(local_frame_client_.Get(), page,
- owner, window_agent_factory,
- interface_registry_));
+ SetCoreFrame(MakeGarbageCollected<LocalFrame>(
+ local_frame_client_.Get(), page, owner, GetFrameToken(),
+ window_agent_factory, interface_registry_));
frame_->Tree().SetName(name);
if (RuntimeEnabledFeatures::FeaturePolicyForSandboxEnabled())
frame_->SetOpenerFeatureState(opener_feature_state);
@@ -1841,10 +1842,10 @@ LocalFrame* WebLocalFrameImpl::CreateChildFrame(
HTMLFrameOwnerElement* owner_element) {
DCHECK(client_);
TRACE_EVENT0("blink", "WebLocalFrameImpl::createChildframe");
- WebTreeScopeType scope =
+ mojom::blink::TreeScopeType scope =
GetFrame()->GetDocument() == owner_element->GetTreeScope()
- ? WebTreeScopeType::kDocument
- : WebTreeScopeType::kShadow;
+ ? mojom::blink::TreeScopeType::kDocument
+ : mojom::blink::TreeScopeType::kShadow;
WebFrameOwnerProperties owner_properties(
owner_element->BrowsingContextContainerName(),
owner_element->ScrollbarMode(), owner_element->MarginWidth(),
@@ -1881,7 +1882,7 @@ std::pair<RemoteFrame*, base::UnguessableToken> WebLocalFrameImpl::CreatePortal(
WebRemoteFrame* portal_frame;
base::UnguessableToken portal_token;
std::tie(portal_frame, portal_token) = client_->CreatePortal(
- portal_receiver.PassHandle(), portal_client.PassHandle(), portal);
+ std::move(portal_receiver), std::move(portal_client), portal);
return {To<WebRemoteFrameImpl>(portal_frame)->GetFrame(), portal_token};
}
@@ -1943,8 +1944,6 @@ void WebLocalFrameImpl::CreateFrameView() {
web_view->MaxAutoSize());
}
- GetFrame()->View()->SetDisplayMode(web_view->DisplayMode());
-
if (frame_widget_)
frame_widget_->DidCreateLocalRootView();
}
@@ -2207,8 +2206,7 @@ void WebLocalFrameImpl::SendOrientationChangeEvent() {
return;
// Screen Orientation API
- if (ScreenOrientationController::From(*GetFrame()))
- ScreenOrientationController::From(*GetFrame())->NotifyOrientationChanged();
+ CoreInitializer::GetInstance().NotifyOrientationChanged(*GetFrame());
// Legacy window.orientation API
if (RuntimeEnabledFeatures::OrientationEventEnabled() &&
@@ -2216,41 +2214,6 @@ void WebLocalFrameImpl::SendOrientationChangeEvent() {
GetFrame()->DomWindow()->SendOrientationChangeEvent();
}
-void WebLocalFrameImpl::DispatchMessageEventWithOriginCheck(
- const WebSecurityOrigin& intended_target_origin,
- const WebDOMMessageEvent& event) {
- DCHECK(!event.IsNull());
-
- MessageEvent* msg_event = static_cast<MessageEvent*>((Event*)event);
- Frame* source_frame = nullptr;
- if (msg_event->source() && msg_event->source()->ToDOMWindow())
- source_frame = msg_event->source()->ToDOMWindow()->GetFrame();
-
- // Transfer user activation state in the target's renderer when
- // |transferUserActivation| is true.
- //
- // Also do the same as an ad-hoc solution to allow the origin trial of dynamic
- // delegation of autoplay capability through postMessages. Note that we
- // skipped updating the user activation states in all other copies of the
- // frame tree in this case because this is a temporary hack.
- //
- // TODO(mustaq): Remove the ad-hoc solution when the API shape is
- // ready. crbug.com/985914
- if ((RuntimeEnabledFeatures::UserActivationPostMessageTransferEnabled() &&
- msg_event->transferUserActivation()) ||
- msg_event->allowAutoplay()) {
- GetFrame()->TransferUserActivationFrom(source_frame);
- if (msg_event->allowAutoplay())
- UseCounter::Count(GetDocument(), WebFeature::kAutoplayDynamicDelegation);
- }
-
- GetFrame()->DomWindow()->DispatchMessageEventWithOriginCheck(
- intended_target_origin.Get(), msg_event,
- std::make_unique<SourceLocation>(String(), 0, 0, nullptr),
- event.locked_agent_cluster_id() ? event.locked_agent_cluster_id().value()
- : base::UnguessableToken());
-}
-
WebNode WebLocalFrameImpl::ContextMenuNode() const {
return ContextMenuNodeInner();
}
@@ -2290,11 +2253,12 @@ void WebLocalFrameImpl::CopyImageAtForTesting(
GetFrame()->CopyImageAtViewportPoint(IntPoint(pos_in_viewport));
}
-mojom::blink::WebSandboxFlags
+network::mojom::blink::WebSandboxFlags
WebLocalFrameImpl::EffectiveSandboxFlagsForTesting() const {
if (!GetFrame())
- return mojom::blink::WebSandboxFlags::kNone;
- SandboxFlags flags = GetFrame()->Loader().EffectiveSandboxFlags();
+ return network::mojom::blink::WebSandboxFlags::kNone;
+ network::mojom::blink::WebSandboxFlags flags =
+ GetFrame()->Loader().EffectiveSandboxFlags();
if (RuntimeEnabledFeatures::FeaturePolicyForSandboxEnabled()) {
// When some of sandbox flags set in the 'sandbox' attribute are implemented
// as policies they are removed form the FrameOwner's sandbox flags to avoid
@@ -2305,13 +2269,13 @@ WebLocalFrameImpl::EffectiveSandboxFlagsForTesting() const {
// FeaturePolicy. For certain flags such as "downloads", dedicated API
// should be used (see IsAllowedToDownload()).
auto* local_owner = GetFrame()->DeprecatedLocalOwner();
- if (local_owner &&
- local_owner->OwnerType() == FrameOwnerElementType::kIframe) {
+ if (local_owner && local_owner->OwnerType() ==
+ mojom::blink::FrameOwnerElementType::kIframe) {
flags |= To<HTMLIFrameElement>(local_owner)
->sandbox_flags_converted_to_feature_policies();
}
}
- return static_cast<mojom::blink::WebSandboxFlags>(flags);
+ return flags;
}
bool WebLocalFrameImpl::IsAllowedToDownload() const {
@@ -2330,8 +2294,8 @@ bool WebLocalFrameImpl::IsAllowedToDownload() const {
GetFrame()->Owner()->GetFramePolicy().allowed_to_download;
}
return (GetFrame()->Loader().PendingEffectiveSandboxFlags() &
- mojom::blink::WebSandboxFlags::kDownloads) ==
- mojom::blink::WebSandboxFlags::kNone;
+ network::mojom::blink::WebSandboxFlags::kDownloads) ==
+ network::mojom::blink::WebSandboxFlags::kNone;
}
void WebLocalFrameImpl::UsageCountChromeLoadTimes(const WebString& metric) {
@@ -2428,6 +2392,10 @@ static String CreateMarkupInRect(LocalFrame* frame,
return CreateMarkup(end_position, start_position, create_markup_options);
}
+void WebLocalFrameImpl::SetMainFrameOverlayColor(SkColor color) {
+ GetFrame()->SetMainFrameColorOverlay(color);
+}
+
bool WebLocalFrameImpl::ShouldSuppressKeyboardForFocusedElement() {
if (!autofill_client_)
return false;
@@ -2455,8 +2423,8 @@ void WebLocalFrameImpl::OnPortalActivated(
DCHECK(!blink_data.locked_agent_cluster_id)
<< "portal activation is always cross-agent-cluster and should be "
"diagnosed early";
- MessagePortArray* ports = MessagePort::EntanglePorts(
- *window->document()->ToExecutionContext(), std::move(blink_data.ports));
+ MessagePortArray* ports =
+ MessagePort::EntanglePorts(*window, std::move(blink_data.ports));
PortalActivateEvent* event = PortalActivateEvent::Create(
frame_.Get(), portal_token, std::move(portal), std::move(portal_client),
@@ -2497,10 +2465,8 @@ void WebLocalFrameImpl::AddInspectorIssueImpl(
mojom::blink::InspectorIssueCode code) {
DCHECK(GetFrame());
auto info = mojom::blink::InspectorIssueInfo::New(
- code, mojom::blink::InspectorIssueDetails::New(),
- mojom::blink::AffectedResources::New());
- GetFrame()->GetDocument()->AddInspectorIssue(
- InspectorIssue::Create(std::move(info)));
+ code, mojom::blink::InspectorIssueDetails::New());
+ GetFrame()->AddInspectorIssue(std::move(info));
}
void WebLocalFrameImpl::SetTextCheckClient(
@@ -2546,17 +2512,16 @@ WebDevToolsAgentImpl* WebLocalFrameImpl::DevToolsAgentImpl() {
}
void WebLocalFrameImpl::BindDevToolsAgent(
- mojo::ScopedInterfaceEndpointHandle devtools_agent_host_remote,
- mojo::ScopedInterfaceEndpointHandle devtools_agent_receiver) {
+ CrossVariantMojoAssociatedRemote<
+ mojom::blink::DevToolsAgentHostInterfaceBase>
+ devtools_agent_host_remote,
+ CrossVariantMojoAssociatedReceiver<mojom::blink::DevToolsAgentInterfaceBase>
+ devtools_agent_receiver) {
WebDevToolsAgentImpl* agent = DevToolsAgentImpl();
if (!agent)
return;
- agent->BindReceiver(
- mojo::PendingAssociatedRemote<mojom::blink::DevToolsAgentHost>(
- std::move(devtools_agent_host_remote),
- mojom::blink::DevToolsAgentHost::Version_),
- mojo::PendingAssociatedReceiver<mojom::blink::DevToolsAgent>(
- std::move(devtools_agent_receiver)));
+ agent->BindReceiver(std::move(devtools_agent_host_remote),
+ std::move(devtools_agent_receiver));
}
void WebLocalFrameImpl::SetLifecycleState(mojom::FrameLifecycleState state) {
diff --git a/chromium/third_party/blink/renderer/core/frame/web_local_frame_impl.h b/chromium/third_party/blink/renderer/core/frame/web_local_frame_impl.h
index a8d2023b6b3..5ee856c20dc 100644
--- a/chromium/third_party/blink/renderer/core/frame/web_local_frame_impl.h
+++ b/chromium/third_party/blink/renderer/core/frame/web_local_frame_impl.h
@@ -39,10 +39,12 @@
#include "base/util/type_safety/pass_key.h"
#include "mojo/public/cpp/bindings/pending_associated_receiver.h"
#include "mojo/public/cpp/bindings/pending_associated_remote.h"
+#include "services/network/public/mojom/web_sandbox_flags.mojom-blink.h"
#include "third_party/blink/public/mojom/ad_tagging/ad_frame.mojom-blink-forward.h"
#include "third_party/blink/public/mojom/devtools/devtools_agent.mojom-blink-forward.h"
#include "third_party/blink/public/mojom/frame/find_in_page.mojom-blink-forward.h"
#include "third_party/blink/public/mojom/frame/lifecycle.mojom-blink-forward.h"
+#include "third_party/blink/public/mojom/frame/tree_scope_type.mojom-blink.h"
#include "third_party/blink/public/mojom/portal/portal.mojom-blink-forward.h"
#include "third_party/blink/public/platform/web_file_system_type.h"
#include "third_party/blink/public/web/web_history_commit_type.h"
@@ -98,13 +100,14 @@ class CORE_EXPORT WebLocalFrameImpl final
void Close() override;
WebView* View() const override;
v8::Local<v8::Object> GlobalProxy() const override;
- void StopLoading() override;
bool IsLoading() const override;
// WebLocalFrame overrides:
- WebLocalFrameImpl* CreateLocalChild(WebTreeScopeType,
- WebLocalFrameClient*,
- blink::InterfaceRegistry*) override;
+ WebLocalFrameImpl* CreateLocalChild(
+ mojom::blink::TreeScopeType,
+ WebLocalFrameClient*,
+ blink::InterfaceRegistry*,
+ const base::UnguessableToken& frame_token) override;
WebLocalFrameClient* Client() const override { return client_; }
void SetAutofillClient(WebAutofillClient*) override;
WebAutofillClient* AutofillClient() override;
@@ -137,12 +140,7 @@ class CORE_EXPORT WebLocalFrameImpl final
const WebSourceLocation&) override;
void SendOrientationChangeEvent() override;
PageSizeType GetPageSizeType(int page_index) override;
- void PageSizeAndMarginsInPixels(int page_index,
- WebDoubleSize& page_size,
- int& margin_top,
- int& margin_right,
- int& margin_bottom,
- int& margin_left) override;
+ void GetPageDescription(int page_index, WebPrintPageDescription*) override;
void ExecuteScript(const WebScriptSource&) override;
void ExecuteScriptInIsolatedWorld(int32_t world_id,
const WebScriptSource&) override;
@@ -180,16 +178,18 @@ class CORE_EXPORT WebLocalFrameImpl final
bool Confirm(const WebString& message) override;
WebString Prompt(const WebString& message,
const WebString& default_value) override;
- void BindDevToolsAgent(
- mojo::ScopedInterfaceEndpointHandle devtools_agent_host_ptr_info,
- mojo::ScopedInterfaceEndpointHandle devtools_agent_request) override;
+ void BindDevToolsAgent(CrossVariantMojoAssociatedRemote<
+ mojom::blink::DevToolsAgentHostInterfaceBase>
+ devtools_agent_host_remote,
+ CrossVariantMojoAssociatedReceiver<
+ mojom::blink::DevToolsAgentInterfaceBase>
+ devtools_agent_receiver) override;
void UnmarkText() override;
bool HasMarkedText() const override;
WebRange MarkedRange() const override;
bool FirstRectForCharacterRange(unsigned location,
unsigned length,
WebRect&) const override;
- size_t CharacterIndexForPoint(const gfx::Point&) const override;
bool ExecuteCommand(const WebString&) override;
bool ExecuteCommand(const WebString&, const WebString& value) override;
bool IsCommandEnabled(const WebString&) const override;
@@ -237,7 +237,7 @@ class CORE_EXPORT WebLocalFrameImpl final
const WebVector<WebString>& words) override;
void SetContentSettingsClient(WebContentSettingsClient*) override;
void ReloadImage(const WebNode&) override;
- mojom::blink::WebSandboxFlags EffectiveSandboxFlagsForTesting()
+ network::mojom::blink::WebSandboxFlags EffectiveSandboxFlagsForTesting()
const override;
bool IsAllowedToDownload() const override;
bool FindForTesting(int identifier,
@@ -250,9 +250,6 @@ class CORE_EXPORT WebLocalFrameImpl final
void SetTickmarks(const WebVector<WebRect>&) override;
WebNode ContextMenuNode() const override;
void CopyImageAtForTesting(const gfx::Point&) override;
- void DispatchMessageEventWithOriginCheck(
- const WebSecurityOrigin& intended_target_origin,
- const WebDOMMessageEvent&) override;
void UsageCountChromeLoadTimes(const WebString& metric) override;
void OnPortalActivated(
const base::UnguessableToken& portal_token,
@@ -271,6 +268,7 @@ class CORE_EXPORT WebLocalFrameImpl final
WebInputMethodController* GetInputMethodController() override;
WebAssociatedURLLoader* CreateAssociatedURLLoader(
const WebAssociatedURLLoaderOptions&) override;
+ void StopLoading() override;
WebSize GetScrollOffset() const override;
void SetScrollOffset(const WebSize&) override;
WebSize DocumentSize() const override;
@@ -287,6 +285,7 @@ class CORE_EXPORT WebLocalFrameImpl final
WebPrintPresetOptions*) override;
bool CapturePaintPreview(const WebRect& bounds,
cc::PaintCanvas* canvas) override;
+ void SetMainFrameOverlayColor(SkColor) override;
bool ShouldSuppressKeyboardForFocusedElement() override;
WebPerformance Performance() const override;
bool IsAdSubframe() const override;
@@ -294,6 +293,7 @@ class CORE_EXPORT WebLocalFrameImpl final
void WaitForDebuggerWhenShown() override;
void PrintPagesForTesting(cc::PaintCanvas*, const WebSize&) override;
WebRect GetSelectionBoundsRectForTesting() const override;
+ gfx::Point GetPositionInViewportForTesting() const override;
void SetLifecycleState(mojom::FrameLifecycleState state) override;
void WasHidden() override;
void WasShown() override;
@@ -335,8 +335,8 @@ class CORE_EXPORT WebLocalFrameImpl final
FrameOwner*,
const AtomicString& name,
WindowAgentFactory*,
- mojom::blink::WebSandboxFlags sandbox_flags =
- mojom::blink::WebSandboxFlags::kNone,
+ network::mojom::blink::WebSandboxFlags sandbox_flags =
+ network::mojom::blink::WebSandboxFlags::kNone,
const FeaturePolicy::FeatureState& opener_feature_state =
FeaturePolicy::FeatureState());
LocalFrame* GetFrame() const { return frame_.Get(); }
@@ -345,27 +345,33 @@ class CORE_EXPORT WebLocalFrameImpl final
void WillDetachParent();
void CollectGarbageForTesting();
- static WebLocalFrameImpl* CreateMainFrame(WebView*,
- WebLocalFrameClient*,
- InterfaceRegistry*,
- WebFrame* opener,
- const WebString& name,
- mojom::blink::WebSandboxFlags,
- const FeaturePolicy::FeatureState&);
- static WebLocalFrameImpl* CreateProvisional(WebLocalFrameClient*,
- InterfaceRegistry*,
- WebFrame*,
- const FramePolicy&,
- const WebString& name);
+ static WebLocalFrameImpl* CreateMainFrame(
+ WebView*,
+ WebLocalFrameClient*,
+ InterfaceRegistry*,
+ const base::UnguessableToken& frame_token,
+ WebFrame* opener,
+ const WebString& name,
+ network::mojom::blink::WebSandboxFlags,
+ const FeaturePolicy::FeatureState&);
+ static WebLocalFrameImpl* CreateProvisional(
+ WebLocalFrameClient*,
+ InterfaceRegistry*,
+ const base::UnguessableToken& frame_token,
+ WebFrame*,
+ const FramePolicy&,
+ const WebString& name);
WebLocalFrameImpl(util::PassKey<WebLocalFrameImpl>,
- WebTreeScopeType,
+ mojom::blink::TreeScopeType,
WebLocalFrameClient*,
- blink::InterfaceRegistry*);
+ blink::InterfaceRegistry*,
+ const base::UnguessableToken& frame_token);
WebLocalFrameImpl(util::PassKey<WebRemoteFrameImpl>,
- WebTreeScopeType,
+ mojom::blink::TreeScopeType,
WebLocalFrameClient*,
- blink::InterfaceRegistry*);
+ blink::InterfaceRegistry*,
+ const base::UnguessableToken& frame_token);
~WebLocalFrameImpl() override;
LocalFrame* CreateChildFrame(const AtomicString& name,
diff --git a/chromium/third_party/blink/renderer/core/frame/web_view_frame_widget.cc b/chromium/third_party/blink/renderer/core/frame/web_view_frame_widget.cc
index 74d711852ad..42afbfb7318 100644
--- a/chromium/third_party/blink/renderer/core/frame/web_view_frame_widget.cc
+++ b/chromium/third_party/blink/renderer/core/frame/web_view_frame_widget.cc
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/core/frame/web_view_frame_widget.h"
#include "third_party/blink/renderer/core/exported/web_view_impl.h"
+#include "third_party/blink/renderer/core/frame/local_frame_ukm_aggregator.h"
#include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
#include "third_party/blink/renderer/platform/scheduler/public/thread.h"
#include "third_party/blink/renderer/platform/widget/widget_base.h"
@@ -35,13 +36,15 @@ WebViewFrameWidget::WebViewFrameWidget(
WebViewFrameWidget::~WebViewFrameWidget() = default;
-void WebViewFrameWidget::Close() {
+void WebViewFrameWidget::Close(
+ scoped_refptr<base::SingleThreadTaskRunner> cleanup_runner,
+ base::OnceCallback<void()> cleanup_task) {
GetPage()->WillCloseAnimationHost(nullptr);
// Closing the WebViewFrameWidget happens in response to the local main frame
// being detached from the Page/WebViewImpl.
web_view_->SetMainFrameWidgetBase(nullptr);
web_view_ = nullptr;
- WebFrameWidgetBase::Close();
+ WebFrameWidgetBase::Close(std::move(cleanup_runner), std::move(cleanup_task));
self_keep_alive_.Clear();
}
@@ -67,14 +70,19 @@ void WebViewFrameWidget::SetSuppressFrameRequestsWorkaroundFor704763Only(
suppress_frame_requests);
}
-void WebViewFrameWidget::DidBeginFrame() {
- web_view_->DidBeginFrame();
-}
-
void WebViewFrameWidget::BeginMainFrame(base::TimeTicks last_frame_time) {
web_view_->BeginFrame(last_frame_time);
}
+void WebViewFrameWidget::DidBeginMainFrame() {
+ WebFrameWidgetBase::DidBeginMainFrame();
+
+ auto* main_frame = web_view_->MainFrameImpl();
+ DocumentLifecycle::AllowThrottlingScope throttling_scope(
+ main_frame->GetFrame()->GetDocument()->Lifecycle());
+ PageWidgetDelegate::DidBeginFrame(*main_frame->GetFrame());
+}
+
void WebViewFrameWidget::BeginUpdateLayers() {
web_view_->BeginUpdateLayers();
}
@@ -84,12 +92,21 @@ void WebViewFrameWidget::EndUpdateLayers() {
}
void WebViewFrameWidget::BeginCommitCompositorFrame() {
- web_view_->BeginCommitCompositorFrame();
+ commit_compositor_frame_start_time_.emplace(base::TimeTicks::Now());
}
void WebViewFrameWidget::EndCommitCompositorFrame(
base::TimeTicks commit_start_time) {
- web_view_->EndCommitCompositorFrame(commit_start_time);
+ DCHECK(commit_compositor_frame_start_time_.has_value());
+
+ WebFrameWidgetBase::EndCommitCompositorFrame(commit_start_time);
+ web_view_->MainFrameImpl()
+ ->GetFrame()
+ ->View()
+ ->EnsureUkmAggregator()
+ .RecordImplCompositorSample(commit_compositor_frame_start_time_.value(),
+ commit_start_time, base::TimeTicks::Now());
+ commit_compositor_frame_start_time_.reset();
}
void WebViewFrameWidget::RecordStartOfFrameMetrics() {
@@ -129,10 +146,6 @@ void WebViewFrameWidget::SetCursorVisibilityState(bool is_visible) {
web_view_->SetCursorVisibilityState(is_visible);
}
-void WebViewFrameWidget::OnFallbackCursorModeToggled(bool is_on) {
- web_view_->OnFallbackCursorModeToggled(is_on);
-}
-
void WebViewFrameWidget::ApplyViewportChanges(
const ApplyViewportChangesArgs& args) {
web_view_->ApplyViewportChanges(args);
@@ -193,11 +206,12 @@ void WebViewFrameWidget::SetRootLayer(scoped_refptr<cc::Layer> root_layer) {
web_view_->DidChangeRootLayer(!!root_layer);
}
-WebHitTestResult WebViewFrameWidget::HitTestResultAt(const gfx::Point& point) {
+WebHitTestResult WebViewFrameWidget::HitTestResultAt(const gfx::PointF& point) {
return web_view_->HitTestResultAt(point);
}
-HitTestResult WebViewFrameWidget::CoreHitTestResultAt(const gfx::Point& point) {
+HitTestResult WebViewFrameWidget::CoreHitTestResultAt(
+ const gfx::PointF& point) {
return web_view_->CoreHitTestResultAt(point);
}
diff --git a/chromium/third_party/blink/renderer/core/frame/web_view_frame_widget.h b/chromium/third_party/blink/renderer/core/frame/web_view_frame_widget.h
index 1bc5f79982e..483c9961018 100644
--- a/chromium/third_party/blink/renderer/core/frame/web_view_frame_widget.h
+++ b/chromium/third_party/blink/renderer/core/frame/web_view_frame_widget.h
@@ -54,36 +54,18 @@ class CORE_EXPORT WebViewFrameWidget : public WebFrameWidgetBase {
~WebViewFrameWidget() override;
// WebWidget overrides:
- void Close() override;
+ void Close(scoped_refptr<base::SingleThreadTaskRunner> cleanup_runner,
+ base::OnceCallback<void()> cleanup_task) override;
WebSize Size() override;
void Resize(const WebSize&) override;
void DidEnterFullscreen() override;
void DidExitFullscreen() override;
- void DidBeginFrame() override;
- void BeginUpdateLayers() override;
- void EndUpdateLayers() override;
- void BeginCommitCompositorFrame() override;
- void EndCommitCompositorFrame(base::TimeTicks commit_start_time) override;
- void RecordStartOfFrameMetrics() override;
- void RecordEndOfFrameMetrics(
- base::TimeTicks frame_begin_time,
- cc::ActiveFrameSequenceTrackers trackers) override;
- std::unique_ptr<cc::BeginMainFrameMetrics> GetBeginMainFrameMetrics()
- override;
void UpdateLifecycle(WebLifecycleUpdate requested_update,
DocumentUpdateReason reason) override;
void ThemeChanged() override;
WebInputEventResult HandleInputEvent(const WebCoalescedInputEvent&) override;
WebInputEventResult DispatchBufferedTouchEvents() override;
void SetCursorVisibilityState(bool is_visible) override;
- void OnFallbackCursorModeToggled(bool is_on) override;
- void ApplyViewportChanges(const ApplyViewportChangesArgs&) override;
- void RecordManipulationTypeCounts(cc::ManipulationInfo info) override;
- void SendOverscrollEventFromImplSide(
- const gfx::Vector2dF& overscroll_delta,
- cc::ElementId scroll_latched_element_id) override;
- void SendScrollEndEventFromImplSide(
- cc::ElementId scroll_latched_element_id) override;
void MouseCaptureLost() override;
void SetFocus(bool) override;
bool SelectionBounds(WebRect& anchor, WebRect& focus) const override;
@@ -93,11 +75,11 @@ class CORE_EXPORT WebViewFrameWidget : public WebFrameWidgetBase {
void DidDetachLocalFrameTree() override;
WebInputMethodController* GetActiveWebInputMethodController() const override;
bool ScrollFocusedEditableElementIntoView() override;
- WebHitTestResult HitTestResultAt(const gfx::Point&) override;
+ WebHitTestResult HitTestResultAt(const gfx::PointF&) override;
// WebFrameWidgetBase overrides:
bool ForSubframe() const override { return false; }
- HitTestResult CoreHitTestResultAt(const gfx::Point&) override;
+ HitTestResult CoreHitTestResultAt(const gfx::PointF&) override;
void ZoomToFindInPageRect(const WebRect& rect_in_root_frame) override;
// FrameWidget overrides:
@@ -106,6 +88,24 @@ class CORE_EXPORT WebViewFrameWidget : public WebFrameWidgetBase {
// WidgetBaseClient overrides:
void BeginMainFrame(base::TimeTicks last_frame_time) override;
void SetSuppressFrameRequestsWorkaroundFor704763Only(bool) final;
+ void RecordStartOfFrameMetrics() override;
+ void RecordEndOfFrameMetrics(
+ base::TimeTicks frame_begin_time,
+ cc::ActiveFrameSequenceTrackers trackers) override;
+ std::unique_ptr<cc::BeginMainFrameMetrics> GetBeginMainFrameMetrics()
+ override;
+ void BeginUpdateLayers() override;
+ void EndUpdateLayers() override;
+ void DidBeginMainFrame() override;
+ void ApplyViewportChanges(const cc::ApplyViewportChangesArgs& args) override;
+ void RecordManipulationTypeCounts(cc::ManipulationInfo info) override;
+ void SendOverscrollEventFromImplSide(
+ const gfx::Vector2dF& overscroll_delta,
+ cc::ElementId scroll_latched_element_id) override;
+ void SendScrollEndEventFromImplSide(
+ cc::ElementId scroll_latched_element_id) override;
+ void BeginCommitCompositorFrame() override;
+ void EndCommitCompositorFrame(base::TimeTicks commit_start_time) override;
void Trace(Visitor*) override;
@@ -114,6 +114,7 @@ class CORE_EXPORT WebViewFrameWidget : public WebFrameWidgetBase {
LocalFrameView* GetLocalFrameViewForAnimationScrolling() override;
scoped_refptr<WebViewImpl> web_view_;
+ base::Optional<base::TimeTicks> commit_compositor_frame_start_time_;
SelfKeepAlive<WebViewFrameWidget> self_keep_alive_;
diff --git a/chromium/third_party/blink/renderer/core/frame/window.idl b/chromium/third_party/blink/renderer/core/frame/window.idl
index 47dd13efd72..b3d5a5549db 100644
--- a/chromium/third_party/blink/renderer/core/frame/window.idl
+++ b/chromium/third_party/blink/renderer/core/frame/window.idl
@@ -35,9 +35,9 @@
] interface Window : EventTarget {
// the current browsing context
// FIXME: The spec uses the WindowProxy type for this and many other attributes.
- [Affects=Nothing, Unforgeable, CrossOrigin] readonly attribute Window window;
- [Replaceable, CrossOrigin] readonly attribute Window self;
- [Affects=Nothing, Unforgeable, CachedAccessor] readonly attribute Document document;
+ [Affects=Nothing, Unforgeable, CrossOrigin, CachedAccessor=kWindowProxy] readonly attribute Window window;
+ [Replaceable, CrossOrigin, CachedAccessor=kWindowProxy] readonly attribute Window self;
+ [Affects=Nothing, Unforgeable, CachedAccessor=kWindowDocument] readonly attribute Document document;
attribute DOMString name;
[Affects=Nothing, PutForwards=href, Unforgeable, CrossOrigin=(Getter,Setter), Custom=Getter] readonly attribute Location location;
[CallWith=ScriptState] readonly attribute CustomElementRegistry customElements;
@@ -56,7 +56,7 @@
[CrossOrigin] void blur();
// other browsing contexts
- [Replaceable, CrossOrigin] readonly attribute Window frames;
+ [Replaceable, CrossOrigin, CachedAccessor=kWindowProxy] readonly attribute Window frames;
[Replaceable, CrossOrigin] readonly attribute unsigned long length;
[Unforgeable, CrossOrigin] readonly attribute Window? top;
// FIXME: opener should be of type any.
@@ -209,7 +209,7 @@
[DisableInNewIDLCompiler] attribute DOMMatrixConstructor WebKitCSSMatrix;
// TrustedTypes API: http://github.com/wicg/trusted-types
- [RuntimeEnabled=TrustedDOMTypes, SecureContext] readonly attribute TrustedTypePolicyFactory trustedTypes;
+ [RuntimeEnabled=TrustedDOMTypes] readonly attribute TrustedTypePolicyFactory trustedTypes;
};
Window includes GlobalEventHandlers;
diff --git a/chromium/third_party/blink/renderer/core/frame/window_event_handlers.idl b/chromium/third_party/blink/renderer/core/frame/window_event_handlers.idl
index 48ed1316809..f4f1fdeae78 100644
--- a/chromium/third_party/blink/renderer/core/frame/window_event_handlers.idl
+++ b/chromium/third_party/blink/renderer/core/frame/window_event_handlers.idl
@@ -34,8 +34,7 @@
] interface mixin WindowEventHandlers {
attribute EventHandler onafterprint;
attribute EventHandler onbeforeprint;
- // FIXME: onbeforeunload should be an OnBeforeUnloadEventHandler.
- attribute EventHandler onbeforeunload;
+ attribute OnBeforeUnloadEventHandler onbeforeunload;
attribute EventHandler onhashchange;
attribute EventHandler onlanguagechange;
attribute EventHandler onmessage;
diff --git a/chromium/third_party/blink/renderer/core/frame/window_or_worker_global_scope.cc b/chromium/third_party/blink/renderer/core/frame/window_or_worker_global_scope.cc
index 13d6a539a16..a2001fb6fb3 100644
--- a/chromium/third_party/blink/renderer/core/frame/window_or_worker_global_scope.cc
+++ b/chromium/third_party/blink/renderer/core/frame/window_or_worker_global_scope.cc
@@ -35,11 +35,11 @@
#include "base/containers/span.h"
#include "third_party/blink/renderer/bindings/core/v8/scheduled_action.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_gc_for_context_dispose.h"
-#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/events/event_target.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/frame/csp/content_security_policy.h"
#include "third_party/blink/renderer/core/frame/dom_timer.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/html/parser/html_parser_idioms.h"
#include "third_party/blink/renderer/core/imagebitmap/image_bitmap_factories.h"
#include "third_party/blink/renderer/core/trustedtypes/trusted_types_util.h"
@@ -55,10 +55,10 @@ namespace blink {
static bool IsAllowed(ExecutionContext* execution_context,
bool is_eval,
const String& source) {
- if (Document* document = Document::DynamicFrom(execution_context)) {
- if (!document->GetFrame())
+ if (auto* window = DynamicTo<LocalDOMWindow>(execution_context)) {
+ if (!window->GetFrame())
return false;
- if (is_eval && !document->GetContentSecurityPolicy()->AllowEval(
+ if (is_eval && !window->GetContentSecurityPolicy()->AllowEval(
ReportingDisposition::kReport,
ContentSecurityPolicy::kWillNotThrowException, source)) {
return false;
@@ -217,17 +217,17 @@ void WindowOrWorkerGlobalScope::clearInterval(EventTarget& event_target,
ScriptPromise WindowOrWorkerGlobalScope::createImageBitmap(
ScriptState* script_state,
- EventTarget& event_target,
+ EventTarget&,
const ImageBitmapSourceUnion& bitmap_source,
const ImageBitmapOptions* options,
ExceptionState& exception_state) {
- return ImageBitmapFactories::CreateImageBitmap(
- script_state, event_target, bitmap_source, options, exception_state);
+ return ImageBitmapFactories::CreateImageBitmap(script_state, bitmap_source,
+ options, exception_state);
}
ScriptPromise WindowOrWorkerGlobalScope::createImageBitmap(
ScriptState* script_state,
- EventTarget& event_target,
+ EventTarget&,
const ImageBitmapSourceUnion& bitmap_source,
int sx,
int sy,
@@ -235,9 +235,8 @@ ScriptPromise WindowOrWorkerGlobalScope::createImageBitmap(
int sh,
const ImageBitmapOptions* options,
ExceptionState& exception_state) {
- return ImageBitmapFactories::CreateImageBitmap(script_state, event_target,
- bitmap_source, sx, sy, sw, sh,
- options, exception_state);
+ return ImageBitmapFactories::CreateImageBitmap(
+ script_state, bitmap_source, sx, sy, sw, sh, options, exception_state);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/fullscreen/fullscreen.cc b/chromium/third_party/blink/renderer/core/fullscreen/fullscreen.cc
index 8d336281208..e9bf6992e1a 100644
--- a/chromium/third_party/blink/renderer/core/fullscreen/fullscreen.cc
+++ b/chromium/third_party/blink/renderer/core/fullscreen/fullscreen.cc
@@ -40,6 +40,7 @@
#include "third_party/blink/renderer/core/dom/element_traversal.h"
#include "third_party/blink/renderer/core/dom/events/event.h"
#include "third_party/blink/renderer/core/dom/shadow_root.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
#include "third_party/blink/renderer/core/frame/settings.h"
@@ -487,21 +488,15 @@ void EnqueueEvent(const AtomicString& type,
const char Fullscreen::kSupplementName[] = "Fullscreen";
-Fullscreen& Fullscreen::From(Document& document) {
- Fullscreen* fullscreen = FromIfExists(document);
+Fullscreen& Fullscreen::From(LocalDOMWindow& window) {
+ Fullscreen* fullscreen = Supplement<LocalDOMWindow>::From<Fullscreen>(window);
if (!fullscreen) {
- fullscreen = MakeGarbageCollected<Fullscreen>(document);
- ProvideTo(document, fullscreen);
+ fullscreen = MakeGarbageCollected<Fullscreen>(window);
+ ProvideTo(window, fullscreen);
}
return *fullscreen;
}
-Fullscreen* Fullscreen::FromIfExists(Document& document) {
- if (!document.HasFullscreenSupplement())
- return nullptr;
- return Supplement<Document>::From<Fullscreen>(document);
-}
-
Element* Fullscreen::FullscreenElementFrom(Document& document) {
// The fullscreen element is the topmost element in the document's top layer
// whose fullscreen flag is set, if any, and null otherwise.
@@ -543,18 +538,12 @@ bool Fullscreen::IsInFullscreenElementStack(const Element& element) {
return HasFullscreenFlag(const_cast<Element&>(element));
}
-Fullscreen::Fullscreen(Document& document)
- : Supplement<Document>(document),
- ExecutionContextLifecycleObserver(&document) {
- document.SetHasFullscreenSupplement();
-}
+Fullscreen::Fullscreen(LocalDOMWindow& window)
+ : Supplement<LocalDOMWindow>(window),
+ ExecutionContextLifecycleObserver(&window) {}
Fullscreen::~Fullscreen() = default;
-Document* Fullscreen::GetDocument() {
- return Document::From(GetExecutionContext());
-}
-
void Fullscreen::ContextDestroyed() {
pending_requests_.clear();
pending_exits_.clear();
@@ -605,11 +594,12 @@ ScriptPromise Fullscreen::RequestFullscreen(Element& pending,
// Use counters only need to be incremented in the process of the actual
// fullscreen element.
+ LocalDOMWindow& window = *document.domWindow();
if (!for_cross_process_descendant) {
- if (document.IsSecureContext())
- UseCounter::Count(document, WebFeature::kFullscreenSecureOrigin);
+ if (window.IsSecureContext())
+ UseCounter::Count(window, WebFeature::kFullscreenSecureOrigin);
else
- UseCounter::Count(document, WebFeature::kFullscreenInsecureOrigin);
+ UseCounter::Count(window, WebFeature::kFullscreenInsecureOrigin);
}
// 5. Let |error| be false.
@@ -631,14 +621,14 @@ ScriptPromise Fullscreen::RequestFullscreen(Element& pending,
// the output device. Optionally display a message how the end user can
// revert this.
if (!error) {
- if (From(document).pending_requests_.size()) {
- UseCounter::Count(document,
+ if (From(window).pending_requests_.size()) {
+ UseCounter::Count(window,
WebFeature::kFullscreenRequestWithPendingElement);
}
- From(document).pending_requests_.push_back(
+ From(window).pending_requests_.push_back(
MakeGarbageCollected<PendingRequest>(&pending, request_type, resolver));
- LocalFrame& frame = *document.GetFrame();
+ LocalFrame& frame = *window.GetFrame();
frame.GetChromeClient().EnterFullscreen(frame, options,
for_cross_process_descendant);
@@ -675,7 +665,7 @@ void Fullscreen::DidResolveEnterFullscreenRequest(Document& document,
}
PendingRequests requests;
- requests.swap(From(document).pending_requests_);
+ requests.swap(From(*document.domWindow()).pending_requests_);
for (const Member<PendingRequest>& request : requests) {
ContinueRequestFullscreen(document, *request->element(), request->type(),
request->resolver(), !granted);
@@ -867,7 +857,7 @@ ScriptPromise Fullscreen::ExitFullscreen(Document& doc,
if (ua_originated) {
ContinueExitFullscreen(&doc, resolver, true /* resize */);
} else {
- From(top_level_doc).pending_exits_.push_back(resolver);
+ From(*top_level_doc.domWindow()).pending_exits_.push_back(resolver);
LocalFrame& frame = *doc.GetFrame();
frame.GetChromeClient().ExitFullscreen(frame);
}
@@ -886,7 +876,7 @@ ScriptPromise Fullscreen::ExitFullscreen(Document& doc,
void Fullscreen::DidExitFullscreen(Document& document) {
// If this is a response to an ExitFullscreen call then
// continue exiting. Otherwise call FullyExitFullscreen.
- Fullscreen& fullscreen = From(document);
+ Fullscreen& fullscreen = From(*document.domWindow());
PendingExits exits;
exits.swap(fullscreen.pending_exits_);
if (exits.IsEmpty()) {
@@ -1028,7 +1018,7 @@ void Fullscreen::ElementRemoved(Element& node) {
void Fullscreen::Trace(Visitor* visitor) {
visitor->Trace(pending_requests_);
visitor->Trace(pending_exits_);
- Supplement<Document>::Trace(visitor);
+ Supplement<LocalDOMWindow>::Trace(visitor);
ExecutionContextLifecycleObserver::Trace(visitor);
}
diff --git a/chromium/third_party/blink/renderer/core/fullscreen/fullscreen.h b/chromium/third_party/blink/renderer/core/fullscreen/fullscreen.h
index 7c6134b3687..b00d221ff28 100644
--- a/chromium/third_party/blink/renderer/core/fullscreen/fullscreen.h
+++ b/chromium/third_party/blink/renderer/core/fullscreen/fullscreen.h
@@ -43,6 +43,7 @@
namespace blink {
+class LocalDOMWindow;
class FullscreenOptions;
class ScriptPromiseResolver;
@@ -51,17 +52,16 @@ class ScriptPromiseResolver;
// Document supplement as each document has some fullscreen state, and to
// actually enter and exit fullscreen it (indirectly) uses FullscreenController.
class CORE_EXPORT Fullscreen final : public GarbageCollected<Fullscreen>,
- public Supplement<Document>,
+ public Supplement<LocalDOMWindow>,
public ExecutionContextLifecycleObserver {
USING_GARBAGE_COLLECTED_MIXIN(Fullscreen);
public:
static const char kSupplementName[];
- explicit Fullscreen(Document&);
+ explicit Fullscreen(LocalDOMWindow&);
virtual ~Fullscreen();
- static Fullscreen& From(Document&);
static Element* FullscreenElementFrom(Document&);
static Element* FullscreenElementForBindingFrom(TreeScope&);
static bool IsFullscreenElement(const Element&);
@@ -109,9 +109,7 @@ class CORE_EXPORT Fullscreen final : public GarbageCollected<Fullscreen>,
void Trace(Visitor*) override;
private:
- static Fullscreen* FromIfExists(Document&);
-
- Document* GetDocument();
+ static Fullscreen& From(LocalDOMWindow&);
static void ContinueRequestFullscreen(Document&,
Element&,
diff --git a/chromium/third_party/blink/renderer/core/geometry/dom_rect.h b/chromium/third_party/blink/renderer/core/geometry/dom_rect.h
index 35318a62d71..fede00578e6 100644
--- a/chromium/third_party/blink/renderer/core/geometry/dom_rect.h
+++ b/chromium/third_party/blink/renderer/core/geometry/dom_rect.h
@@ -34,6 +34,13 @@ class CORE_EXPORT DOMRect final : public DOMRectReadOnly {
void setHeight(double height) { height_ = height; }
};
+constexpr bool operator==(const DOMRect& lhs, const DOMRect& rhs) {
+ return lhs.x() == rhs.x() && lhs.y() == rhs.y() &&
+ lhs.width() == rhs.width() && lhs.height() == rhs.height();
+}
+constexpr bool operator!=(const DOMRect& lhs, const DOMRect& rhs) {
+ return !(lhs == rhs);
+}
} // namespace blink
-#endif
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_GEOMETRY_DOM_RECT_H_
diff --git a/chromium/third_party/blink/renderer/core/geometry/dom_rect_list.idl b/chromium/third_party/blink/renderer/core/geometry/dom_rect_list.idl
index 7afa3d6df2f..79417a79312 100644
--- a/chromium/third_party/blink/renderer/core/geometry/dom_rect_list.idl
+++ b/chromium/third_party/blink/renderer/core/geometry/dom_rect_list.idl
@@ -8,7 +8,9 @@
// DOMRectList only exists for compatibility with legacy web content.
// When specifying a new API, use sequence<DOMRect> instead.
-interface DOMRectList {
+[
+ Exposed=Window
+] interface DOMRectList {
readonly attribute unsigned long length;
[MeasureAs=ClientRectListItem] getter DOMRect? item(unsigned long index);
};
diff --git a/chromium/third_party/blink/renderer/core/html/BUILD.gn b/chromium/third_party/blink/renderer/core/html/BUILD.gn
index de82c30b599..76cfc6e1dd6 100644
--- a/chromium/third_party/blink/renderer/core/html/BUILD.gn
+++ b/chromium/third_party/blink/renderer/core/html/BUILD.gn
@@ -466,6 +466,8 @@ blink_core_sources("html") {
"link_style.h",
"list_item_ordinal.cc",
"list_item_ordinal.h",
+ "loading_attribute.cc",
+ "loading_attribute.h",
"media/autoplay_policy.cc",
"media/autoplay_policy.h",
"media/autoplay_uma_helper.cc",
diff --git a/chromium/third_party/blink/renderer/core/html/anchor_element_metrics.cc b/chromium/third_party/blink/renderer/core/html/anchor_element_metrics.cc
index 04987385b04..cbb16b5d4f5 100644
--- a/chromium/third_party/blink/renderer/core/html/anchor_element_metrics.cc
+++ b/chromium/third_party/blink/renderer/core/html/anchor_element_metrics.cc
@@ -143,7 +143,7 @@ base::Optional<AnchorElementMetrics> AnchorElementMetrics::Create(
return base::nullopt;
AnchorElementMetrics anchor_metrics(
- anchor_element, 0, 0, 0, 0, 0, 0, 0, IsInIFrame(*anchor_element),
+ anchor_element, 0, 0, 0, 0, 0, 0, IsInIFrame(*anchor_element),
ContainsImage(*anchor_element), IsSameHost(*anchor_element),
IsUrlIncrementedByOne(*anchor_element));
@@ -191,7 +191,6 @@ base::Optional<AnchorElementMetrics> AnchorElementMetrics::Create(
->GetScrollableArea()
->ContentsSize()
.Height();
- float ratio_root_height = root_height / base_height;
int root_scrolled =
root_frame_view->LayoutViewport()->ScrollOffsetInt().Height();
@@ -211,7 +210,7 @@ base::Optional<AnchorElementMetrics> AnchorElementMetrics::Create(
return AnchorElementMetrics(
anchor_element, ratio_area, ratio_visible_area,
ratio_distance_top_to_visible_top, ratio_distance_center_to_visible_top,
- ratio_distance_root_top, ratio_distance_root_bottom, ratio_root_height,
+ ratio_distance_root_top, ratio_distance_root_bottom,
IsInIFrame(*anchor_element), ContainsImage(*anchor_element),
IsSameHost(*anchor_element), IsUrlIncrementedByOne(*anchor_element));
}
@@ -230,7 +229,7 @@ AnchorElementMetrics::MaybeReportClickedMetricsOnClick(
// Create metrics that don't have sizes set. The browser only records
// metrics unrelated to sizes.
AnchorElementMetrics anchor_metrics(
- anchor_element, 0, 0, 0, 0, 0, 0, 0, IsInIFrame(*anchor_element),
+ anchor_element, 0, 0, 0, 0, 0, 0, IsInIFrame(*anchor_element),
ContainsImage(*anchor_element), IsSameHost(*anchor_element),
IsUrlIncrementedByOne(*anchor_element));
@@ -343,45 +342,8 @@ mojom::blink::AnchorElementMetricsPtr AnchorElementMetrics::CreateMetricsPtr()
}
void AnchorElementMetrics::RecordMetricsOnClick() const {
- UMA_HISTOGRAM_PERCENTAGE("AnchorElementMetrics.Clicked.RatioArea",
- static_cast<int>(ratio_area_ * 100));
-
- UMA_HISTOGRAM_PERCENTAGE("AnchorElementMetrics.Clicked.RatioVisibleArea",
- static_cast<int>(ratio_visible_area_ * 100));
-
- UMA_HISTOGRAM_PERCENTAGE(
- "AnchorElementMetrics.Clicked.RatioDistanceTopToVisibleTop",
- static_cast<int>(std::min(ratio_distance_top_to_visible_top_, 1.0f) *
- 100));
-
- UMA_HISTOGRAM_PERCENTAGE(
- "AnchorElementMetrics.Clicked.RatioDistanceCenterToVisibleTop",
- static_cast<int>(std::min(ratio_distance_center_to_visible_top_, 1.0f) *
- 100));
-
- UMA_HISTOGRAM_COUNTS_10000(
- "AnchorElementMetrics.Clicked.RatioDistanceRootTop",
- static_cast<int>(std::min(ratio_distance_root_top_, 100.0f) * 100));
-
- UMA_HISTOGRAM_COUNTS_10000(
- "AnchorElementMetrics.Clicked.RatioDistanceRootBottom",
- static_cast<int>(std::min(ratio_distance_root_bottom_, 100.0f) * 100));
-
- UMA_HISTOGRAM_COUNTS_10000(
- "AnchorElementMetrics.Clicked.RatioRootHeight",
- static_cast<int>(std::min(ratio_root_height_, 100.0f) * 100));
-
- UMA_HISTOGRAM_BOOLEAN("AnchorElementMetrics.Clicked.IsInIFrame",
- is_in_iframe_);
-
- UMA_HISTOGRAM_BOOLEAN("AnchorElementMetrics.Clicked.ContainsImage",
- contains_image_);
-
UMA_HISTOGRAM_BOOLEAN("AnchorElementMetrics.Clicked.IsSameHost",
is_same_host_);
-
- UMA_HISTOGRAM_BOOLEAN("AnchorElementMetrics.Clicked.IsUrlIncrementedByOne",
- is_url_incremented_by_one_);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/anchor_element_metrics.h b/chromium/third_party/blink/renderer/core/html/anchor_element_metrics.h
index 52eb928f076..73ae3e64718 100644
--- a/chromium/third_party/blink/renderer/core/html/anchor_element_metrics.h
+++ b/chromium/third_party/blink/renderer/core/html/anchor_element_metrics.h
@@ -94,9 +94,6 @@ class CORE_EXPORT AnchorElementMetrics {
// height.
const float ratio_distance_root_bottom_;
- // The hight of the root document, divided by the viewport height.
- const float ratio_root_height_;
-
// Whether the anchor element is within an iframe.
const bool is_in_iframe_;
@@ -117,7 +114,6 @@ class CORE_EXPORT AnchorElementMetrics {
float ratio_distance_center_to_visible_top,
float ratio_distance_root_top,
float ratio_distance_root_bottom,
- float ratio_root_height,
bool is_in_iframe,
bool contains_image,
bool is_same_host,
@@ -130,7 +126,6 @@ class CORE_EXPORT AnchorElementMetrics {
ratio_distance_center_to_visible_top),
ratio_distance_root_top_(ratio_distance_root_top),
ratio_distance_root_bottom_(ratio_distance_root_bottom),
- ratio_root_height_(ratio_root_height),
is_in_iframe_(is_in_iframe),
contains_image_(contains_image),
is_same_host_(is_same_host),
diff --git a/chromium/third_party/blink/renderer/core/html/anchor_element_metrics_sender.cc b/chromium/third_party/blink/renderer/core/html/anchor_element_metrics_sender.cc
index 45cc716171c..6b73d04db1c 100644
--- a/chromium/third_party/blink/renderer/core/html/anchor_element_metrics_sender.cc
+++ b/chromium/third_party/blink/renderer/core/html/anchor_element_metrics_sender.cc
@@ -85,8 +85,6 @@ void AnchorElementMetricsSender::AddAnchorElement(HTMLAnchorElement& element) {
return;
bool is_ad_frame_element = ShouldDiscardAnchorElement(element);
- UMA_HISTOGRAM_BOOLEAN("AnchorElementMetrics.IsAdFrameElement",
- is_ad_frame_element);
// We ignore anchor elements that are in ad frames.
if (is_ad_frame_element)
diff --git a/chromium/third_party/blink/renderer/core/html/canvas/canvas_async_blob_creator.cc b/chromium/third_party/blink/renderer/core/html/canvas/canvas_async_blob_creator.cc
index 98297281a3b..fbe1cc5eb3e 100644
--- a/chromium/third_party/blink/renderer/core/html/canvas/canvas_async_blob_creator.cc
+++ b/chromium/third_party/blink/renderer/core/html/canvas/canvas_async_blob_creator.cc
@@ -309,8 +309,9 @@ void CanvasAsyncBlobCreator::ScheduleAsyncBlobCreation(const double& quality) {
// deadlines (6.7s or 13s) bypass the web test running deadline (6s)
// and result in timeouts on different tests. We use
// enforce_idle_encoding_for_test_ to test idle encoding in unit tests.
- // We also don't use idle tasks in workers because there's no proper idle
- // queue there and tasks can take too long without requestAnimationFrame.
+ // We also don't use idle tasks in workers because the short idle periods are
+ // not implemented, so the idle task can take a long time even when the thread
+ // is not busy.
bool use_idle_encoding =
WTF::IsMainThread() && (mime_type_ != kMimeTypeWebp) &&
(enforce_idle_encoding_for_test_ ||
diff --git a/chromium/third_party/blink/renderer/core/html/canvas/canvas_font_cache_test.cc b/chromium/third_party/blink/renderer/core/html/canvas/canvas_font_cache_test.cc
index 12047018871..9a34c10bdfe 100644
--- a/chromium/third_party/blink/renderer/core/html/canvas/canvas_font_cache_test.cc
+++ b/chromium/third_party/blink/renderer/core/html/canvas/canvas_font_cache_test.cc
@@ -71,7 +71,7 @@ TEST_F(CanvasFontCacheTest, CacheHardLimit) {
TEST_F(CanvasFontCacheTest, PageVisibilityChange) {
Context2D()->setFont("10px sans-serif");
EXPECT_TRUE(Cache()->IsInCache("10px sans-serif"));
- GetPage().SetVisibilityState(PageVisibilityState::kHidden,
+ GetPage().SetVisibilityState(mojom::blink::PageVisibilityState::kHidden,
/*initial_state=*/false);
EXPECT_FALSE(Cache()->IsInCache("10px sans-serif"));
@@ -83,7 +83,7 @@ TEST_F(CanvasFontCacheTest, PageVisibilityChange) {
EXPECT_TRUE(Cache()->IsInCache("10px sans-serif"));
EXPECT_FALSE(Cache()->IsInCache("15px sans-serif"));
- GetPage().SetVisibilityState(PageVisibilityState::kVisible,
+ GetPage().SetVisibilityState(mojom::blink::PageVisibilityState::kVisible,
/*initial_state=*/false);
Context2D()->setFont("15px sans-serif");
Context2D()->setFont("10px sans-serif");
diff --git a/chromium/third_party/blink/renderer/core/html/canvas/canvas_rendering_context_host.cc b/chromium/third_party/blink/renderer/core/html/canvas/canvas_rendering_context_host.cc
index 6e4763718ca..1ef7b373945 100644
--- a/chromium/third_party/blink/renderer/core/html/canvas/canvas_rendering_context_host.cc
+++ b/chromium/third_party/blink/renderer/core/html/canvas/canvas_rendering_context_host.cc
@@ -93,15 +93,10 @@ CanvasRenderingContextHost::GetOrCreateCanvasResourceProviderImpl(
AccelerationHint hint) {
if (!ResourceProvider() && !did_fail_to_create_resource_provider_) {
if (IsValidImageSize(Size())) {
- base::WeakPtr<CanvasResourceDispatcher> dispatcher =
- GetOrCreateResourceDispatcher()
- ? GetOrCreateResourceDispatcher()->GetWeakPtr()
- : nullptr;
-
if (Is3d()) {
- CreateCanvasResourceProvider3D(hint, dispatcher);
+ CreateCanvasResourceProvider3D(hint);
} else {
- CreateCanvasResourceProvider2D(hint, dispatcher);
+ CreateCanvasResourceProvider2D(hint);
}
}
if (!ResourceProvider())
@@ -111,8 +106,7 @@ CanvasRenderingContextHost::GetOrCreateCanvasResourceProviderImpl(
}
void CanvasRenderingContextHost::CreateCanvasResourceProvider3D(
- AccelerationHint hint,
- base::WeakPtr<CanvasResourceDispatcher> dispatcher) {
+ AccelerationHint hint) {
DCHECK(Is3d());
uint8_t presentation_mode = CanvasResourceProvider::kDefaultPresentationMode;
@@ -127,9 +121,13 @@ void CanvasRenderingContextHost::CreateCanvasResourceProvider3D(
presentation_mode |=
CanvasResourceProvider::kAllowSwapChainPresentationMode;
}
- CanvasResourceProvider::ResourceUsage usage;
-
+ std::unique_ptr<CanvasResourceProvider> provider;
+ base::WeakPtr<CanvasResourceDispatcher> dispatcher =
+ GetOrCreateResourceDispatcher()
+ ? GetOrCreateResourceDispatcher()->GetWeakPtr()
+ : nullptr;
if (SharedGpuContext::IsGpuCompositingEnabled()) {
+ CanvasResourceProvider::ResourceUsage usage;
if (LowLatencyEnabled() && RenderingContext()) {
// Allow swap chain presentation only if 3d context is using a swap
// chain since we'll be importing it as a passthrough texture.
@@ -139,17 +137,27 @@ void CanvasRenderingContextHost::CreateCanvasResourceProvider3D(
usage = CanvasResourceProvider::ResourceUsage::
kAcceleratedCompositedResourceUsage;
}
+ provider = CanvasResourceProvider::Create(
+ Size(), usage, SharedGpuContext::ContextProviderWrapper(),
+ 0 /* msaa_sample_count */, FilterQuality(), ColorParams(),
+ presentation_mode, std::move(dispatcher),
+ RenderingContext()->IsOriginTopLeft());
} else {
- usage =
- CanvasResourceProvider::ResourceUsage::kSoftwareCompositedResourceUsage;
+ // Here it should try a SoftwareCompositedResourceUsage, but as
+ // SharedGpuCOntext::IsGpuCompositingEnabled() is false and that being true
+ // is a requirement to try and create a SharedImageProvider if
+ // SoftwareCompositeResourceUsage is used, it will go straight ahead to a
+ // fallback SharedBitmap and then to a Bitmap provider
+ provider = CanvasResourceProvider::CreateSharedBitmapProvider(
+ Size(), SharedGpuContext::ContextProviderWrapper(), FilterQuality(),
+ ColorParams(), std::move(dispatcher));
+ if (!provider) {
+ provider = CanvasResourceProvider::CreateBitmapProvider(
+ Size(), FilterQuality(), ColorParams());
+ }
}
- base::UmaHistogramEnumeration("Blink.Canvas.ResourceProviderUsage", usage);
- ReplaceResourceProvider(CanvasResourceProvider::Create(
- Size(), usage, SharedGpuContext::ContextProviderWrapper(),
- 0 /* msaa_sample_count */, FilterQuality(), ColorParams(),
- presentation_mode, std::move(dispatcher),
- RenderingContext()->IsOriginTopLeft()));
+ ReplaceResourceProvider(std::move(provider));
if (ResourceProvider() && ResourceProvider()->IsValid()) {
base::UmaHistogramBoolean("Blink.Canvas.ResourceProviderIsAccelerated",
ResourceProvider()->IsAccelerated());
@@ -159,13 +167,17 @@ void CanvasRenderingContextHost::CreateCanvasResourceProvider3D(
}
void CanvasRenderingContextHost::CreateCanvasResourceProvider2D(
- AccelerationHint hint,
- base::WeakPtr<CanvasResourceDispatcher> dispatcher) {
+ AccelerationHint hint) {
DCHECK(Is2d());
const bool want_acceleration =
hint == kPreferAcceleration && ShouldAccelerate2dContext();
+ base::WeakPtr<CanvasResourceDispatcher> dispatcher =
+ GetOrCreateResourceDispatcher()
+ ? GetOrCreateResourceDispatcher()->GetWeakPtr()
+ : nullptr;
uint8_t presentation_mode = CanvasResourceProvider::kDefaultPresentationMode;
+ bool composited_mode = false;
// Allow GMB image resources if the runtime feature is enabled or if
// we want to use it for low latency mode.
if (RuntimeEnabledFeatures::Canvas2dImageChromiumEnabled() ||
@@ -174,6 +186,7 @@ void CanvasRenderingContextHost::CreateCanvasResourceProvider2D(
LowLatencyEnabled() && want_acceleration)) {
presentation_mode |=
CanvasResourceProvider::kAllowImageChromiumPresentationMode;
+ composited_mode = true;
}
if (base::FeatureList::IsEnabled(features::kLowLatencyCanvas2dSwapChain) &&
LowLatencyEnabled() && want_acceleration) {
@@ -181,6 +194,8 @@ void CanvasRenderingContextHost::CreateCanvasResourceProvider2D(
CanvasResourceProvider::kAllowSwapChainPresentationMode;
}
+ bool try_swap_chain = false;
+
CanvasResourceProvider::ResourceUsage usage;
if (want_acceleration) {
if (LowLatencyEnabled()) {
@@ -188,6 +203,7 @@ void CanvasRenderingContextHost::CreateCanvasResourceProvider2D(
// in low latency mode too.
usage = CanvasResourceProvider::ResourceUsage::
kAcceleratedDirect2DResourceUsage;
+ try_swap_chain = true;
} else {
usage = CanvasResourceProvider::ResourceUsage::
kAcceleratedCompositedResourceUsage;
@@ -197,17 +213,54 @@ void CanvasRenderingContextHost::CreateCanvasResourceProvider2D(
CanvasResourceProvider::ResourceUsage::kSoftwareCompositedResourceUsage;
}
+ std::unique_ptr<CanvasResourceProvider> provider;
// It is important to not use the context's IsOriginTopLeft() here
// because that denotes the current state and could change after the
// new resource provider is created e.g. due to switching between
// unaccelerated and accelerated modes during tab switching.
const bool is_origin_top_left = !want_acceleration || LowLatencyEnabled();
- base::UmaHistogramEnumeration("Blink.Canvas.ResourceProviderUsage", usage);
- ReplaceResourceProvider(CanvasResourceProvider::Create(
- Size(), usage, SharedGpuContext::ContextProviderWrapper(),
- GetMSAASampleCountFor2dContext(), FilterQuality(), ColorParams(),
- presentation_mode, std::move(dispatcher), is_origin_top_left));
+ // First try to be optimized for displaying on screen. In the case we are
+ // hardware compositing, we also try to enable the usage of the image as
+ // scanout buffer (overlay)
+ uint32_t shared_image_usage_flags = gpu::SHARED_IMAGE_USAGE_DISPLAY;
+ if (composited_mode)
+ shared_image_usage_flags |= gpu::SHARED_IMAGE_USAGE_SCANOUT;
+
+ if (try_swap_chain) {
+ // Swap Chain is used for low latency.
+ provider = CanvasResourceProvider::Create(
+ Size(), usage, SharedGpuContext::ContextProviderWrapper(),
+ GetMSAASampleCountFor2dContext(), FilterQuality(), ColorParams(),
+ presentation_mode, std::move(dispatcher), is_origin_top_left);
+ } else if (want_acceleration) {
+ provider = CanvasResourceProvider::CreateSharedImageProvider(
+ Size(), SharedGpuContext::ContextProviderWrapper(), FilterQuality(),
+ ColorParams(), is_origin_top_left,
+ CanvasResourceProvider::RasterMode::kGPU, shared_image_usage_flags);
+ } else if (composited_mode) {
+ provider = CanvasResourceProvider::CreateSharedImageProvider(
+ Size(), SharedGpuContext::ContextProviderWrapper(), FilterQuality(),
+ ColorParams(), is_origin_top_left,
+ CanvasResourceProvider::RasterMode::kCPU, shared_image_usage_flags);
+ }
+
+ if (!provider && !try_swap_chain) {
+ // If the sharedImage Provider creation above failed, we try a
+ // SharedBitmap Provider before falling back to a Bitmap Provider
+ provider = CanvasResourceProvider::CreateSharedBitmapProvider(
+ Size(), SharedGpuContext::ContextProviderWrapper(), FilterQuality(),
+ ColorParams(), std::move(dispatcher));
+ }
+
+ if (!provider && !try_swap_chain) {
+ // If any of the above Create was able to create a valid provider, a
+ // BitmapProvider will be created here.
+ provider = CanvasResourceProvider::CreateBitmapProvider(
+ Size(), FilterQuality(), ColorParams());
+ }
+
+ ReplaceResourceProvider(std::move(provider));
if (ResourceProvider()) {
if (ResourceProvider()->IsValid()) {
diff --git a/chromium/third_party/blink/renderer/core/html/canvas/canvas_rendering_context_host.h b/chromium/third_party/blink/renderer/core/html/canvas/canvas_rendering_context_host.h
index e0503886bc6..0716b939ac8 100644
--- a/chromium/third_party/blink/renderer/core/html/canvas/canvas_rendering_context_host.h
+++ b/chromium/third_party/blink/renderer/core/html/canvas/canvas_rendering_context_host.h
@@ -79,6 +79,12 @@ class CORE_EXPORT CanvasRenderingContextHost : public CanvasResourceHost,
virtual void Commit(scoped_refptr<CanvasResource> canvas_resource,
const SkIRect& damage_rect);
+ // For deferred canvases this will have the side effect of drawing recorded
+ // commands in order to finalize the frame.
+ virtual ScriptPromise convertToBlob(ScriptState*,
+ const ImageEncodeOptions*,
+ ExceptionState&);
+
bool IsPaintable() const;
// Required by template functions in WebGLRenderingContextBase
@@ -96,12 +102,6 @@ class CORE_EXPORT CanvasRenderingContextHost : public CanvasResourceHost,
bool Is2d() const;
CanvasColorParams ColorParams() const;
- // For deferred canvases this will have the side effect of drawing recorded
- // commands in order to finalize the frame.
- ScriptPromise convertToBlob(ScriptState*,
- const ImageEncodeOptions*,
- ExceptionState&);
-
// blink::CanvasImageSource
bool IsOffscreenCanvas() const override;
@@ -110,12 +110,8 @@ class CORE_EXPORT CanvasRenderingContextHost : public CanvasResourceHost,
scoped_refptr<StaticBitmapImage> CreateTransparentImage(const IntSize&) const;
- void CreateCanvasResourceProvider2D(
- AccelerationHint hint,
- base::WeakPtr<CanvasResourceDispatcher> dispatcher);
- void CreateCanvasResourceProvider3D(
- AccelerationHint hint,
- base::WeakPtr<CanvasResourceDispatcher> dispatcher);
+ void CreateCanvasResourceProvider2D(AccelerationHint hint);
+ void CreateCanvasResourceProvider3D(AccelerationHint hint);
bool did_fail_to_create_resource_provider_ = false;
bool did_record_canvas_size_to_uma_ = false;
diff --git a/chromium/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc b/chromium/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc
index 487efcdd8ba..a5b05b93340 100644
--- a/chromium/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc
+++ b/chromium/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc
@@ -38,7 +38,10 @@
#include "base/metrics/histogram_macros.h"
#include "base/numerics/checked_math.h"
#include "build/build_config.h"
+#include "services/metrics/public/cpp/ukm_recorder.h"
#include "third_party/blink/public/common/features.h"
+#include "third_party/blink/public/common/privacy_budget/identifiability_metric_builder.h"
+#include "third_party/blink/public/common/privacy_budget/identifiability_metrics.h"
#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/public/resources/grit/blink_image_resources.h"
#include "third_party/blink/renderer/bindings/core/v8/script_controller.h"
@@ -55,6 +58,7 @@
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/local_frame_client.h"
#include "third_party/blink/renderer/core/frame/settings.h"
+#include "third_party/blink/renderer/core/frame/web_feature.h"
#include "third_party/blink/renderer/core/html/canvas/canvas_async_blob_creator.h"
#include "third_party/blink/renderer/core/html/canvas/canvas_context_creation_attributes_core.h"
#include "third_party/blink/renderer/core/html/canvas/canvas_draw_listener.h"
@@ -249,6 +253,15 @@ void HTMLCanvasElement::RegisterRenderingContextFactory(
RenderingContextFactories()[type] = std::move(rendering_context_factory);
}
+void HTMLCanvasElement::RecordIdentifiabilityMetric(
+ const blink::IdentifiableSurface& surface,
+ int64_t value) const {
+ blink::IdentifiabilityMetricBuilder(
+ base::UkmSourceId::FromInt64(GetDocument().UkmSourceID()))
+ .Set(surface, value)
+ .Record(GetDocument().UkmRecorder());
+}
+
CanvasRenderingContext* HTMLCanvasElement::GetCanvasRenderingContext(
const String& type,
const CanvasContextCreationAttributesCore& attributes) {
@@ -271,8 +284,14 @@ CanvasRenderingContext* HTMLCanvasElement::GetCanvasRenderingContextInternal(
}
// Log the aliased context type used.
- if (!context_)
+ if (!context_) {
+ RecordIdentifiabilityMetric(
+ blink::IdentifiableSurface::FromTypeAndInput(
+ blink::IdentifiableSurface::Type::kWebFeature,
+ static_cast<uint64_t>(blink::WebFeature::kCanvasRenderingContext)),
+ blink::IdentifiabilityDigestHelper(context_type));
UMA_HISTOGRAM_ENUMERATION("Blink.Canvas.ContextType", context_type);
+ }
context_type =
CanvasRenderingContext::ResolveContextTypeAliases(context_type);
@@ -354,6 +373,20 @@ CanvasRenderingContext* HTMLCanvasElement::GetCanvasRenderingContextInternal(
return context_.Get();
}
+ScriptPromise HTMLCanvasElement::convertToBlob(
+ ScriptState* script_state,
+ const ImageEncodeOptions* options,
+ ExceptionState& exception_state) {
+ RecordIdentifiabilityMetric(
+ blink::IdentifiableSurface::FromTypeAndInput(
+ blink::IdentifiableSurface::Type::kCanvasReadback,
+ context_ ? context_->GetContextType()
+ : CanvasRenderingContext::kContextTypeUnknown),
+ 0);
+ return CanvasRenderingContextHost::convertToBlob(script_state, options,
+ exception_state);
+}
+
bool HTMLCanvasElement::ShouldBeDirectComposited() const {
return (context_ && context_->IsComposited()) || (!!surface_layer_bridge_);
}
@@ -694,6 +727,16 @@ bool HTMLCanvasElement::LowLatencyEnabled() const {
return !!frame_dispatcher_;
}
+void HTMLCanvasElement::UpdateFilterQuality() {
+ if (IsOffscreenCanvasRegistered())
+ UpdateOffscreenCanvasFilterQuality(FilterQuality());
+
+ if (context_ && Is3d())
+ context_->SetFilterQuality(FilterQuality());
+ else if (canvas2d_bridge_)
+ canvas2d_bridge_->UpdateFilterQuality();
+}
+
// In some instances we don't actually want to paint to the parent layer
// We still might want to set filter quality and MarkFirstContentfulPaint though
void HTMLCanvasElement::Paint(GraphicsContext& context,
@@ -724,11 +767,6 @@ void HTMLCanvasElement::Paint(GraphicsContext& context,
if (!context_ && !OffscreenCanvasFrame())
return;
- if (Is3d())
- context_->SetFilterQuality(FilterQuality());
- else if (canvas2d_bridge_)
- canvas2d_bridge_->UpdateFilterQuality();
-
if (HasResourceProvider() && !canvas_is_clear_)
PaintTiming::From(GetDocument()).MarkFirstContentfulPaint();
@@ -920,6 +958,12 @@ String HTMLCanvasElement::ToDataURLInternal(
// Currently we only support three encoding types.
NOTREACHED();
}
+ RecordIdentifiabilityMetric(
+ blink::IdentifiableSurface::FromTypeAndInput(
+ blink::IdentifiableSurface::Type::kCanvasReadback,
+ context_ ? context_->GetContextType()
+ : CanvasRenderingContext::kContextTypeUnknown),
+ 0);
return data_url;
}
@@ -986,6 +1030,13 @@ void HTMLCanvasElement::toBlob(V8BlobCallback* callback,
GetExecutionContext());
}
+ RecordIdentifiabilityMetric(
+ blink::IdentifiableSurface::FromTypeAndInput(
+ blink::IdentifiableSurface::Type::kCanvasReadback,
+ context_ ? context_->GetContextType()
+ : CanvasRenderingContext::kContextTypeUnknown),
+ 0);
+
if (async_creator) {
async_creator->ScheduleAsyncBlobCreation(quality);
} else {
@@ -1317,12 +1368,9 @@ IntSize HTMLCanvasElement::BitmapSourceSize() const {
ScriptPromise HTMLCanvasElement::CreateImageBitmap(
ScriptState* script_state,
- EventTarget& event_target,
base::Optional<IntRect> crop_rect,
const ImageBitmapOptions* options,
ExceptionState& exception_state) {
- DCHECK(event_target.ToLocalDOMWindow());
-
return ImageBitmapSource::FulfillImageBitmap(
script_state, MakeGarbageCollected<ImageBitmap>(this, crop_rect, options),
exception_state);
@@ -1427,7 +1475,8 @@ void HTMLCanvasElement::CreateLayer() {
// We do not design transferControlToOffscreen() for frame-less HTML canvas.
if (frame) {
surface_layer_bridge_ = std::make_unique<::blink::SurfaceLayerBridge>(
- frame->GetPage()->GetChromeClient().GetFrameSinkId(frame), this,
+ frame->GetPage()->GetChromeClient().GetFrameSinkId(frame),
+ ::blink::SurfaceLayerBridge::ContainsVideo::kNo, this,
base::DoNothing());
// Creates a placeholder layer first before Surface is created.
surface_layer_bridge_->CreateSolidColorLayer();
diff --git a/chromium/third_party/blink/renderer/core/html/canvas/html_canvas_element.h b/chromium/third_party/blink/renderer/core/html/canvas/html_canvas_element.h
index c929303ec30..e36e9a211ab 100644
--- a/chromium/third_party/blink/renderer/core/html/canvas/html_canvas_element.h
+++ b/chromium/third_party/blink/renderer/core/html/canvas/html_canvas_element.h
@@ -32,6 +32,7 @@
#include "base/memory/weak_ptr.h"
#include "base/single_thread_task_runner.h"
+#include "third_party/blink/public/common/privacy_budget/identifiable_surface.h"
#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_blob_callback.h"
#include "third_party/blink/renderer/core/core_export.h"
@@ -154,6 +155,7 @@ class CORE_EXPORT HTMLCanvasElement final
void DidDraw(const FloatRect&) override;
void DidDraw() override;
+ void UpdateFilterQuality();
void Paint(GraphicsContext&,
const PhysicalRect&,
bool flatten_composited_layers);
@@ -232,7 +234,6 @@ class CORE_EXPORT HTMLCanvasElement final
// ImageBitmapSource implementation
IntSize BitmapSourceSize() const override;
ScriptPromise CreateImageBitmap(ScriptState*,
- EventTarget&,
base::Optional<IntRect> crop_rect,
const ImageBitmapOptions*,
ExceptionState&) override;
@@ -289,6 +290,10 @@ class CORE_EXPORT HTMLCanvasElement final
context_creation_was_blocked_ = true;
}
+ ScriptPromise convertToBlob(ScriptState*,
+ const ImageEncodeOptions*,
+ ExceptionState&) override;
+
bool NeedsUnbufferedInputEvents() const { return needs_unbuffered_input_; }
void SetNeedsUnbufferedInputEvents(bool value) {
@@ -314,6 +319,9 @@ class CORE_EXPORT HTMLCanvasElement final
private:
void Dispose();
+ void RecordIdentifiabilityMetric(const blink::IdentifiableSurface& surface,
+ int64_t value) const;
+
void PaintInternal(GraphicsContext&, const PhysicalRect&);
using ContextFactoryVector =
diff --git a/chromium/third_party/blink/renderer/core/html/canvas/image_data.cc b/chromium/third_party/blink/renderer/core/html/canvas/image_data.cc
index eb28b745ed9..099510256d3 100644
--- a/chromium/third_party/blink/renderer/core/html/canvas/image_data.cc
+++ b/chromium/third_party/blink/renderer/core/html/canvas/image_data.cc
@@ -463,7 +463,7 @@ ImageData* ImageData::CreateImageData(ImageDataArray& data,
NOTREACHED();
}
- if (storage_format_name != color_settings->storageFormat())
+ if (color_settings->storageFormat() != storage_format_name)
color_settings->setStorageFormat(storage_format_name);
if (!ImageData::ValidateConstructorArguments(
@@ -550,7 +550,6 @@ ImageData* ImageData::CropRect(const IntRect& crop_rect, bool flip_y) {
}
ScriptPromise ImageData::CreateImageBitmap(ScriptState* script_state,
- EventTarget& event_target,
base::Optional<IntRect> crop_rect,
const ImageBitmapOptions* options,
ExceptionState& exception_state) {
diff --git a/chromium/third_party/blink/renderer/core/html/canvas/image_data.h b/chromium/third_party/blink/renderer/core/html/canvas/image_data.h
index 6690cd30bb7..4101d0fa9b2 100644
--- a/chromium/third_party/blink/renderer/core/html/canvas/image_data.h
+++ b/chromium/third_party/blink/renderer/core/html/canvas/image_data.h
@@ -154,7 +154,6 @@ class CORE_EXPORT ImageData final : public ScriptWrappable,
// ImageBitmapSource implementation
IntSize BitmapSourceSize() const override { return size_; }
ScriptPromise CreateImageBitmap(ScriptState*,
- EventTarget&,
base::Optional<IntRect> crop_rect,
const ImageBitmapOptions*,
ExceptionState&) override;
diff --git a/chromium/third_party/blink/renderer/core/html/canvas/image_element_base.cc b/chromium/third_party/blink/renderer/core/html/canvas/image_element_base.cc
index 86980200a42..33076248c58 100644
--- a/chromium/third_party/blink/renderer/core/html/canvas/image_element_base.cc
+++ b/chromium/third_party/blink/renderer/core/html/canvas/image_element_base.cc
@@ -123,12 +123,9 @@ IntSize ImageElementBase::BitmapSourceSize() const {
ScriptPromise ImageElementBase::CreateImageBitmap(
ScriptState* script_state,
- EventTarget& event_target,
base::Optional<IntRect> crop_rect,
const ImageBitmapOptions* options,
ExceptionState& exception_state) {
- DCHECK(event_target.ToLocalDOMWindow());
-
ImageResourceContent* image_content = CachedImage();
if (!image_content) {
exception_state.ThrowDOMException(
@@ -148,15 +145,10 @@ ScriptPromise ImageElementBase::CreateImageBitmap(
"specified.");
return ScriptPromise();
}
- return ImageBitmap::CreateAsync(this, crop_rect,
- event_target.ToLocalDOMWindow()->document(),
- script_state, options);
+ return ImageBitmap::CreateAsync(this, crop_rect, script_state, options);
}
return ImageBitmapSource::FulfillImageBitmap(
- script_state,
- MakeGarbageCollected<ImageBitmap>(
- this, crop_rect, event_target.ToLocalDOMWindow()->document(),
- options),
+ script_state, MakeGarbageCollected<ImageBitmap>(this, crop_rect, options),
exception_state);
}
diff --git a/chromium/third_party/blink/renderer/core/html/canvas/image_element_base.h b/chromium/third_party/blink/renderer/core/html/canvas/image_element_base.h
index 25c5d8f8468..05a08421d22 100644
--- a/chromium/third_party/blink/renderer/core/html/canvas/image_element_base.h
+++ b/chromium/third_party/blink/renderer/core/html/canvas/image_element_base.h
@@ -28,7 +28,6 @@ class CORE_EXPORT ImageElementBase : public CanvasImageSource,
IntSize BitmapSourceSize() const override;
ScriptPromise CreateImageBitmap(ScriptState*,
- EventTarget&,
base::Optional<IntRect>,
const ImageBitmapOptions*,
ExceptionState&) override;
diff --git a/chromium/third_party/blink/renderer/core/html/custom/custom_element.cc b/chromium/third_party/blink/renderer/core/html/custom/custom_element.cc
index 1a031cecfab..eeca328bf00 100644
--- a/chromium/third_party/blink/renderer/core/html/custom/custom_element.cc
+++ b/chromium/third_party/blink/renderer/core/html/custom/custom_element.cc
@@ -305,8 +305,7 @@ void CustomElement::EnqueueFormStateRestoreCallback(
}
}
-void CustomElement::TryToUpgrade(Element& element,
- bool upgrade_invisible_elements) {
+void CustomElement::TryToUpgrade(Element& element) {
// Try to upgrade an element
// https://html.spec.whatwg.org/C/#concept-try-upgrade
@@ -320,7 +319,7 @@ void CustomElement::TryToUpgrade(Element& element,
registry->DefinitionFor(CustomElementDescriptor(
is_value.IsNull() ? element.localName() : is_value,
element.localName())))
- definition->EnqueueUpgradeReaction(element, upgrade_invisible_elements);
+ definition->EnqueueUpgradeReaction(element);
else
registry->AddCandidate(element);
}
diff --git a/chromium/third_party/blink/renderer/core/html/custom/custom_element.h b/chromium/third_party/blink/renderer/core/html/custom/custom_element.h
index 16e077eb151..e30afccf52a 100644
--- a/chromium/third_party/blink/renderer/core/html/custom/custom_element.h
+++ b/chromium/third_party/blink/renderer/core/html/custom/custom_element.h
@@ -116,7 +116,7 @@ class CORE_EXPORT CustomElement {
const FileOrUSVStringOrFormData& value,
const String& mode);
- static void TryToUpgrade(Element&, bool upgrade_invisible_elements = false);
+ static void TryToUpgrade(Element&);
static void AddEmbedderCustomElementNameForTesting(const AtomicString& name,
ExceptionState&);
diff --git a/chromium/third_party/blink/renderer/core/html/custom/custom_element_definition.cc b/chromium/third_party/blink/renderer/core/html/custom/custom_element_definition.cc
index c5e4a121416..3c4b80f4433 100644
--- a/chromium/third_party/blink/renderer/core/html/custom/custom_element_definition.cc
+++ b/chromium/third_party/blink/renderer/core/html/custom/custom_element_definition.cc
@@ -275,11 +275,9 @@ bool CustomElementDefinition::HasStyleAttributeChangedCallback() const {
return has_style_attribute_changed_callback_;
}
-void CustomElementDefinition::EnqueueUpgradeReaction(
- Element& element,
- bool upgrade_invisible_elements) {
- CustomElement::Enqueue(element, CustomElementReactionFactory::CreateUpgrade(
- *this, upgrade_invisible_elements));
+void CustomElementDefinition::EnqueueUpgradeReaction(Element& element) {
+ CustomElement::Enqueue(element,
+ CustomElementReactionFactory::CreateUpgrade(*this));
}
void CustomElementDefinition::EnqueueConnectedCallback(Element& element) {
diff --git a/chromium/third_party/blink/renderer/core/html/custom/custom_element_definition.h b/chromium/third_party/blink/renderer/core/html/custom/custom_element_definition.h
index a3610a2c26f..4df21e145c3 100644
--- a/chromium/third_party/blink/renderer/core/html/custom/custom_element_definition.h
+++ b/chromium/third_party/blink/renderer/core/html/custom/custom_element_definition.h
@@ -98,8 +98,7 @@ class CORE_EXPORT CustomElementDefinition
const FileOrUSVStringOrFormData& value,
const String& mode) = 0;
- void EnqueueUpgradeReaction(Element&,
- bool upgrade_invisible_elements = false);
+ void EnqueueUpgradeReaction(Element&);
void EnqueueConnectedCallback(Element&);
void EnqueueDisconnectedCallback(Element&);
void EnqueueAdoptedCallback(Element&,
diff --git a/chromium/third_party/blink/renderer/core/html/custom/custom_element_reaction_factory.cc b/chromium/third_party/blink/renderer/core/html/custom/custom_element_reaction_factory.cc
index b0a18bad6e4..859dd263529 100644
--- a/chromium/third_party/blink/renderer/core/html/custom/custom_element_reaction_factory.cc
+++ b/chromium/third_party/blink/renderer/core/html/custom/custom_element_reaction_factory.cc
@@ -14,28 +14,18 @@ namespace blink {
class CustomElementUpgradeReaction final : public CustomElementReaction {
public:
- CustomElementUpgradeReaction(CustomElementDefinition& definition,
- bool upgrade_invisible_elements)
- : CustomElementReaction(definition),
- upgrade_invisible_elements_(upgrade_invisible_elements) {}
+ explicit CustomElementUpgradeReaction(CustomElementDefinition& definition)
+ : CustomElementReaction(definition) {}
private:
void Invoke(Element& element) override {
// Don't call Upgrade() if it's already upgraded. Multiple upgrade reactions
// could be enqueued because the state changes in step 10 of upgrades.
// https://html.spec.whatwg.org/C/#upgrades
- if (element.GetCustomElementState() == CustomElementState::kUndefined) {
- // Don't upgrade elements inside an invisible-static tree, unless it was
- // triggered by CustomElementRegistry::upgrade.
- if (!RuntimeEnabledFeatures::InvisibleDOMEnabled() ||
- !element.IsInsideInvisibleStaticSubtree() ||
- upgrade_invisible_elements_)
- definition_->Upgrade(element);
- }
+ if (element.GetCustomElementState() == CustomElementState::kUndefined)
+ definition_->Upgrade(element);
}
- bool upgrade_invisible_elements_;
-
DISALLOW_COPY_AND_ASSIGN(CustomElementUpgradeReaction);
};
@@ -235,10 +225,8 @@ class CustomElementFormStateRestoreCallbackReaction final
// ----------------------------------------------------------------
CustomElementReaction& CustomElementReactionFactory::CreateUpgrade(
- CustomElementDefinition& definition,
- bool upgrade_invisible_elements) {
- return *MakeGarbageCollected<CustomElementUpgradeReaction>(
- definition, upgrade_invisible_elements);
+ CustomElementDefinition& definition) {
+ return *MakeGarbageCollected<CustomElementUpgradeReaction>(definition);
}
CustomElementReaction& CustomElementReactionFactory::CreateConnected(
diff --git a/chromium/third_party/blink/renderer/core/html/custom/custom_element_reaction_factory.h b/chromium/third_party/blink/renderer/core/html/custom/custom_element_reaction_factory.h
index 177bcd7e207..1e74d95cd06 100644
--- a/chromium/third_party/blink/renderer/core/html/custom/custom_element_reaction_factory.h
+++ b/chromium/third_party/blink/renderer/core/html/custom/custom_element_reaction_factory.h
@@ -22,8 +22,7 @@ class CustomElementReactionFactory {
public:
static CustomElementReaction& CreateUpgrade(
- CustomElementDefinition& definition,
- bool upgrade_invisible_elements);
+ CustomElementDefinition& definition);
static CustomElementReaction& CreateConnected(
CustomElementDefinition& definition);
static CustomElementReaction& CreateDisconnected(
diff --git a/chromium/third_party/blink/renderer/core/html/custom/custom_element_registry.cc b/chromium/third_party/blink/renderer/core/html/custom/custom_element_registry.cc
index 59e806f5309..f1579312558 100644
--- a/chromium/third_party/blink/renderer/core/html/custom/custom_element_registry.cc
+++ b/chromium/third_party/blink/renderer/core/html/custom/custom_element_registry.cc
@@ -144,7 +144,7 @@ CustomElementDefinition* CustomElementRegistry::DefineInternal(
// Step 7. customized built-in elements definition
// element interface extends option checks
- if (options->hasExtends()) {
+ if (!options->extends().IsNull()) {
// 7.1. If element interface is valid custom element name, throw exception
const AtomicString& extends = AtomicString(options->extends());
if (ThrowIfValidName(AtomicString(options->extends()), exception_state))
@@ -355,10 +355,8 @@ void CustomElementRegistry::upgrade(Node* root) {
CollectUpgradeCandidateInNode(*root, candidates);
// 2. For each candidate of candidates, try to upgrade candidate.
- for (auto& candidate : candidates) {
- CustomElement::TryToUpgrade(*candidate,
- true /* upgrade_invisible_elements */);
- }
+ for (auto& candidate : candidates)
+ CustomElement::TryToUpgrade(*candidate);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/custom/element_internals.cc b/chromium/third_party/blink/renderer/core/html/custom/element_internals.cc
index d207f394d88..731e5ebcad3 100644
--- a/chromium/third_party/blink/renderer/core/html/custom/element_internals.cc
+++ b/chromium/third_party/blink/renderer/core/html/custom/element_internals.cc
@@ -321,30 +321,6 @@ void ElementInternals::SetElementArrayAttribute(
}
}
-HeapVector<Member<Element>> ElementInternals::GetElementArrayAttribute(
- const QualifiedName& name,
- bool is_null) {
- is_null = true;
- auto iter = explicitly_set_attr_elements_map_.find(name);
- if (iter != explicitly_set_attr_elements_map_.end()) {
- is_null = false;
- return *(iter->value);
- }
- return HeapVector<Member<Element>>();
-}
-
-void ElementInternals::SetElementArrayAttribute(
- const QualifiedName& name,
- HeapVector<Member<Element>> elements,
- bool is_null) {
- if (is_null) {
- explicitly_set_attr_elements_map_.erase(name);
- return;
- }
- explicitly_set_attr_elements_map_.Set(
- name, MakeGarbageCollected<HeapVector<Member<Element>>>(elements));
-}
-
bool ElementInternals::IsTargetFormAssociated() const {
if (Target().IsFormAssociatedCustomElement())
return true;
diff --git a/chromium/third_party/blink/renderer/core/html/custom/element_internals.h b/chromium/third_party/blink/renderer/core/html/custom/element_internals.h
index dc4133e64e7..18519174b08 100644
--- a/chromium/third_party/blink/renderer/core/html/custom/element_internals.h
+++ b/chromium/third_party/blink/renderer/core/html/custom/element_internals.h
@@ -67,13 +67,6 @@ class CORE_EXPORT ElementInternals : public ScriptWrappable,
void SetElementArrayAttribute(
const QualifiedName& name,
const base::Optional<HeapVector<Member<Element>>>& elements);
- // TODO(crbug.com/1060971): Remove |is_null| version.
- HeapVector<Member<Element>> GetElementArrayAttribute(
- const QualifiedName& name,
- bool is_null); // DEPRECATED
- void SetElementArrayAttribute(const QualifiedName&,
- HeapVector<Member<Element>>,
- bool is_null); // DEPRECATED
bool HasAttribute(const QualifiedName& attribute) const;
const HashMap<QualifiedName, AtomicString>& GetAttributes() const;
diff --git a/chromium/third_party/blink/renderer/core/html/forms/base_button_input_type.cc b/chromium/third_party/blink/renderer/core/html/forms/base_button_input_type.cc
index 6fc142b3b06..793b040d25e 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/base_button_input_type.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/base_button_input_type.cc
@@ -33,6 +33,7 @@
#include "third_party/blink/renderer/core/dom/shadow_root.h"
#include "third_party/blink/renderer/core/dom/text.h"
+#include "third_party/blink/renderer/core/frame/web_feature.h"
#include "third_party/blink/renderer/core/html/forms/html_form_element.h"
#include "third_party/blink/renderer/core/html/forms/html_input_element.h"
#include "third_party/blink/renderer/core/html/parser/html_parser_idioms.h"
@@ -80,6 +81,8 @@ bool BaseButtonInputType::TypeShouldForceLegacyLayout() const {
LayoutObject* BaseButtonInputType::CreateLayoutObject(const ComputedStyle&,
LegacyLayout) const {
+ UseCounter::Count(GetElement().GetDocument(),
+ WebFeature::kLegacyLayoutByButton);
return new LayoutButton(&GetElement());
}
diff --git a/chromium/third_party/blink/renderer/core/html/forms/color_chooser_popup_ui_controller.cc b/chromium/third_party/blink/renderer/core/html/forms/color_chooser_popup_ui_controller.cc
index f61b77e16fe..5dc4c58a213 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/color_chooser_popup_ui_controller.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/color_chooser_popup_ui_controller.cc
@@ -29,6 +29,7 @@
#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/strings/grit/blink_strings.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
#include "third_party/blink/renderer/core/html/forms/chooser_resource_loader.h"
@@ -55,7 +56,8 @@ ColorChooserPopupUIController::ColorChooserPopupUIController(
: ColorChooserUIController(frame, client),
chrome_client_(chrome_client),
popup_(nullptr),
- locale_(Locale::DefaultLocale()) {}
+ locale_(Locale::DefaultLocale()),
+ eye_dropper_chooser_(frame->DomWindow()) {}
ColorChooserPopupUIController::~ColorChooserPopupUIController() {
DCHECK(!popup_);
@@ -63,6 +65,7 @@ ColorChooserPopupUIController::~ColorChooserPopupUIController() {
void ColorChooserPopupUIController::Trace(Visitor* visitor) {
visitor->Trace(chrome_client_);
+ visitor->Trace(eye_dropper_chooser_);
ColorChooserUIController::Trace(visitor);
}
@@ -117,6 +120,29 @@ void ColorChooserPopupUIController::WriteColorPickerDocument(
AddProperty("isBorderTransparent", features::IsFormControlsRefreshEnabled(),
data);
#endif
+ // We don't create PagePopups on Android, so these strings are excluded
+ // from blink_strings.grd on Android to save binary size. We have to
+ // exclude them here as well to avoid an Android build break.
+#if !defined(OS_ANDROID)
+ AddLocalizedProperty("axColorWellLabel", IDS_AX_COLOR_WELL, data);
+ AddLocalizedProperty("axColorWellRoleDescription",
+ IDS_AX_COLOR_WELL_ROLEDESCRIPTION, data);
+ AddLocalizedProperty("axHueSliderLabel", IDS_AX_COLOR_HUE_SLIDER, data);
+ AddLocalizedProperty("axHexadecimalEditLabel", IDS_AX_COLOR_EDIT_HEXADECIMAL,
+ data);
+ AddLocalizedProperty("axRedEditLabel", IDS_AX_COLOR_EDIT_RED, data);
+ AddLocalizedProperty("axGreenEditLabel", IDS_AX_COLOR_EDIT_GREEN, data);
+ AddLocalizedProperty("axBlueEditLabel", IDS_AX_COLOR_EDIT_BLUE, data);
+ AddLocalizedProperty("axHueEditLabel", IDS_AX_COLOR_EDIT_HUE, data);
+ AddLocalizedProperty("axSaturationEditLabel", IDS_AX_COLOR_EDIT_SATURATION,
+ data);
+ AddLocalizedProperty("axLightnessEditLabel", IDS_AX_COLOR_EDIT_LIGHTNESS,
+ data);
+ AddLocalizedProperty("axFormatTogglerLabel", IDS_AX_COLOR_FORMAT_TOGGLER,
+ data);
+#else
+ CHECK(false) << "We should never reach PagePopupClient code on Android";
+#endif
PagePopupClient::AddString("};\n", data);
data->Append(ChooserResourceLoader::GetPickerCommonJS());
data->Append(ChooserResourceLoader::GetColorPickerJS());
@@ -146,9 +172,8 @@ void ColorChooserPopupUIController::WriteColorSuggestionPickerDocument(
"window.dialogArguments = {\n",
data);
PagePopupClient::AddProperty("values", suggestion_values, data);
- PagePopupClient::AddProperty(
- "otherColorLabel", GetLocale().QueryString(IDS_FORM_OTHER_COLOR_LABEL),
- data);
+ PagePopupClient::AddLocalizedProperty("otherColorLabel",
+ IDS_FORM_OTHER_COLOR_LABEL, data);
if (features::IsFormControlsRefreshEnabled()) {
PagePopupClient::AddProperty("selectedColor",
client_->CurrentColor().Serialized(), data);
@@ -225,18 +250,30 @@ void ColorChooserPopupUIController::CancelPopup() {
}
PagePopupController* ColorChooserPopupUIController::CreatePagePopupController(
+ Page& page,
PagePopup& popup) {
- return MakeGarbageCollected<ColorPagePopupController>(popup, this);
+ return MakeGarbageCollected<ColorPagePopupController>(page, popup, this);
}
void ColorChooserPopupUIController::EyeDropperResponseHandler(bool success,
uint32_t color) {
- // TODO(crbug.com/992297): update the color popup with the chosen value.
+ eye_dropper_chooser_.reset();
+
+ if (!popup_)
+ return;
+ // Notify the popup that there is a response from the eye dropper.
+ scoped_refptr<SharedBuffer> data = SharedBuffer::Create();
+ PagePopupClient::AddString("window.updateData = {\n", data.get());
+ AddProperty("success", success, data.get());
+ AddProperty("color", Color(color).Serialized(), data.get());
+ PagePopupClient::AddString("}\n", data.get());
+ popup_->PostMessageToPopup(String::FromUTF8(data->Data(), data->size()));
}
void ColorChooserPopupUIController::OpenEyeDropper() {
frame_->GetBrowserInterfaceBroker().GetInterface(
- eye_dropper_chooser_.BindNewPipeAndPassReceiver());
+ eye_dropper_chooser_.BindNewPipeAndPassReceiver(
+ frame_->GetTaskRunner(TaskType::kUserInteraction)));
eye_dropper_chooser_.set_disconnect_handler(WTF::Bind(
&ColorChooserPopupUIController::EndChooser, WrapWeakPersistent(this)));
eye_dropper_chooser_->Choose(
diff --git a/chromium/third_party/blink/renderer/core/html/forms/color_chooser_popup_ui_controller.h b/chromium/third_party/blink/renderer/core/html/forms/color_chooser_popup_ui_controller.h
index fd20189266e..0984c237224 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/color_chooser_popup_ui_controller.h
+++ b/chromium/third_party/blink/renderer/core/html/forms/color_chooser_popup_ui_controller.h
@@ -29,11 +29,14 @@
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/html/forms/color_chooser_ui_controller.h"
#include "third_party/blink/renderer/core/page/page_popup_client.h"
+#include "third_party/blink/renderer/platform/mojo/heap_mojo_remote.h"
+#include "third_party/blink/renderer/platform/mojo/heap_mojo_wrapper_mode.h"
namespace blink {
class ChromeClient;
class ColorChooserClient;
+class Page;
class PagePopup;
class PagePopupController;
@@ -62,7 +65,7 @@ class CORE_EXPORT ColorChooserPopupUIController final
void CancelPopup() override;
Element& OwnerElement() override;
void DidClosePopup() override;
- PagePopupController* CreatePagePopupController(PagePopup&) override;
+ PagePopupController* CreatePagePopupController(Page&, PagePopup&) override;
void OpenEyeDropper();
void EyeDropperResponseHandler(bool success, uint32_t color);
@@ -78,7 +81,9 @@ class CORE_EXPORT ColorChooserPopupUIController final
Member<ChromeClient> chrome_client_;
PagePopup* popup_;
Locale& locale_;
- mojo::Remote<mojom::blink::EyeDropperChooser> eye_dropper_chooser_;
+ HeapMojoRemote<mojom::blink::EyeDropperChooser,
+ HeapMojoWrapperMode::kWithoutContextObserver>
+ eye_dropper_chooser_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/forms/color_chooser_ui_controller.h b/chromium/third_party/blink/renderer/core/html/forms/color_chooser_ui_controller.h
index 69168e082da..bccebbd339f 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/color_chooser_ui_controller.h
+++ b/chromium/third_party/blink/renderer/core/html/forms/color_chooser_ui_controller.h
@@ -74,6 +74,7 @@ class CORE_EXPORT ColorChooserUIController
private:
mojo::Remote<mojom::blink::ColorChooserFactory> color_chooser_factory_;
HeapMojoReceiver<mojom::blink::ColorChooserClient,
+ ColorChooserUIController,
HeapMojoWrapperMode::kWithoutContextObserver>
receiver_;
};
diff --git a/chromium/third_party/blink/renderer/core/html/forms/date_time_chooser_impl.cc b/chromium/third_party/blink/renderer/core/html/forms/date_time_chooser_impl.cc
index beb631c63c6..ca0dababf14 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/date_time_chooser_impl.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/date_time_chooser_impl.cc
@@ -123,7 +123,10 @@ void DateTimeChooserImpl::WriteDocument(SharedBuffer* data) {
GetLocale().QueryString(IDS_FORM_OTHER_DATE_LABEL);
}
- AddString("<!DOCTYPE html><head><meta charset='UTF-8'><style>\n", data);
+ AddString(
+ "<!DOCTYPE html><head><meta charset='UTF-8'><meta name='color-scheme' "
+ "content='light,dark'><style>\n",
+ data);
data->Append(ChooserResourceLoader::GetPickerCommonStyleSheet());
if (!features::IsFormControlsRefreshEnabled())
@@ -158,28 +161,20 @@ void DateTimeChooserImpl::WriteDocument(SharedBuffer* data) {
data);
AddProperty("locale", parameters_->locale.GetString(), data);
AddProperty("todayLabel", today_label_string, data);
- AddProperty("clearLabel", GetLocale().QueryString(IDS_FORM_CALENDAR_CLEAR),
- data);
- AddProperty("weekLabel", GetLocale().QueryString(IDS_FORM_WEEK_NUMBER_LABEL),
- data);
- AddProperty("axShowMonthSelector",
- GetLocale().QueryString(IDS_AX_CALENDAR_SHOW_MONTH_SELECTOR),
- data);
- AddProperty("axShowNextMonth",
- GetLocale().QueryString(IDS_AX_CALENDAR_SHOW_NEXT_MONTH), data);
- AddProperty("axShowPreviousMonth",
- GetLocale().QueryString(IDS_AX_CALENDAR_SHOW_PREVIOUS_MONTH),
- data);
- AddProperty("axHourLabel", GetLocale().QueryString(IDS_AX_HOUR_FIELD_TEXT),
- data);
- AddProperty("axMinuteLabel",
- GetLocale().QueryString(IDS_AX_MINUTE_FIELD_TEXT), data);
- AddProperty("axSecondLabel",
- GetLocale().QueryString(IDS_AX_SECOND_FIELD_TEXT), data);
- AddProperty("axMillisecondLabel",
- GetLocale().QueryString(IDS_AX_MILLISECOND_FIELD_TEXT), data);
- AddProperty("axAmPmLabel", GetLocale().QueryString(IDS_AX_AM_PM_FIELD_TEXT),
- data);
+ AddLocalizedProperty("clearLabel", IDS_FORM_CALENDAR_CLEAR, data);
+ AddLocalizedProperty("weekLabel", IDS_FORM_WEEK_NUMBER_LABEL, data);
+ AddLocalizedProperty("axShowMonthSelector",
+ IDS_AX_CALENDAR_SHOW_MONTH_SELECTOR, data);
+ AddLocalizedProperty("axShowNextMonth", IDS_AX_CALENDAR_SHOW_NEXT_MONTH,
+ data);
+ AddLocalizedProperty("axShowPreviousMonth",
+ IDS_AX_CALENDAR_SHOW_PREVIOUS_MONTH, data);
+ AddLocalizedProperty("axHourLabel", IDS_AX_HOUR_FIELD_TEXT, data);
+ AddLocalizedProperty("axMinuteLabel", IDS_AX_MINUTE_FIELD_TEXT, data);
+ AddLocalizedProperty("axSecondLabel", IDS_AX_SECOND_FIELD_TEXT, data);
+ AddLocalizedProperty("axMillisecondLabel", IDS_AX_MILLISECOND_FIELD_TEXT,
+ data);
+ AddLocalizedProperty("axAmPmLabel", IDS_AX_AM_PM_FIELD_TEXT, data);
AddProperty("weekStartDay", locale_->FirstDayOfWeek(), data);
AddProperty("shortMonthLabels", locale_->ShortMonthLabels(), data);
AddProperty("dayLabels", locale_->WeekDayShortLabels(), data);
@@ -221,9 +216,9 @@ void DateTimeChooserImpl::WriteDocument(SharedBuffer* data) {
data);
AddProperty("otherDateLabel", other_date_label_string, data);
- DCHECK(OwnerElement().GetComputedStyle());
+ const ComputedStyle* style = OwnerElement().GetComputedStyle();
WebColorScheme color_scheme =
- OwnerElement().GetComputedStyle()->UsedColorScheme();
+ style ? style->UsedColorScheme() : WebColorScheme::kLight;
AddProperty("suggestionHighlightColor",
LayoutTheme::GetTheme()
diff --git a/chromium/third_party/blink/renderer/core/html/forms/date_time_field_element.cc b/chromium/third_party/blink/renderer/core/html/forms/date_time_field_element.cc
index 13dbe846f5b..43011524c79 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/date_time_field_element.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/date_time_field_element.cc
@@ -28,7 +28,11 @@
#include "third_party/blink/renderer/core/css/style_change_reason.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/text.h"
+#include "third_party/blink/renderer/core/editing/frame_selection.h"
+#include "third_party/blink/renderer/core/editing/position.h"
+#include "third_party/blink/renderer/core/editing/selection_template.h"
#include "third_party/blink/renderer/core/events/keyboard_event.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/html_names.h"
#include "third_party/blink/renderer/core/layout/text_run_constructor.h"
#include "third_party/blink/renderer/core/style/computed_style.h"
@@ -134,6 +138,15 @@ void DateTimeFieldElement::SetFocused(bool value,
if (field_owner_) {
if (value) {
field_owner_->DidFocusOnField(focus_type);
+ GetDocument().GetFrame()->Selection().SetSelection(
+ SelectionInDOMTree::Builder()
+ .Collapse(Position::FirstPositionInNode(*this))
+ .Build(),
+ SetSelectionOptions::Builder()
+ .SetShouldCloseTyping(true)
+ .SetShouldClearTypingStyle(true)
+ .SetDoNotSetFocus(true)
+ .Build());
} else {
field_owner_->DidBlurFromField(focus_type);
}
diff --git a/chromium/third_party/blink/renderer/core/html/forms/external_popup_menu.cc b/chromium/third_party/blink/renderer/core/html/forms/external_popup_menu.cc
index f7aab03b544..25090b9a149 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/external_popup_menu.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/external_popup_menu.cc
@@ -31,14 +31,10 @@
#include "third_party/blink/renderer/core/html/forms/external_popup_menu.h"
#include "build/build_config.h"
+#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
+#include "third_party/blink/public/common/input/web_coalesced_input_event.h"
#include "third_party/blink/public/common/input/web_mouse_event.h"
#include "third_party/blink/public/platform/task_type.h"
-#include "third_party/blink/public/platform/web_coalesced_input_event.h"
-#include "third_party/blink/public/platform/web_vector.h"
-#include "third_party/blink/public/web/web_external_popup_menu.h"
-#include "third_party/blink/public/web/web_local_frame_client.h"
-#include "third_party/blink/public/web/web_menu_item_info.h"
-#include "third_party/blink/public/web/web_popup_menu_info.h"
#include "third_party/blink/renderer/core/dom/node_computed_style.h"
#include "third_party/blink/renderer/core/events/current_input_event.h"
#include "third_party/blink/renderer/core/exported/web_view_impl.h"
@@ -49,14 +45,12 @@
#include "third_party/blink/renderer/core/html/forms/html_option_element.h"
#include "third_party/blink/renderer/core/html/forms/html_select_element.h"
#include "third_party/blink/renderer/core/layout/layout_box.h"
+#include "third_party/blink/renderer/core/page/chrome_client.h"
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/core/style/computed_style.h"
#include "third_party/blink/renderer/platform/geometry/float_quad.h"
#include "third_party/blink/renderer/platform/geometry/int_point.h"
#include "third_party/blink/renderer/platform/text/text_direction.h"
-#if defined(OS_MACOSX)
-#include "third_party/blink/renderer/core/page/chrome_client.h"
-#endif
namespace blink {
@@ -67,33 +61,39 @@ ExternalPopupMenu::ExternalPopupMenu(LocalFrame& frame,
dispatch_event_timer_(frame.GetTaskRunner(TaskType::kInternalDefault),
this,
&ExternalPopupMenu::DispatchEvent),
- web_external_popup_menu_(nullptr) {}
+ receiver_(this, owner_element.GetExecutionContext()) {}
ExternalPopupMenu::~ExternalPopupMenu() = default;
void ExternalPopupMenu::Trace(Visitor* visitor) {
visitor->Trace(owner_element_);
visitor->Trace(local_frame_);
+ visitor->Trace(receiver_);
PopupMenu::Trace(visitor);
}
+void ExternalPopupMenu::Reset() {
+ receiver_.reset();
+}
+
bool ExternalPopupMenu::ShowInternal() {
// Blink core reuses the PopupMenu of an element. For simplicity, we do
- // recreate the actual external popup everytime.
- if (web_external_popup_menu_) {
- web_external_popup_menu_->Close();
- web_external_popup_menu_ = nullptr;
- }
-
- WebPopupMenuInfo info;
- GetPopupMenuInfo(info, *owner_element_);
- if (info.items.empty())
+ // recreate the actual external popup every time.
+ Reset();
+
+ int32_t item_height;
+ double font_size;
+ int32_t selected_item;
+ Vector<mojom::blink::MenuItemPtr> menu_items;
+ bool right_aligned;
+ bool allow_multiple_selection;
+ GetPopupMenuInfo(*owner_element_, &item_height, &font_size, &selected_item,
+ &menu_items, &right_aligned, &allow_multiple_selection);
+ if (menu_items.IsEmpty())
return false;
- WebLocalFrameImpl* webframe =
- WebLocalFrameImpl::FromFrame(local_frame_.Get());
- web_external_popup_menu_ =
- webframe->Client()->CreateExternalPopupMenu(info, this);
- if (web_external_popup_menu_) {
+
+ auto* execution_context = owner_element_->GetExecutionContext();
+ if (!receiver_.is_bound()) {
LayoutObject* layout_object = owner_element_->GetLayoutObject();
if (!layout_object || !layout_object->IsBox())
return false;
@@ -102,7 +102,20 @@ bool ExternalPopupMenu::ShowInternal() {
->LocalToAbsoluteRect(
ToLayoutBox(layout_object)->PhysicalBorderBoxRect()));
IntRect rect_in_viewport = local_frame_->View()->FrameToViewport(rect);
- web_external_popup_menu_->Show(rect_in_viewport);
+ float scale_for_emulation = WebLocalFrameImpl::FromFrame(local_frame_)
+ ->LocalRootFrameWidget()
+ ->Client()
+ ->GetEmulatorScale();
+
+ gfx::Rect bounds =
+ gfx::Rect(rect_in_viewport.X() * scale_for_emulation,
+ rect_in_viewport.Y() * scale_for_emulation,
+ rect_in_viewport.Width(), rect_in_viewport.Height());
+ local_frame_->GetLocalFrameHostRemote().ShowPopupMenu(
+ receiver_.BindNewPipeAndPassRemote(execution_context->GetTaskRunner(
+ TaskType::kInternalUserInteraction)),
+ bounds, item_height, font_size, selected_item, std::move(menu_items),
+ right_aligned, allow_multiple_selection);
return true;
}
@@ -117,10 +130,11 @@ void ExternalPopupMenu::Show() {
return;
#if defined(OS_MACOSX)
const WebInputEvent* current_event = CurrentInputEvent::Get();
- if (current_event && current_event->GetType() == WebInputEvent::kMouseDown) {
+ if (current_event &&
+ current_event->GetType() == WebInputEvent::Type::kMouseDown) {
synthetic_event_ = std::make_unique<WebMouseEvent>();
*synthetic_event_ = *static_cast<const WebMouseEvent*>(current_event);
- synthetic_event_->SetType(WebInputEvent::kMouseUp);
+ synthetic_event_->SetType(WebInputEvent::Type::kMouseUp);
dispatch_event_timer_.StartOneShot(base::TimeDelta(), FROM_HERE);
// FIXME: show() is asynchronous. If preparing a popup is slow and a
// user released the mouse button before showing the popup, mouseup and
@@ -133,17 +147,15 @@ void ExternalPopupMenu::Show() {
void ExternalPopupMenu::DispatchEvent(TimerBase*) {
WebLocalFrameImpl::FromFrame(local_frame_->LocalFrameRoot())
->FrameWidgetImpl()
- ->HandleInputEvent(blink::WebCoalescedInputEvent(*synthetic_event_));
+ ->HandleInputEvent(
+ blink::WebCoalescedInputEvent(*synthetic_event_, ui::LatencyInfo()));
synthetic_event_.reset();
}
void ExternalPopupMenu::Hide() {
if (owner_element_)
owner_element_->PopupDidHide();
- if (!web_external_popup_menu_)
- return;
- web_external_popup_menu_->Close();
- web_external_popup_menu_ = nullptr;
+ Reset();
}
void ExternalPopupMenu::UpdateFromElement(UpdateReason reason) {
@@ -168,7 +180,7 @@ void ExternalPopupMenu::UpdateFromElement(UpdateReason reason) {
}
void ExternalPopupMenu::Update() {
- if (!web_external_popup_menu_ || !owner_element_)
+ if (!receiver_.is_bound() || !owner_element_)
return;
owner_element_->GetDocument().UpdateStyleAndLayoutTree();
// disconnectClient() might have been called.
@@ -188,32 +200,21 @@ void ExternalPopupMenu::DisconnectClient() {
dispatch_event_timer_.Stop();
}
-void ExternalPopupMenu::DidChangeSelection(int index) {}
+void ExternalPopupMenu::DidAcceptIndices(const Vector<int32_t>& indices) {
+ local_frame_->NotifyUserActivation();
-void ExternalPopupMenu::DidAcceptIndex(int index) {
// Calling methods on the HTMLSelectElement might lead to this object being
// derefed. This ensures it does not get deleted while we are running this
// method.
- int popup_menu_item_index = ToPopupMenuItemIndex(index, *owner_element_);
-
- if (owner_element_) {
- owner_element_->PopupDidHide();
- owner_element_->SelectOptionByPopup(popup_menu_item_index);
- }
- web_external_popup_menu_ = nullptr;
-}
-
-// Android uses this function even for single SELECT.
-void ExternalPopupMenu::DidAcceptIndices(const WebVector<int>& indices) {
if (!owner_element_) {
- web_external_popup_menu_ = nullptr;
+ Reset();
return;
}
HTMLSelectElement* owner_element = owner_element_;
owner_element->PopupDidHide();
- if (indices.empty()) {
+ if (indices.IsEmpty()) {
owner_element->SelectOptionByPopup(-1);
} else if (!owner_element->IsMultiple()) {
owner_element->SelectOptionByPopup(
@@ -226,44 +227,54 @@ void ExternalPopupMenu::DidAcceptIndices(const WebVector<int>& indices) {
list_indices.push_back(ToPopupMenuItemIndex(indices[i], *owner_element));
owner_element->SelectMultipleOptionsByPopup(list_indices);
}
-
- web_external_popup_menu_ = nullptr;
+ Reset();
}
void ExternalPopupMenu::DidCancel() {
+ local_frame_->NotifyUserActivation();
+
if (owner_element_)
owner_element_->PopupDidHide();
- web_external_popup_menu_ = nullptr;
+ Reset();
}
-void ExternalPopupMenu::GetPopupMenuInfo(WebPopupMenuInfo& info,
- HTMLSelectElement& owner_element) {
+void ExternalPopupMenu::GetPopupMenuInfo(
+ HTMLSelectElement& owner_element,
+ int32_t* item_height,
+ double* font_size,
+ int32_t* selected_item,
+ Vector<mojom::blink::MenuItemPtr>* menu_items,
+ bool* right_aligned,
+ bool* allow_multiple_selection) {
const HeapVector<Member<HTMLElement>>& list_items =
owner_element.GetListItems();
wtf_size_t item_count = list_items.size();
- wtf_size_t count = 0;
- Vector<WebMenuItemInfo> items(item_count);
for (wtf_size_t i = 0; i < item_count; ++i) {
if (owner_element.ItemIsDisplayNone(*list_items[i]))
continue;
Element& item_element = *list_items[i];
- WebMenuItemInfo& popup_item = items[count++];
- popup_item.label = owner_element.ItemText(item_element);
- popup_item.tool_tip = item_element.title();
- popup_item.checked = false;
+ auto popup_item = mojom::blink::MenuItem::New();
+ popup_item->label = owner_element.ItemText(item_element);
+ popup_item->tool_tip = item_element.title();
+ popup_item->checked = false;
if (IsA<HTMLHRElement>(item_element)) {
- popup_item.type = WebMenuItemInfo::kSeparator;
+ popup_item->type = mojom::blink::MenuItem::Type::kSeparator;
} else if (IsA<HTMLOptGroupElement>(item_element)) {
- popup_item.type = WebMenuItemInfo::kGroup;
+ popup_item->type = mojom::blink::MenuItem::Type::kGroup;
} else {
- popup_item.type = WebMenuItemInfo::kOption;
- popup_item.checked = To<HTMLOptionElement>(item_element).Selected();
+ popup_item->type = mojom::blink::MenuItem::Type::kOption;
+ popup_item->checked = To<HTMLOptionElement>(item_element).Selected();
}
- popup_item.enabled = !item_element.IsDisabledFormControl();
+ popup_item->enabled = !item_element.IsDisabledFormControl();
const ComputedStyle& style = *owner_element.ItemComputedStyle(item_element);
- popup_item.text_direction = ToBaseTextDirection(style.Direction());
- popup_item.has_text_direction_override = IsOverride(style.GetUnicodeBidi());
+ popup_item->text_direction =
+ style.Direction() == TextDirection::kLtr
+ ? mojo_base::mojom::blink::TextDirection::LEFT_TO_RIGHT
+ : mojo_base::mojom::blink::TextDirection::RIGHT_TO_LEFT;
+ popup_item->has_text_direction_override =
+ IsOverride(style.GetUnicodeBidi());
+ menu_items->push_back(std::move(popup_item));
}
const ComputedStyle& menu_style = owner_element.GetComputedStyle()
@@ -271,16 +282,15 @@ void ExternalPopupMenu::GetPopupMenuInfo(WebPopupMenuInfo& info,
: *owner_element.EnsureComputedStyle();
const SimpleFontData* font_data = menu_style.GetFont().PrimaryFont();
DCHECK(font_data);
- info.item_height = font_data ? font_data->GetFontMetrics().Height() : 0;
- info.item_font_size = static_cast<int>(
+ *item_height = font_data ? font_data->GetFontMetrics().Height() : 0;
+ *font_size = static_cast<int>(
menu_style.GetFont().GetFontDescription().ComputedSize());
- info.selected_index = ToExternalPopupMenuItemIndex(
+ *selected_item = ToExternalPopupMenuItemIndex(
owner_element.SelectedListIndex(), owner_element);
- info.right_aligned = menu_style.Direction() == TextDirection::kRtl;
- info.allow_multiple_selection = owner_element.IsMultiple();
- if (count < item_count)
- items.Shrink(count);
- info.items = items;
+
+ *right_aligned = menu_style.Direction() == TextDirection::kRtl;
+
+ *allow_multiple_selection = owner_element.IsMultiple();
}
int ExternalPopupMenu::ToPopupMenuItemIndex(int external_popup_menu_item_index,
diff --git a/chromium/third_party/blink/renderer/core/html/forms/external_popup_menu.h b/chromium/third_party/blink/renderer/core/html/forms/external_popup_menu.h
index 2c572003d0c..c5429e05b96 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/external_popup_menu.h
+++ b/chromium/third_party/blink/renderer/core/html/forms/external_popup_menu.h
@@ -33,23 +33,24 @@
#include <memory>
#include "cc/paint/paint_canvas.h"
-#include "third_party/blink/public/web/web_external_popup_menu_client.h"
+#include "third_party/blink/public/mojom/choosers/popup_menu.mojom-blink.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/html/forms/popup_menu.h"
+#include "third_party/blink/renderer/platform/mojo/heap_mojo_receiver.h"
+#include "third_party/blink/renderer/platform/mojo/heap_mojo_remote.h"
#include "third_party/blink/renderer/platform/timer.h"
namespace blink {
class HTMLSelectElement;
class LocalFrame;
-class WebExternalPopupMenu;
class WebMouseEvent;
-struct WebPopupMenuInfo;
// The ExternalPopupMenu is a PopupMenu implementation for macOS and Android.
// It uses a OS-native menu implementation.
-class CORE_EXPORT ExternalPopupMenu final : public PopupMenu,
- public WebExternalPopupMenuClient {
+class CORE_EXPORT ExternalPopupMenu final
+ : public PopupMenu,
+ public mojom::blink::PopupMenuClient {
public:
ExternalPopupMenu(LocalFrame&, HTMLSelectElement&);
~ExternalPopupMenu() override;
@@ -58,7 +59,13 @@ class CORE_EXPORT ExternalPopupMenu final : public PopupMenu,
// PopupMenuClient associated with this ExternalPopupMenu.
// FIXME: public only for test access. Need to revert once gtest
// helpers from chromium are available for blink.
- static void GetPopupMenuInfo(WebPopupMenuInfo&, HTMLSelectElement&);
+ static void GetPopupMenuInfo(HTMLSelectElement&,
+ int32_t* item_height,
+ double* font_size,
+ int32_t* selected_item,
+ Vector<mojom::blink::MenuItemPtr>* menu_items,
+ bool* right_aligned,
+ bool* allow_multiple_selection);
static int ToPopupMenuItemIndex(int index, HTMLSelectElement&);
static int ToExternalPopupMenuItemIndex(int index, HTMLSelectElement&);
@@ -71,12 +78,11 @@ class CORE_EXPORT ExternalPopupMenu final : public PopupMenu,
void UpdateFromElement(UpdateReason) override;
void DisconnectClient() override;
- // WebExternalPopupClient methods:
- void DidChangeSelection(int index) override;
- void DidAcceptIndex(int index) override;
- void DidAcceptIndices(const WebVector<int>& indices) override;
+ // mojom::blink::PopupMenuClient methods:
+ void DidAcceptIndices(const Vector<int32_t>& indices) override;
void DidCancel() override;
+ void Reset();
bool ShowInternal();
void DispatchEvent(TimerBase*);
void Update();
@@ -86,7 +92,10 @@ class CORE_EXPORT ExternalPopupMenu final : public PopupMenu,
std::unique_ptr<WebMouseEvent> synthetic_event_;
TaskRunnerTimer<ExternalPopupMenu> dispatch_event_timer_;
// The actual implementor of the show menu.
- WebExternalPopupMenu* web_external_popup_menu_;
+ HeapMojoReceiver<mojom::blink::PopupMenuClient,
+ ExternalPopupMenu,
+ HeapMojoWrapperMode::kWithoutContextObserver>
+ receiver_;
bool needs_update_ = false;
};
diff --git a/chromium/third_party/blink/renderer/core/html/forms/external_popup_menu_test.cc b/chromium/third_party/blink/renderer/core/html/forms/external_popup_menu_test.cc
index a493fa8b0c7..f3a5f8186a5 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/external_popup_menu_test.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/external_popup_menu_test.cc
@@ -7,8 +7,9 @@
#include <memory>
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
+#include "third_party/blink/public/mojom/choosers/popup_menu.mojom-blink.h"
#include "third_party/blink/public/platform/web_url_loader_mock_factory.h"
-#include "third_party/blink/public/web/web_external_popup_menu.h"
#include "third_party/blink/public/web/web_popup_menu_info.h"
#include "third_party/blink/public/web/web_settings.h"
#include "third_party/blink/renderer/core/frame/frame_test_helpers.h"
@@ -16,9 +17,11 @@
#include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
#include "third_party/blink/renderer/core/html/forms/html_select_element.h"
#include "third_party/blink/renderer/core/html/forms/popup_menu.h"
+#include "third_party/blink/renderer/core/html/html_iframe_element.h"
#include "third_party/blink/renderer/core/html_names.h"
#include "third_party/blink/renderer/core/layout/layout_object.h"
#include "third_party/blink/renderer/core/page/page.h"
+#include "third_party/blink/renderer/core/testing/fake_local_frame_host.h"
#include "third_party/blink/renderer/core/testing/page_test_base.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
#include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
@@ -47,9 +50,16 @@ class ExternalPopupMenuDisplayNoneItemsTest : public PageTestBase {
};
TEST_F(ExternalPopupMenuDisplayNoneItemsTest, PopupMenuInfoSizeTest) {
- WebPopupMenuInfo info;
- ExternalPopupMenu::GetPopupMenuInfo(info, *owner_element_);
- EXPECT_EQ(5U, info.items.size());
+ int32_t item_height;
+ double font_size;
+ int32_t selected_item;
+ Vector<mojom::blink::MenuItemPtr> menu_items;
+ bool right_aligned;
+ bool allow_multiple_selection;
+ ExternalPopupMenu::GetPopupMenuInfo(
+ *owner_element_, &item_height, &font_size, &selected_item, &menu_items,
+ &right_aligned, &allow_multiple_selection);
+ EXPECT_EQ(5U, menu_items.size());
}
TEST_F(ExternalPopupMenuDisplayNoneItemsTest, IndexMappingTest) {
@@ -65,31 +75,57 @@ TEST_F(ExternalPopupMenuDisplayNoneItemsTest, IndexMappingTest) {
EXPECT_EQ(-1, ExternalPopupMenu::ToPopupMenuItemIndex(8, *owner_element_));
}
-class ExternalPopupMenuWebFrameClient
- : public frame_test_helpers::TestWebFrameClient {
+class TestLocalFrameExternalPopupClient : public FakeLocalFrameHost {
public:
- WebExternalPopupMenu* CreateExternalPopupMenu(
- const WebPopupMenuInfo&,
- WebExternalPopupMenuClient*) override {
- return &mock_web_external_popup_menu_;
+ void ShowPopupMenu(
+ mojo::PendingRemote<mojom::blink::PopupMenuClient> popup_client,
+ const gfx::Rect& bounds,
+ int32_t item_height,
+ double font_size,
+ int32_t selected_item,
+ Vector<mojom::blink::MenuItemPtr> menu_items,
+ bool right_aligned,
+ bool allow_multiple_selection) override {
+ Reset();
+
+ bounds_ = bounds;
+ selected_item_ = selected_item;
+ menu_items_ = std::move(menu_items);
+ popup_client_.Bind(std::move(popup_client));
+ popup_client_.set_disconnect_handler(base::BindOnce(
+ &TestLocalFrameExternalPopupClient::Reset, base::Unretained(this)));
+ std::move(showed_callback_).Run();
}
- WebRect ShownBounds() const {
- return mock_web_external_popup_menu_.ShownBounds();
+
+ void Reset() { popup_client_.reset(); }
+
+ void WaitUntilShowedPopup() {
+ base::RunLoop run_loop;
+ showed_callback_ = run_loop.QuitClosure();
+ run_loop.Run();
+ }
+
+ mojom::blink::PopupMenuClient* PopupClient() {
+ DCHECK(popup_client_);
+ return popup_client_.get();
+ }
+
+ bool IsBound() const { return popup_client_.is_bound(); }
+
+ const Vector<mojom::blink::MenuItemPtr>& MenuItems() const {
+ return menu_items_;
}
+ int32_t SelectedItem() const { return selected_item_; }
+
+ const gfx::Rect& ShownBounds() const { return bounds_; }
+
private:
- class MockWebExternalPopupMenu : public WebExternalPopupMenu {
- void Show(const WebRect& bounds) override { shown_bounds_ = bounds; }
- void Close() override {}
-
- public:
- WebRect ShownBounds() const { return shown_bounds_; }
-
- private:
- WebRect shown_bounds_;
- };
- WebRect shown_bounds_;
- MockWebExternalPopupMenu mock_web_external_popup_menu_;
+ base::OnceClosure showed_callback_;
+ mojo::Remote<mojom::blink::PopupMenuClient> popup_client_;
+ int32_t selected_item_;
+ Vector<mojom::blink::MenuItemPtr> menu_items_;
+ gfx::Rect bounds_;
};
class ExternalPopupMenuTest : public testing::Test {
@@ -98,6 +134,8 @@ class ExternalPopupMenuTest : public testing::Test {
protected:
void SetUp() override {
+ frame_host_.Init(
+ web_frame_client_.GetRemoteNavigationAssociatedInterfaces());
helper_.Initialize(&web_frame_client_);
WebView()->SetUseExternalPopupMenus(true);
}
@@ -121,14 +159,29 @@ class ExternalPopupMenuTest : public testing::Test {
}
WebViewImpl* WebView() const { return helper_.GetWebView(); }
- const ExternalPopupMenuWebFrameClient& Client() const {
- return web_frame_client_;
+
+ const Vector<mojom::blink::MenuItemPtr>& MenuItems() const {
+ return frame_host_.MenuItems();
}
+
+ bool IsBound() const { return frame_host_.IsBound(); }
+
+ int32_t SelectedItem() const { return frame_host_.SelectedItem(); }
+
+ const gfx::Rect& ShownBounds() const { return frame_host_.ShownBounds(); }
+
+ mojom::blink::PopupMenuClient* PopupClient() {
+ return frame_host_.PopupClient();
+ }
+
+ void WaitUntilShowedPopup() { frame_host_.WaitUntilShowedPopup(); }
+
WebLocalFrameImpl* MainFrame() const { return helper_.LocalMainFrame(); }
private:
+ TestLocalFrameExternalPopupClient frame_host_;
+ frame_test_helpers::TestWebFrameClient web_frame_client_;
std::string base_url_;
- ExternalPopupMenuWebFrameClient web_frame_client_;
frame_test_helpers::WebViewHelper helper_;
};
@@ -160,9 +213,10 @@ TEST_F(ExternalPopupMenuTest, PopupAccountsForVisualViewportTransform) {
WebView()->SetPageScaleFactor(kScaleFactor);
visual_viewport.Move(scroll_delta);
select->ShowPopup();
+ WaitUntilShowedPopup();
- EXPECT_EQ(expected_x, Client().ShownBounds().x);
- EXPECT_EQ(expected_y, Client().ShownBounds().y);
+ EXPECT_EQ(expected_x, ShownBounds().x());
+ EXPECT_EQ(expected_y, ShownBounds().y());
}
TEST_F(ExternalPopupMenuTest, DidAcceptIndex) {
@@ -175,11 +229,13 @@ TEST_F(ExternalPopupMenuTest, DidAcceptIndex) {
ASSERT_TRUE(layout_object);
select->ShowPopup();
+ WaitUntilShowedPopup();
+
ASSERT_TRUE(select->PopupIsVisible());
- WebExternalPopupMenuClient* client =
- static_cast<ExternalPopupMenu*>(select->PopupForTesting());
- client->DidAcceptIndex(2);
+ PopupClient()->DidAcceptIndices({2});
+ base::RunLoop().RunUntilIdle();
+
EXPECT_FALSE(select->PopupIsVisible());
ASSERT_EQ("2", select->InnerElement().innerText().Utf8());
EXPECT_EQ(2, select->selectedIndex());
@@ -195,13 +251,13 @@ TEST_F(ExternalPopupMenuTest, DidAcceptIndices) {
ASSERT_TRUE(layout_object);
select->ShowPopup();
+ WaitUntilShowedPopup();
+
ASSERT_TRUE(select->PopupIsVisible());
- WebExternalPopupMenuClient* client =
- static_cast<ExternalPopupMenu*>(select->PopupForTesting());
- int indices[] = {2};
- WebVector<int> indices_vector(indices, 1);
- client->DidAcceptIndices(indices_vector);
+ PopupClient()->DidAcceptIndices({2});
+ base::RunLoop().RunUntilIdle();
+
EXPECT_FALSE(select->PopupIsVisible());
EXPECT_EQ("2", select->InnerElement().innerText());
EXPECT_EQ(2, select->selectedIndex());
@@ -217,14 +273,136 @@ TEST_F(ExternalPopupMenuTest, DidAcceptIndicesClearSelect) {
ASSERT_TRUE(layout_object);
select->ShowPopup();
+ WaitUntilShowedPopup();
+
ASSERT_TRUE(select->PopupIsVisible());
+ PopupClient()->DidAcceptIndices({});
+ base::RunLoop().RunUntilIdle();
- WebExternalPopupMenuClient* client =
- static_cast<ExternalPopupMenu*>(select->PopupForTesting());
- WebVector<int> indices;
- client->DidAcceptIndices(indices);
EXPECT_FALSE(select->PopupIsVisible());
EXPECT_EQ(-1, select->selectedIndex());
}
+// Normal case: test showing a select popup, canceling/selecting an item.
+TEST_F(ExternalPopupMenuTest, NormalCase) {
+ RegisterMockedURLLoad("select.html");
+ LoadFrame("select.html");
+
+ // Show the popup-menu.
+ auto* select = To<HTMLSelectElement>(
+ MainFrame()->GetFrame()->GetDocument()->getElementById("select"));
+ auto* layout_object = select->GetLayoutObject();
+ ASSERT_TRUE(layout_object);
+
+ select->ShowPopup();
+ WaitUntilShowedPopup();
+
+ ASSERT_TRUE(select->PopupIsVisible());
+ ASSERT_EQ(3U, MenuItems().size());
+ EXPECT_EQ(1, SelectedItem());
+
+ // Simulate the user canceling the popup; the index should not have changed.
+ PopupClient()->DidCancel();
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(1, select->selectedIndex());
+
+ // Show the pop-up again and this time make a selection.
+ select->ShowPopup();
+ WaitUntilShowedPopup();
+
+ PopupClient()->DidAcceptIndices({0});
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(0, select->selectedIndex());
+
+ // Show the pop-up again and make another selection.
+ select->ShowPopup();
+ WaitUntilShowedPopup();
+
+ ASSERT_EQ(3U, MenuItems().size());
+ EXPECT_EQ(0, SelectedItem());
+}
+
+// Page shows popup, then navigates away while popup showing, then select.
+TEST_F(ExternalPopupMenuTest, ShowPopupThenNavigate) {
+ RegisterMockedURLLoad("select.html");
+ LoadFrame("select.html");
+
+ // Show the popup-menu.
+ auto* document = MainFrame()->GetFrame()->GetDocument();
+ auto* select = To<HTMLSelectElement>(document->getElementById("select"));
+ auto* layout_object = select->GetLayoutObject();
+ ASSERT_TRUE(layout_object);
+
+ select->ShowPopup();
+ WaitUntilShowedPopup();
+
+ // Now we navigate to another pager.
+ document->documentElement()->setInnerHTML("<blink>Awesome page!</blink>");
+ document->UpdateStyleAndLayout(DocumentUpdateReason::kTest);
+ base::RunLoop().RunUntilIdle();
+
+ // Now HTMLSelectElement should be nullptr and mojo is disconnected.
+ select = To<HTMLSelectElement>(document->getElementById("select"));
+ EXPECT_FALSE(select);
+ EXPECT_FALSE(IsBound());
+}
+
+// An empty select should not cause a crash when clicked.
+// http://crbug.com/63774
+TEST_F(ExternalPopupMenuTest, EmptySelect) {
+ RegisterMockedURLLoad("select.html");
+ LoadFrame("select.html");
+
+ auto* select = To<HTMLSelectElement>(
+ MainFrame()->GetFrame()->GetDocument()->getElementById("emptySelect"));
+ EXPECT_TRUE(select);
+ select->click();
+}
+
+// Tests that nothing bad happen when the page removes the select when it
+// changes. (http://crbug.com/61997)
+TEST_F(ExternalPopupMenuTest, RemoveOnChange) {
+ RegisterMockedURLLoad("select_event_remove_on_change.html");
+ LoadFrame("select_event_remove_on_change.html");
+
+ // Show the popup-menu.
+ auto* document = MainFrame()->GetFrame()->GetDocument();
+ auto* select = To<HTMLSelectElement>(document->getElementById("s"));
+ auto* layout_object = select->GetLayoutObject();
+ ASSERT_TRUE(layout_object);
+
+ select->ShowPopup();
+ WaitUntilShowedPopup();
+
+ // Select something, it causes the select to be removed from the page.
+ PopupClient()->DidAcceptIndices({1});
+ base::RunLoop().RunUntilIdle();
+
+ // Just to check the soundness of the test.
+ // It should return nullptr as the select has been removed.
+ select = To<HTMLSelectElement>(document->getElementById("s"));
+ EXPECT_FALSE(select);
+}
+
+// crbug.com/912211
+TEST_F(ExternalPopupMenuTest, RemoveFrameOnChange) {
+ RegisterMockedURLLoad("select_event_remove_frame_on_change.html");
+ LoadFrame("select_event_remove_frame_on_change.html");
+
+ // Open a popup.
+ auto* iframe = To<HTMLIFrameElement>(
+ MainFrame()->GetFrame()->GetDocument()->QuerySelector("iframe"));
+ auto* select =
+ To<HTMLSelectElement>(iframe->contentDocument()->QuerySelector("select"));
+ auto* layout_object = select->GetLayoutObject();
+ ASSERT_TRUE(layout_object);
+
+ select->ShowPopup();
+
+ // Select something on the sub-frame, it causes the frame to be removed from
+ // the page.
+ select->SelectOptionByPopup(1);
+ // The test passes if the test didn't crash and ASAN didn't complain.
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/forms/file_input_type.cc b/chromium/third_party/blink/renderer/core/html/forms/file_input_type.cc
index 62d3be9b859..c6b772fcd4e 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/file_input_type.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/file_input_type.cc
@@ -208,7 +208,11 @@ void FileInputType::CustomStyleForLayoutObject(ComputedStyle& style) {
}
bool FileInputType::TypeShouldForceLegacyLayout() const {
- return !RuntimeEnabledFeatures::LayoutNGForControlsEnabled();
+ if (RuntimeEnabledFeatures::LayoutNGForControlsEnabled())
+ return false;
+ UseCounter::Count(GetElement().GetDocument(),
+ WebFeature::kLegacyLayoutByFileUploadControl);
+ return true;
}
LayoutObject* FileInputType::CreateLayoutObject(const ComputedStyle& style,
diff --git a/chromium/third_party/blink/renderer/core/html/forms/form_data_event.idl b/chromium/third_party/blink/renderer/core/html/forms/form_data_event.idl
index 84c7af0cc1e..502c847e27a 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/form_data_event.idl
+++ b/chromium/third_party/blink/renderer/core/html/forms/form_data_event.idl
@@ -7,6 +7,6 @@
[
Exposed=Window
] interface FormDataEvent : Event {
- constructor(DOMString type, optional FormDataEventInit eventInitDict = {});
+ constructor(DOMString type, FormDataEventInit eventInitDict);
readonly attribute FormData formData;
};
diff --git a/chromium/third_party/blink/renderer/core/html/forms/html_button_element.cc b/chromium/third_party/blink/renderer/core/html/forms/html_button_element.cc
index e062da100d7..1ff4dbb5bf3 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/html_button_element.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/html_button_element.cc
@@ -27,6 +27,7 @@
#include "third_party/blink/renderer/core/dom/attribute.h"
#include "third_party/blink/renderer/core/events/keyboard_event.h"
+#include "third_party/blink/renderer/core/frame/web_feature.h"
#include "third_party/blink/renderer/core/html/forms/form_data.h"
#include "third_party/blink/renderer/core/html/forms/html_form_element.h"
#include "third_party/blink/renderer/core/html_names.h"
@@ -53,6 +54,7 @@ LayoutObject* HTMLButtonElement::CreateLayoutObject(const ComputedStyle& style,
display == EDisplay::kInlineLayoutCustom ||
display == EDisplay::kLayoutCustom)
return HTMLFormControlElement::CreateLayoutObject(style, legacy);
+ UseCounter::Count(GetDocument(), WebFeature::kLegacyLayoutByButton);
return new LayoutButton(this);
}
diff --git a/chromium/third_party/blink/renderer/core/html/forms/html_form_control_element_with_state.h b/chromium/third_party/blink/renderer/core/html/forms/html_form_control_element_with_state.h
index 88b71eccf45..11b4d5e26c6 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/html_form_control_element_with_state.h
+++ b/chromium/third_party/blink/renderer/core/html/forms/html_form_control_element_with_state.h
@@ -48,6 +48,9 @@ class CORE_EXPORT HTMLFormControlElementWithState
bool ShouldSaveAndRestoreFormControlState() const override;
bool UserHasEditedTheField() const { return user_has_edited_the_field_; }
+ void SetUserHasEditedTheField(bool value) {
+ user_has_edited_the_field_ = value;
+ }
// This is only used in tests, to fake the user's action
void SetUserHasEditedTheFieldForTest() { user_has_edited_the_field_ = true; }
diff --git a/chromium/third_party/blink/renderer/core/html/forms/html_form_element.cc b/chromium/third_party/blink/renderer/core/html/forms/html_form_element.cc
index aa0f521211e..7c149fb0f92 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/html_form_element.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/html_form_element.cc
@@ -265,7 +265,8 @@ void HTMLFormElement::PrepareForSubmission(
return;
}
- if (GetDocument().IsSandboxed(mojom::blink::WebSandboxFlags::kForms)) {
+ if (GetDocument().IsSandboxed(
+ network::mojom::blink::WebSandboxFlags::kForms)) {
GetDocument().AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>(
mojom::ConsoleMessageSource::kSecurity,
mojom::ConsoleMessageLevel::kError,
@@ -453,7 +454,8 @@ void HTMLFormElement::ScheduleFormSubmission(
DCHECK(form_submission->Form());
if (form_submission->Action().IsEmpty())
return;
- if (GetDocument().IsSandboxed(mojom::blink::WebSandboxFlags::kForms)) {
+ if (GetDocument().IsSandboxed(
+ network::mojom::blink::WebSandboxFlags::kForms)) {
// FIXME: This message should be moved off the console once a solution to
// https://bugs.webkit.org/show_bug.cgi?id=103274 exists.
GetDocument().AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>(
diff --git a/chromium/third_party/blink/renderer/core/html/forms/html_input_element.cc b/chromium/third_party/blink/renderer/core/html/forms/html_input_element.cc
index ce0b6a33afb..d5a4f05446e 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/html_input_element.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/html_input_element.cc
@@ -623,26 +623,6 @@ base::Optional<uint32_t> HTMLInputElement::selectionEndForBinding(
return TextControlElement::selectionEnd();
}
-unsigned HTMLInputElement::selectionStartForBinding(
- bool& is_null,
- ExceptionState& exception_state) const {
- if (!input_type_->SupportsSelectionAPI()) {
- is_null = true;
- return 0;
- }
- return TextControlElement::selectionStart();
-}
-
-unsigned HTMLInputElement::selectionEndForBinding(
- bool& is_null,
- ExceptionState& exception_state) const {
- if (!input_type_->SupportsSelectionAPI()) {
- is_null = true;
- return 0;
- }
- return TextControlElement::selectionEnd();
-}
-
String HTMLInputElement::selectionDirectionForBinding(
ExceptionState& exception_state) const {
if (!input_type_->SupportsSelectionAPI()) {
@@ -677,34 +657,6 @@ void HTMLInputElement::setSelectionEndForBinding(
TextControlElement::setSelectionEnd(end.value_or(0));
}
-void HTMLInputElement::setSelectionStartForBinding(
- unsigned start,
- bool is_null,
- ExceptionState& exception_state) {
- if (!input_type_->SupportsSelectionAPI()) {
- exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
- "The input element's type ('" +
- input_type_->FormControlType() +
- "') does not support selection.");
- return;
- }
- TextControlElement::setSelectionStart(start);
-}
-
-void HTMLInputElement::setSelectionEndForBinding(
- unsigned end,
- bool is_null,
- ExceptionState& exception_state) {
- if (!input_type_->SupportsSelectionAPI()) {
- exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
- "The input element's type ('" +
- input_type_->FormControlType() +
- "') does not support selection.");
- return;
- }
- TextControlElement::setSelectionEnd(end);
-}
-
void HTMLInputElement::setSelectionDirectionForBinding(
const String& direction,
ExceptionState& exception_state) {
diff --git a/chromium/third_party/blink/renderer/core/html/forms/html_input_element.h b/chromium/third_party/blink/renderer/core/html/forms/html_input_element.h
index 9b0f10e05d9..e2b0b44ab88 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/html_input_element.h
+++ b/chromium/third_party/blink/renderer/core/html/forms/html_input_element.h
@@ -185,20 +185,9 @@ class CORE_EXPORT HTMLInputElement
base::Optional<uint32_t> selectionStartForBinding(ExceptionState&) const;
base::Optional<uint32_t> selectionEndForBinding(ExceptionState&) const;
- // TODO(crbug.com/1060971): Remove |is_null| version.
- unsigned selectionStartForBinding(bool&,
- ExceptionState&) const; // DEPRECATED
- unsigned selectionEndForBinding(bool&, ExceptionState&) const; // DEPRECATED
String selectionDirectionForBinding(ExceptionState&) const;
void setSelectionStartForBinding(base::Optional<uint32_t>, ExceptionState&);
void setSelectionEndForBinding(base::Optional<uint32_t>, ExceptionState&);
- // TODO(crbug.com/1060971): Remove |is_null| version.
- void setSelectionStartForBinding(unsigned,
- bool is_null,
- ExceptionState&); // DEPRECATED
- void setSelectionEndForBinding(unsigned,
- bool is_null,
- ExceptionState&); // DEPRECATED
void setSelectionDirectionForBinding(const String&, ExceptionState&);
void setSelectionRangeForBinding(unsigned start,
unsigned end,
diff --git a/chromium/third_party/blink/renderer/core/html/forms/html_opt_group_element.cc b/chromium/third_party/blink/renderer/core/html/forms/html_opt_group_element.cc
index ae6b2f65cfd..0219dc9ba41 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/html_opt_group_element.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/html_opt_group_element.cc
@@ -139,8 +139,7 @@ String HTMLOptGroupElement::GroupLabelText() const {
}
HTMLSelectElement* HTMLOptGroupElement::OwnerSelectElement() const {
- // TODO(tkent): We should return only the parent <select>.
- return Traversal<HTMLSelectElement>::FirstAncestor(*this);
+ return DynamicTo<HTMLSelectElement>(parentNode());
}
String HTMLOptGroupElement::DefaultToolTip() const {
diff --git a/chromium/third_party/blink/renderer/core/html/forms/html_option_element.h b/chromium/third_party/blink/renderer/core/html/forms/html_option_element.h
index 87e6b6a698e..e895c8546f8 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/html_option_element.h
+++ b/chromium/third_party/blink/renderer/core/html/forms/html_option_element.h
@@ -101,6 +101,11 @@ class CORE_EXPORT HTMLOptionElement final : public HTMLElement {
void SetMultiSelectFocusedState(bool);
bool IsMultiSelectFocused() const;
+ void SetWasOptionInsertedCalled(bool flag) {
+ was_option_inserted_called_ = true;
+ }
+ bool WasOptionInsertedCalled() const { return was_option_inserted_called_; }
+
private:
~HTMLOptionElement() override;
@@ -126,6 +131,11 @@ class CORE_EXPORT HTMLOptionElement final : public HTMLElement {
// Represents the option being focused on in a multi-select non-contiguous
// traversal via the keyboard.
bool is_multi_select_focused_ = false;
+
+ // True while HTMLSelectElement::OptionInserted(this) and OptionRemoved(this);
+ // This flag is necessary to detect a state where DOM tree is updated and
+ // OptionInserted() is not called yet.
+ bool was_option_inserted_called_ = false;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/forms/html_select_element.cc b/chromium/third_party/blink/renderer/core/html/forms/html_select_element.cc
index a5f4eb0657c..bf5514858c6 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/html_select_element.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/html_select_element.cc
@@ -65,8 +65,6 @@
#include "third_party/blink/renderer/core/page/chrome_client.h"
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/core/page/spatial_navigation.h"
-#include "third_party/blink/renderer/core/paint/paint_layer.h"
-#include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
@@ -203,6 +201,7 @@ void HTMLSelectElement::SelectMultipleOptionsByPopup(
}
}
+ select_type_->UpdateTextStyleAndContent();
SetNeedsValidityCheck();
if (has_new_selection || !old_selection.IsEmpty()) {
DispatchInputEvent();
@@ -368,7 +367,11 @@ bool HTMLSelectElement::CanSelectAll() const {
}
bool HTMLSelectElement::TypeShouldForceLegacyLayout() const {
- return UsesMenuList();
+ if (UsesMenuList()) {
+ UseCounter::Count(GetDocument(), WebFeature::kLegacyLayoutByMenuList);
+ return true;
+ }
+ return false;
}
LayoutObject* HTMLSelectElement::CreateLayoutObject(
@@ -523,7 +526,7 @@ void HTMLSelectElement::ScrollToSelection() {
return;
if (UsesMenuList())
return;
- ScrollToOption(ActiveSelectionEnd());
+ select_type_->ScrollToOption(ActiveSelectionEnd());
if (AXObjectCache* cache = GetDocument().ExistingAXObjectCache())
cache->ListboxActiveIndexChanged(this);
}
@@ -705,50 +708,6 @@ void HTMLSelectElement::SetSuggestedOption(HTMLOptionElement* option) {
select_type_->DidSetSuggestedOption(option);
}
-void HTMLSelectElement::ScrollToOption(HTMLOptionElement* option) {
- if (!option)
- return;
- if (UsesMenuList())
- return;
- bool has_pending_task = option_to_scroll_to_;
- // We'd like to keep an HTMLOptionElement reference rather than the index of
- // the option because the task should work even if unselected option is
- // inserted before executing scrollToOptionTask().
- option_to_scroll_to_ = option;
- if (!has_pending_task) {
- GetDocument()
- .GetTaskRunner(TaskType::kUserInteraction)
- ->PostTask(FROM_HERE, WTF::Bind(&HTMLSelectElement::ScrollToOptionTask,
- WrapPersistent(this)));
- }
-}
-
-void HTMLSelectElement::ScrollToOptionTask() {
- HTMLOptionElement* option = option_to_scroll_to_.Release();
- if (!option || !isConnected())
- return;
- // OptionRemoved() makes sure option_to_scroll_to_ doesn't have an option with
- // another owner.
- DCHECK_EQ(option->OwnerSelectElement(), this);
- GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kScroll);
- if (!GetLayoutObject() || UsesMenuList())
- return;
- PhysicalRect bounds = option->BoundingBoxForScrollIntoView();
-
- // The following code will not scroll parent boxes unlike ScrollRectToVisible.
- auto* box = GetLayoutBox();
- if (!box->HasOverflowClip())
- return;
- DCHECK(box->Layer());
- DCHECK(box->Layer()->GetScrollableArea());
- box->Layer()->GetScrollableArea()->ScrollIntoView(
- bounds,
- ScrollAlignment::CreateScrollIntoViewParams(
- ScrollAlignment::ToEdgeIfNeeded(), ScrollAlignment::ToEdgeIfNeeded(),
- mojom::blink::ScrollType::kProgrammatic, false,
- mojom::blink::ScrollBehavior::kInstant));
-}
-
void HTMLSelectElement::OptionSelectionStateChanged(HTMLOptionElement* option,
bool option_is_selected) {
DCHECK_EQ(option->OwnerSelectElement(), this);
@@ -798,6 +757,7 @@ bool HTMLSelectElement::ChildrenChangedAllChildrenRemovedNeedsList() const {
void HTMLSelectElement::OptionInserted(HTMLOptionElement& option,
bool option_is_selected) {
DCHECK_EQ(option.OwnerSelectElement(), this);
+ option.SetWasOptionInsertedCalled(true);
SetRecalcListItems();
if (option_is_selected) {
SelectOption(&option, IsMultiple() ? 0 : kDeselectOtherOptionsFlag);
@@ -820,6 +780,7 @@ void HTMLSelectElement::OptionInserted(HTMLOptionElement& option,
}
void HTMLSelectElement::OptionRemoved(HTMLOptionElement& option) {
+ option.SetWasOptionInsertedCalled(false);
SetRecalcListItems();
if (option.Selected())
ResetToDefaultSelection(kResetReasonSelectedOptionRemoved);
@@ -827,8 +788,7 @@ void HTMLSelectElement::OptionRemoved(HTMLOptionElement& option) {
ResetToDefaultSelection();
if (last_on_change_option_ == &option)
last_on_change_option_.Clear();
- if (option_to_scroll_to_ == &option)
- option_to_scroll_to_.Clear();
+ select_type_->OptionRemoved(option);
if (active_selection_anchor_ == &option)
active_selection_anchor_.Clear();
if (active_selection_end_ == &option)
@@ -942,11 +902,13 @@ bool HTMLSelectElement::DeselectItemsWithoutValidation(
}
bool did_update_selection = false;
for (auto* const option : GetOptionList()) {
- if (option != exclude_element) {
- if (option->Selected())
- did_update_selection = true;
- option->SetSelectedState(false);
- }
+ if (option == exclude_element)
+ continue;
+ if (!option->WasOptionInsertedCalled())
+ continue;
+ if (option->Selected())
+ did_update_selection = true;
+ option->SetSelectedState(false);
}
return did_update_selection;
}
@@ -1226,7 +1188,7 @@ void HTMLSelectElement::FinishParsingChildren() {
HTMLFormControlElementWithState::FinishParsingChildren();
if (UsesMenuList())
return;
- ScrollToOption(SelectedOption());
+ select_type_->ScrollToOption(SelectedOption());
if (AXObjectCache* cache = GetDocument().ExistingAXObjectCache())
cache->ListboxActiveIndexChanged(this);
}
@@ -1252,7 +1214,6 @@ void HTMLSelectElement::Trace(Visitor* visitor) {
visitor->Trace(last_on_change_option_);
visitor->Trace(active_selection_anchor_);
visitor->Trace(active_selection_end_);
- visitor->Trace(option_to_scroll_to_);
visitor->Trace(suggested_option_);
visitor->Trace(select_type_);
HTMLFormControlElementWithState::Trace(visitor);
diff --git a/chromium/third_party/blink/renderer/core/html/forms/html_select_element.h b/chromium/third_party/blink/renderer/core/html/forms/html_select_element.h
index 314840a3f45..eb28983c7ad 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/html_select_element.h
+++ b/chromium/third_party/blink/renderer/core/html/forms/html_select_element.h
@@ -123,7 +123,6 @@ class CORE_EXPORT HTMLSelectElement final
HTMLOptionElement* item(unsigned index);
void ScrollToSelection();
- void ScrollToOption(HTMLOptionElement*);
bool CanSelectAll() const;
void SelectAll();
@@ -265,7 +264,6 @@ class CORE_EXPORT HTMLSelectElement final
AutoscrollController* GetAutoscrollController() const;
LayoutBox* AutoscrollBox() override;
void StopAutoscroll() override;
- void ScrollToOptionTask();
bool AreAuthorShadowsAllowed() const override { return false; }
void FinishParsingChildren() override;
@@ -289,7 +287,6 @@ class CORE_EXPORT HTMLSelectElement final
Member<HTMLOptionElement> last_on_change_option_;
Member<HTMLOptionElement> active_selection_anchor_;
Member<HTMLOptionElement> active_selection_end_;
- Member<HTMLOptionElement> option_to_scroll_to_;
Member<HTMLOptionElement> suggested_option_;
bool uses_menu_list_ = true;
bool is_multiple_;
diff --git a/chromium/third_party/blink/renderer/core/html/forms/html_select_element_test.cc b/chromium/third_party/blink/renderer/core/html/forms/html_select_element_test.cc
index f92a9abb963..9a0133c5b2d 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/html_select_element_test.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/html_select_element_test.cc
@@ -50,6 +50,11 @@ class HTMLSelectElementTest : public PageTestBase {
return select->isConnected();
}
+ String MenuListLabel() const {
+ auto* select = To<HTMLSelectElement>(GetDocument().body()->firstChild());
+ return select->InnerElement().textContent();
+ }
+
private:
bool original_delegates_flag_;
};
@@ -564,6 +569,39 @@ TEST_F(HTMLSelectElementTest, SelectMultipleOptionsByPopup) {
EXPECT_FALSE(FirstSelectIsConnectedAfterSelectMultiple(Vector<int>{1}))
<< "Onchange handler should be executed.";
}
+
+ // Check if the label is correctly updated.
+ {
+ SetHtmlInnerHTML(
+ "<select multiple>"
+ "<option selected>o0</option><option selected>o1</option></select>");
+ EXPECT_EQ("2 selected", MenuListLabel());
+ EXPECT_TRUE(FirstSelectIsConnectedAfterSelectMultiple(Vector<int>{1}));
+ EXPECT_EQ("o1", MenuListLabel());
+ }
+}
+
+TEST_F(HTMLSelectElementTest, IntrinsicInlineSizeOverflow) {
+ // crbug.com/1068338
+ // This test passes if UBSAN doesn't complain.
+ SetHtmlInnerHTML(
+ "<select style='word-spacing:1073741824em;'>"
+ "<option>abc def</option></select>");
+ GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest);
+}
+
+TEST_F(HTMLSelectElementTest, AddingNotOwnedOption) {
+ // crbug.com/1077556
+ auto& doc = GetDocument();
+ SetHtmlInnerHTML("<select>");
+ auto* select = To<HTMLSelectElement>(doc.body()->firstChild());
+ // Append <div><optgroup></optgroup></div> to the SELECT.
+ // We can't do it with the HTML parser.
+ auto* optgroup = doc.CreateRawElement(html_names::kOptgroupTag);
+ select->appendChild(doc.CreateRawElement(html_names::kDivTag))
+ ->appendChild(optgroup);
+ optgroup->appendChild(doc.CreateRawElement(html_names::kOptionTag));
+ // This test passes if the above appendChild() doesn't cause a DCHECK failure.
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/forms/html_text_area_element.cc b/chromium/third_party/blink/renderer/core/html/forms/html_text_area_element.cc
index d10fd35c9af..04bcc8532b1 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/html_text_area_element.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/html_text_area_element.cc
@@ -214,6 +214,7 @@ void HTMLTextAreaElement::ParseAttribute(
LayoutObject* HTMLTextAreaElement::CreateLayoutObject(const ComputedStyle&,
LegacyLayout) {
+ UseCounter::Count(GetDocument(), WebFeature::kLegacyLayoutByTextControl);
return new LayoutTextControlMultiLine(this);
}
diff --git a/chromium/third_party/blink/renderer/core/html/forms/internal_popup_menu.cc b/chromium/third_party/blink/renderer/core/html/forms/internal_popup_menu.cc
index 360545b4afe..411650375cf 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/internal_popup_menu.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/internal_popup_menu.cc
@@ -9,6 +9,7 @@
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/renderer/core/css/css_font_selector.h"
+#include "third_party/blink/renderer/core/css/css_value_id_mappings.h"
#include "third_party/blink/renderer/core/css/style_engine.h"
#include "third_party/blink/renderer/core/dom/element_traversal.h"
#include "third_party/blink/renderer/core/dom/events/scoped_event_queue.h"
@@ -46,18 +47,7 @@ const char* FontStyleToString(FontSelectionValue slope) {
}
const char* TextTransformToString(ETextTransform transform) {
- switch (transform) {
- case ETextTransform::kCapitalize:
- return "capitalize";
- case ETextTransform::kUppercase:
- return "uppercase";
- case ETextTransform::kLowercase:
- return "lowercase";
- case ETextTransform::kNone:
- return "none";
- }
- NOTREACHED();
- return "";
+ return getValueName(PlatformEnumToCSSValueID(transform));
}
} // anonymous namespace
@@ -78,7 +68,7 @@ class PopupMenuCSSFontSelector : public CSSFontSelector,
void Trace(Visitor*) override;
private:
- void FontsNeedUpdate(FontSelector*) override;
+ void FontsNeedUpdate(FontSelector*, FontInvalidationReason) override;
Member<CSSFontSelector> owner_font_selector_;
};
@@ -98,8 +88,9 @@ scoped_refptr<FontData> PopupMenuCSSFontSelector::GetFontData(
return owner_font_selector_->GetFontData(description, name);
}
-void PopupMenuCSSFontSelector::FontsNeedUpdate(FontSelector* font_selector) {
- DispatchInvalidationCallbacks();
+void PopupMenuCSSFontSelector::FontsNeedUpdate(FontSelector* font_selector,
+ FontInvalidationReason reason) {
+ DispatchInvalidationCallbacks(reason);
}
void PopupMenuCSSFontSelector::Trace(Visitor* visitor) {
@@ -227,7 +218,7 @@ void InternalPopupMenu::WriteDocument(SharedBuffer* data) {
// When writing the document, we ensure the ComputedStyle of the select
// element's items (see AddElementStyle). This requires a style-clean tree.
// See Element::EnsureComputedStyle for further explanation.
- owner_element.GetDocument().UpdateStyleAndLayoutTree();
+ DCHECK(!owner_element.GetDocument().NeedsLayoutTreeUpdate());
IntRect anchor_rect_in_screen = chrome_client_->ViewportToScreen(
owner_element.VisibleBoundsInVisualViewport(),
owner_element.GetDocument().View());
@@ -508,20 +499,12 @@ void InternalPopupMenu::Hide() {
}
void InternalPopupMenu::UpdateFromElement(UpdateReason) {
- if (needs_update_)
- return;
needs_update_ = true;
- OwnerElement()
- .GetDocument()
- .GetTaskRunner(TaskType::kUserInteraction)
- ->PostTask(FROM_HERE,
- WTF::Bind(&InternalPopupMenu::Update, WrapPersistent(this)));
}
-void InternalPopupMenu::Update() {
- if (!popup_ || !owner_element_)
+void InternalPopupMenu::Update(bool force_update) {
+ if (!popup_ || !owner_element_ || (!needs_update_ && !force_update))
return;
- OwnerElement().GetDocument().UpdateStyleAndLayoutTree();
// disconnectClient() might have been called.
if (!owner_element_)
return;
diff --git a/chromium/third_party/blink/renderer/core/html/forms/internal_popup_menu.h b/chromium/third_party/blink/renderer/core/html/forms/internal_popup_menu.h
index b6af0908fa0..ccd7c5f5304 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/internal_popup_menu.h
+++ b/chromium/third_party/blink/renderer/core/html/forms/internal_popup_menu.h
@@ -29,7 +29,7 @@ class CORE_EXPORT InternalPopupMenu final : public PopupMenu,
~InternalPopupMenu() override;
void Trace(Visitor*) override;
- void Update();
+ void Update(bool force_update) override;
void Dispose();
diff --git a/chromium/third_party/blink/renderer/core/html/forms/internal_popup_menu_test.cc b/chromium/third_party/blink/renderer/core/html/forms/internal_popup_menu_test.cc
index e74aa17fb04..225ed07a96e 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/internal_popup_menu_test.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/internal_popup_menu_test.cc
@@ -21,30 +21,6 @@ namespace blink {
// InternalPopupMenu::WriteDocument.
#if !defined(OS_ANDROID)
-TEST(InternalPopupMenuTest, WriteDocumentInStyleDirtyTree) {
- auto dummy_page_holder_ =
- std::make_unique<DummyPageHolder>(IntSize(800, 600));
- Document& document = dummy_page_holder_->GetDocument();
- document.body()->setInnerHTML(R"HTML(
- <select id="select">
- <option value="foo">Foo</option>
- <option value="bar" style="display:none">Bar</option>
- </select>
- )HTML");
- document.View()->UpdateAllLifecyclePhases(DocumentUpdateReason::kTest);
- auto* select = To<HTMLSelectElement>(document.getElementById("select"));
- ASSERT_TRUE(select);
- auto* menu = MakeGarbageCollected<InternalPopupMenu>(
- MakeGarbageCollected<EmptyChromeClient>(), *select);
-
- document.body()->SetInlineStyleProperty(CSSPropertyID::kColor, "blue");
-
- scoped_refptr<SharedBuffer> buffer = SharedBuffer::Create();
-
- // Don't DCHECK in Element::EnsureComputedStyle.
- static_cast<PagePopupClient*>(menu)->WriteDocument(buffer.get());
-}
-
TEST(InternalPopupMenuTest, ShowSelectDisplayNone) {
auto dummy_page_holder_ =
std::make_unique<DummyPageHolder>(IntSize(800, 600));
diff --git a/chromium/third_party/blink/renderer/core/html/forms/multiple_fields_temporal_input_type_view.cc b/chromium/third_party/blink/renderer/core/html/forms/multiple_fields_temporal_input_type_view.cc
index 76092674346..f204c7d2228 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/multiple_fields_temporal_input_type_view.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/multiple_fields_temporal_input_type_view.cc
@@ -490,8 +490,7 @@ void MultipleFieldsTemporalInputTypeView::HandleKeydownEvent(
((event.key() == "ArrowDown" && event.getModifierState("Alt")) ||
(LayoutTheme::GetTheme().ShouldOpenPickerWithF4Key() &&
event.key() == "F4") ||
- (features::IsFormControlsRefreshEnabled() &&
- (event.key() == "Enter" || event.key() == " ")))) {
+ (features::IsFormControlsRefreshEnabled() && event.key() == " "))) {
if (PickerIndicatorElement* element = GetPickerIndicatorElement())
element->OpenPopup();
event.SetDefaultHandled();
diff --git a/chromium/third_party/blink/renderer/core/html/forms/password_input_type.cc b/chromium/third_party/blink/renderer/core/html/forms/password_input_type.cc
index 171ce12062c..ef20471af5d 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/password_input_type.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/password_input_type.cc
@@ -200,4 +200,9 @@ void PasswordInputType::HandleKeydownEvent(KeyboardEvent& event) {
if (!event.DefaultHandled())
BaseTextInputType::HandleKeydownEvent(event);
}
+
+bool PasswordInputType::SupportsInputModeAttribute() const {
+ return true;
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/forms/password_input_type.h b/chromium/third_party/blink/renderer/core/html/forms/password_input_type.h
index 10804fb46ec..8dff1f7443b 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/password_input_type.h
+++ b/chromium/third_party/blink/renderer/core/html/forms/password_input_type.h
@@ -62,6 +62,7 @@ class PasswordInputType final : public BaseTextInputType {
void HandleBeforeTextInsertedEvent(BeforeTextInsertedEvent&) override;
void HandleBlurEvent() override;
+ bool SupportsInputModeAttribute() const override;
bool should_show_reveal_button_ = false;
};
diff --git a/chromium/third_party/blink/renderer/core/html/forms/picker_indicator_element.cc b/chromium/third_party/blink/renderer/core/html/forms/picker_indicator_element.cc
index 50036ddb04b..e9e58542693 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/picker_indicator_element.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/picker_indicator_element.cc
@@ -63,6 +63,7 @@ LayoutObject* PickerIndicatorElement::CreateLayoutObject(
if (features::IsFormControlsRefreshEnabled())
return HTMLDivElement::CreateLayoutObject(style, legacy);
+ UseCounter::Count(GetDocument(), WebFeature::kLegacyLayoutByDetailsMarker);
return new LayoutDetailsMarker(this);
}
diff --git a/chromium/third_party/blink/renderer/core/html/forms/range_input_type.cc b/chromium/third_party/blink/renderer/core/html/forms/range_input_type.cc
index 0eed4825627..253ea5a28d3 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/range_input_type.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/range_input_type.cc
@@ -259,6 +259,8 @@ bool RangeInputType::TypeShouldForceLegacyLayout() const {
LayoutObject* RangeInputType::CreateLayoutObject(const ComputedStyle&,
LegacyLayout) const {
+ UseCounter::Count(GetElement().GetDocument(),
+ WebFeature::kLegacyLayoutBySlider);
return new LayoutSlider(&GetElement());
}
diff --git a/chromium/third_party/blink/renderer/core/html/forms/resources/color_picker.js b/chromium/third_party/blink/renderer/core/html/forms/resources/color_picker.js
index f7396a8596b..c2c2366c838 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/resources/color_picker.js
+++ b/chromium/third_party/blink/renderer/core/html/forms/resources/color_picker.js
@@ -433,10 +433,15 @@ class ColorPicker extends HTMLElement {
this.visualColorPicker_ = new VisualColorPicker(initialColor);
this.manualColorPicker_ = new ManualColorPicker(initialColor);
- this.append(this.visualColorPicker_, this.manualColorPicker_);
+ this.colorValueAXAnnouncer_ = new ColorValueAXAnnouncer();
+ this.append(
+ this.visualColorPicker_, this.manualColorPicker_,
+ this.colorValueAXAnnouncer_);
this.visualColorPicker_.addEventListener(
'visual-color-picker-initialized', this.initializeListeners_);
+
+ window.addEventListener('resize', this.onWindowResize_, {once: true});
}
initializeListeners_ = () => {
@@ -445,11 +450,13 @@ class ColorPicker extends HTMLElement {
this.addEventListener('visual-color-change', this.onVisualColorChange_);
- this.addEventListener('format-change', this.updateFocusableElements_);
+ this.addEventListener('format-change', this.onFormatChange_);
- document.documentElement.addEventListener('keydown', this.onKeyDown_);
+ this.addEventListener('focusin', this.onFocusin_);
- window.addEventListener('resize', this.onWindowResize_, {once: true});
+ window.addEventListener('message', this.onMessageReceived_);
+
+ document.documentElement.addEventListener('keydown', this.onKeyDown_);
}
get selectedColor() {
@@ -499,6 +506,8 @@ class ColorPicker extends HTMLElement {
this.selectedColor = newColor;
this.manualColorPicker_.color = newColor;
+ this.colorValueAXAnnouncer_.announceColor(newColor);
+
const selectedValue = newColor.asHex();
window.pagePopupController.setValue(selectedValue);
} else {
@@ -548,6 +557,23 @@ class ColorPicker extends HTMLElement {
}
};
+ onFormatChange_ = (event) => {
+ this.updateFocusableElements_();
+ this.colorValueAXAnnouncer_.updateColorFormat(event.detail.colorFormat);
+ };
+
+ onFocusin_ = (event) => {
+ if (event.target instanceof ColorSelectionRing) {
+ // Announce the current color when the user focuses the ColorWell or the
+ // HueSlider.
+ this.colorValueAXAnnouncer_.announceColor(this.selectedColor);
+ } else if (event.target instanceof FormatToggler) {
+ // Announce the current color format when the user focuses the
+ // FormatToggler.
+ this.colorValueAXAnnouncer_.announceColorFormat();
+ }
+ };
+
updateFocusableElements_ = () => {
this.focusableElements_ = Array.from(this.querySelectorAll(
'color-value-container:not(.hidden-color-value-container) > input,' +
@@ -561,6 +587,22 @@ class ColorPicker extends HTMLElement {
}
this.focusableElements_[0].focus({preventScroll: true});
};
+
+ onMessageReceived_ = (event) => {
+ eval(event.data);
+ if (window.updateData && window.updateData.success) {
+ // Update the popup with the color selected using the eye dropper.
+ const selectedValue = new Color(window.updateData.color);
+ this.selectedColor = selectedValue;
+ this.manualColorPicker_.color = selectedValue;
+ this.visualColorPicker_.color = selectedValue;
+
+ const hexValue = selectedValue.asHex();
+ window.pagePopupController.setValue(hexValue);
+ }
+ this.visualColorPicker_.eyeDropper.finished();
+ delete window.updateData;
+ }
}
window.customElements.define('color-picker', ColorPicker);
@@ -681,7 +723,7 @@ class VisualColorPicker extends HTMLElement {
event.preventDefault();
event.stopPropagation();
this.hueSlider_.focused = false;
- this.colorWell_.pointerDown(new Point(event.touches[0].clientX, event.touches[0].clientY));
+ this.colorWell_.pointerDown(new Point(Math.round(event.touches[0].clientX), Math.round(event.touches[0].clientY)));
}
/**
@@ -691,7 +733,7 @@ class VisualColorPicker extends HTMLElement {
event.preventDefault();
event.stopPropagation();
this.colorWell_.focused = false;
- this.hueSlider_.pointerDown(new Point(event.touches[0].clientX, event.touches[0].clientY));
+ this.hueSlider_.pointerDown(new Point(Math.round(event.touches[0].clientX), Math.round(event.touches[0].clientY)));
}
onTouchStart_ = () => {
@@ -703,7 +745,7 @@ class VisualColorPicker extends HTMLElement {
* @param {!Event} event
*/
onTouchMove_ = (event) => {
- var point = new Point(event.touches[0].clientX, event.touches[0].clientY);
+ var point = new Point(Math.round(event.touches[0].clientX), Math.round(event.touches[0].clientY));
this.colorWell_.pointerMove(point);
this.hueSlider_.pointerMove(point);
}
@@ -746,6 +788,10 @@ class VisualColorPicker extends HTMLElement {
this.hueSlider_.color = newColor;
this.colorWell_.selectedColor = newColor;
}
+
+ get eyeDropper() {
+ return this.eyeDropper_;
+ }
}
window.customElements.define('visual-color-picker', VisualColorPicker);
@@ -836,6 +882,10 @@ class EyeDropper extends HTMLElement {
break;
}
};
+
+ finished = () => {
+ this.classList.remove('selected');
+ }
}
window.customElements.define('eye-dropper', EyeDropper);
@@ -850,6 +900,10 @@ class ColorViewer extends HTMLElement {
super();
this.color = initialColor;
+
+ // Leave the ColorViewer out of the accessibility tree; it's redundant
+ // with the updates from ColorValueAXAnnouncer.
+ this.setAttribute('aria-hidden', 'true');
}
get color() {
@@ -1010,7 +1064,7 @@ class ColorPalette extends HTMLCanvasElement {
* @param {number} y
*/
hslImageDataAtPoint_(x, y) {
- let offset = Math.round(y * this.width + x) * 3;
+ let offset = (y * this.width + x) * 3;
// It is possible that the computed offset is larger than the hslImageData
// array's length. This can happen at certain zoom levels (ex. 150%), where
// the height of the color well is not a round number. The getImageData API
@@ -1198,9 +1252,50 @@ class ColorSelectionRing extends HTMLElement {
onPositionChange_() {
this.setElementPosition_();
+ this.updatePositionForAria_();
this.updateColor();
}
+ initializeAria(isForColorWell) {
+ this.setAttribute('role', 'slider');
+ this.isForColorWell = isForColorWell;
+ this.setAttribute('aria-valuemin', 0);
+ if (isForColorWell) {
+ this.setAttribute('aria-label', global.params.axColorWellLabel);
+ this.setAttribute(
+ 'aria-roledescription', global.params.axColorWellRoleDescription);
+ this.setAttribute(
+ 'aria-valuemax',
+ this.backingColorPalette_.offsetHeight *
+ this.backingColorPalette_.offsetWidth);
+ } else {
+ this.setAttribute('aria-label', global.params.axHueSliderLabel);
+ this.setAttribute(
+ 'aria-valuemax',
+ this.backingColorPalette_.right - this.backingColorPalette_.left);
+ }
+ this.updatePositionForAria_();
+ }
+
+ updatePositionForAria_() {
+ if (this.isForColorWell) {
+ let positionX = (this.position_.x - this.backingColorPalette_.left);
+ let positionY = (this.position_.y - this.backingColorPalette_.top);
+ let colorWellWidth =
+ (this.backingColorPalette_.right - this.backingColorPalette_.left);
+
+ // aria-valuenow only takes a single numeric value, so we use this
+ // scheme to collapse the 2-D coordinates into a 1-D slider value.
+ this.setAttribute(
+ 'aria-valuenow', (positionY * colorWellWidth) + positionX);
+
+ this.setAttribute('aria-valuetext', `X: ${positionX}, Y: ${positionY}`);
+ } else {
+ this.setAttribute(
+ 'aria-valuenow', this.position_.x - this.backingColorPalette_.left);
+ }
+ }
+
setElementPosition_() {
if (this.height > this.backingColorPalette_.height) {
this.style.top = this.top -
@@ -1356,6 +1451,7 @@ class ColorWell extends ColorSelectionArea {
'color-selection-ring-update', this.onColorSelectionRingUpdate_);
this.moveColorSelectionRingTo_(this.selectedColor_);
+ this.colorSelectionRing_.initializeAria(/*isForColorWell*/ true);
this.resizeObserver_.disconnect();
this.resizeObserver_ = null;
@@ -1470,6 +1566,7 @@ class HueSlider extends ColorSelectionArea {
'color-selection-ring-update', this.onColorSelectionRingUpdate_);
this.moveColorSelectionRingTo_(this.color_);
+ this.colorSelectionRing_.initializeAria(/*isForColorWell*/ false);
this.resizeObserver_.disconnect();
this.resizeObserver_ = null;
@@ -1687,36 +1784,44 @@ class ChannelValueContainer extends HTMLInputElement {
this.setAttribute('type', 'text');
this.colorChannel_ = colorChannel;
+
switch (colorChannel) {
case ColorChannel.HEX:
this.setAttribute('id', 'hexValueContainer');
this.setAttribute('maxlength', '7');
+ this.setAttribute('aria-label', global.params.axHexadecimalEditLabel);
break;
case ColorChannel.R:
this.setAttribute('id', 'rValueContainer');
this.setAttribute('maxlength', '3');
+ this.setAttribute('aria-label', global.params.axRedEditLabel);
break;
case ColorChannel.G:
this.setAttribute('id', 'gValueContainer');
this.setAttribute('maxlength', '3');
+ this.setAttribute('aria-label', global.params.axGreenEditLabel);
break;
case ColorChannel.B:
this.setAttribute('id', 'bValueContainer');
this.setAttribute('maxlength', '3');
+ this.setAttribute('aria-label', global.params.axBlueEditLabel);
break;
case ColorChannel.H:
this.setAttribute('id', 'hValueContainer');
this.setAttribute('maxlength', '3');
+ this.setAttribute('aria-label', global.params.axHueEditLabel);
break;
case ColorChannel.S:
// up to 3 digits plus '%'
this.setAttribute('id', 'sValueContainer');
this.setAttribute('maxlength', '4');
+ this.setAttribute('aria-label', global.params.axSaturationEditLabel);
break;
case ColorChannel.L:
// up to 3 digits plus '%'
this.setAttribute('id', 'lValueContainer');
this.setAttribute('maxlength', '4');
+ this.setAttribute('aria-label', global.params.axLightnessEditLabel);
break;
}
this.setValue(initialColor);
@@ -1858,13 +1963,18 @@ class FormatToggler extends HTMLElement {
super();
this.setAttribute('tabIndex', 0);
+ this.setAttribute('role', 'spinbutton');
+ this.setAttribute('aria-label', global.params.axFormatTogglerLabel);
+ this.setAttribute('aria-valuenow', '1');
+ this.setAttribute('aria-valuemin', '1');
+ this.setAttribute('aria-valuemax', '3');
this.currentColorFormat_ = initialColorFormat;
- this.hexFormatLabel_ = new FormatLabel(ColorFormat.HEX);
this.rgbFormatLabel_ = new FormatLabel(ColorFormat.RGB);
+ this.hexFormatLabel_ = new FormatLabel(ColorFormat.HEX);
this.hslFormatLabel_ = new FormatLabel(ColorFormat.HSL);
this.colorFormatLabels_ = [
- this.hexFormatLabel_,
this.rgbFormatLabel_,
+ this.hexFormatLabel_,
this.hslFormatLabel_,
];
this.adjustFormatLabelVisibility_();
@@ -1900,6 +2010,14 @@ class FormatToggler extends HTMLElement {
});
this.currentColorFormat_ = ColorFormat[newColorFormatKey];
+ if (this.currentColorFormat_ === ColorFormat.RGB) {
+ this.setAttribute('aria-valuenow', '1');
+ } else if (this.currentColorFormat_ === ColorFormat.HSL) {
+ this.setAttribute('aria-valuenow', '2');
+ } else if (this.currentColorFormat_ === ColorFormat.HEX) {
+ this.setAttribute('aria-valuenow', '3');
+ }
+
this.adjustFormatLabelVisibility_();
this.dispatchEvent(new CustomEvent(
@@ -2010,3 +2128,94 @@ class ChannelLabel extends HTMLElement {
}
}
window.customElements.define('channel-label', ChannelLabel);
+
+/**
+ * ColorValueAXAnnouncer: Make announcements to be read out by accessibility tools
+ * when the color value is changed by the ColorWell or HueSlider.
+ * Ideally it would be sufficient to just set the right ARIA attributes on the elements
+ * themselves, but the color control does not fit neatly into existing ARIA roles.
+ * ColorValueAXAnnouncer fills this gap by reading out color value changes using an
+ * ARIA live region.
+ */
+class ColorValueAXAnnouncer extends HTMLElement {
+ constructor() {
+ super();
+ this.setAttribute('aria-live', 'polite');
+ this.colorFormat_ = ColorFormat.RGB;
+
+ // We don't want this element to be visible so hide it off the edge of the popup.
+ this.style.position = 'absolute';
+ this.style.left = '-99999ch';
+
+ this.addEventListener('format-change', this.onFormatChange_);
+ }
+
+ announceColor(newColor) {
+ let announcementString = null;
+ if (this.colorFormat_ === ColorFormat.HEX) {
+ announcementString =
+ `${global.params.axHexadecimalEditLabel} ${newColor.hexValue}`;
+ } else if (this.colorFormat_ === ColorFormat.RGB) {
+ announcementString =
+ `${global.params.axRedEditLabel} ${newColor.rValue}, ${
+ global.params.axGreenEditLabel} ${newColor.gValue}, ${
+ global.params.axBlueEditLabel} ${newColor.bValue}`;
+ } else if (this.colorFormat_ === ColorFormat.HSL) {
+ announcementString =
+ `${global.params.axHueEditLabel} ${newColor.hValue}, ${
+ global.params.axSaturationEditLabel} ${newColor.sValue}, ${
+ global.params.axLightnessEditLabel} ${newColor.lValue}`;
+ }
+ this.announce_(announcementString)
+ }
+
+ // Announce format changes via the live region in order to work around an
+ // issue where Windows Narrator does not support aria-valuetext for
+ // spinbutton. The behavior that this achieves is similar to updating the
+ // FormatToggler spinbutton's aria-valuetext whenever the format changes,
+ // but it dodges the Narrator bug.
+ // TODO(crbug.com/1073188): Remove this workaround and use aria-valuetext
+ // instead once the Narrator bug has been fixed.
+ announceColorFormat() {
+ // These are deliberately non-localized so that they match the
+ // abbreviations of the text on the FormatToggler ChannelLabels,
+ // which are also not localized.
+ let announcementString = null;
+ if (this.colorFormat_ === ColorFormat.HEX) {
+ announcementString = 'Hex';
+ } else if (this.colorFormat_ === ColorFormat.RGB) {
+ announcementString = 'RGB';
+ } else if (this.colorFormat_ === ColorFormat.HSL) {
+ announcementString = 'HSL';
+ }
+
+ this.announce_(announcementString)
+ }
+
+ updateColorFormat(newColorFormat) {
+ this.colorFormat_ = newColorFormat;
+ this.announceColorFormat();
+ }
+
+ announce_(announcementString) {
+ // Only cue one announcement at a time so that user isn't spammed with a backlog
+ // of announcements after holding down an arrow key.
+ // Announce after a delay so that the control announces its raw position before
+ // the full announcement starts.
+ window.clearTimeout(this.pendingAnnouncement_);
+ this.pendingAnnouncement_ = window.setTimeout(() => {
+ if (this.textContent === announcementString) {
+ // The AT will only do an announcement if the live-region content has
+ // changed, so make a no-op change to fool it into announcing every
+ // time. Normal whitespace is ignored by Narrator for this purpose,
+ // so use a non-breaking space.
+ this.textContent += String.fromCharCode(160);
+ } else {
+ this.textContent = announcementString;
+ }
+ }, ColorValueAXAnnouncer.announcementDelayMS);
+ }
+
+ static announcementDelayMS = 500;
+}
+window.customElements.define('color-value-ax-announcer', ColorValueAXAnnouncer);
diff --git a/chromium/third_party/blink/renderer/core/html/forms/resources/color_picker_common.js b/chromium/third_party/blink/renderer/core/html/forms/resources/color_picker_common.js
index 907aa31debe..653de81fffc 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/resources/color_picker_common.js
+++ b/chromium/third_party/blink/renderer/core/html/forms/resources/color_picker_common.js
@@ -19,6 +19,7 @@ var DefaultColorPalette = [
* @param {Event} event
*/
function handleMessage(event) {
+ window.removeEventListener('message', handleMessage, false);
initialize(JSON.parse(event.data));
global.argumentsReceived = true;
}
diff --git a/chromium/third_party/blink/renderer/core/html/forms/resources/listPicker.css b/chromium/third_party/blink/renderer/core/html/forms/resources/listPicker.css
index be88651d93a..b0e435ff75e 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/resources/listPicker.css
+++ b/chromium/third_party/blink/renderer/core/html/forms/resources/listPicker.css
@@ -21,8 +21,3 @@ option, optgroup {
border-radius: 0px;
outline: none;
}
-
-.controls-refresh option:checked:enabled {
- outline: solid 2px -webkit-focus-ring-color;
- outline-offset: -2px;
-}
diff --git a/chromium/third_party/blink/renderer/core/html/forms/resources/listPicker.js b/chromium/third_party/blink/renderer/core/html/forms/resources/listPicker.js
index 0709fa0ee21..5fa721917a4 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/resources/listPicker.js
+++ b/chromium/third_party/blink/renderer/core/html/forms/resources/listPicker.js
@@ -99,12 +99,8 @@ ListPicker.prototype._handleWindowMessage = function(event) {
window.updateData.anchorRectInScreen.width ||
this._config.anchorRectInScreen.height !==
window.updateData.anchorRectInScreen.height) {
- // TODO(tkent): Don't fix window size here due to a bug of Aura or
- // compositor. crbug.com/863770
- if (!navigator.platform.startsWith('Win')) {
this._config.anchorRectInScreen = window.updateData.anchorRectInScreen;
this._fixWindowSize();
- }
}
}
delete window.updateData;
diff --git a/chromium/third_party/blink/renderer/core/html/forms/select_type.cc b/chromium/third_party/blink/renderer/core/html/forms/select_type.cc
index 345cbeb2682..6048bc713fc 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/select_type.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/select_type.cc
@@ -52,6 +52,8 @@
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/core/page/spatial_navigation.h"
#include "third_party/blink/renderer/core/paint/paint_layer.h"
+#include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
+#include "third_party/blink/renderer/core/scroll/scroll_alignment.h"
#include "third_party/blink/renderer/platform/text/platform_locale.h"
#include "ui/base/ui_base_features.h"
@@ -611,10 +613,14 @@ void MenuListSelectType::DidMutateSubtree() {
class ListBoxSelectType final : public SelectType {
public:
explicit ListBoxSelectType(HTMLSelectElement& select) : SelectType(select) {}
+ void Trace(Visitor* visitor) override;
+
bool DefaultEventHandler(const Event& event) override;
+ void OptionRemoved(HTMLOptionElement& option) override;
void DidBlur() override;
void DidSetSuggestedOption(HTMLOptionElement* option) override;
void SaveLastSelection() override;
+ void ScrollToOption(HTMLOptionElement* option) override;
void SelectAll() override;
void SaveListboxActiveSelection() override;
void HandleMouseRelease() override;
@@ -635,13 +641,20 @@ class ListBoxSelectType final : public SelectType {
void UpdateSelectedState(HTMLOptionElement* clicked_option,
SelectionMode mode);
void UpdateListBoxSelection(bool deselect_other_options, bool scroll = true);
+ void ScrollToOptionTask();
Vector<bool> cached_state_for_active_selection_;
Vector<bool> last_on_change_selection_;
+ Member<HTMLOptionElement> option_to_scroll_to_;
bool is_in_non_contiguous_selection_ = false;
bool active_selection_state_ = false;
};
+void ListBoxSelectType::Trace(Visitor* visitor) {
+ visitor->Trace(option_to_scroll_to_);
+ SelectType::Trace(visitor);
+}
+
bool ListBoxSelectType::DefaultEventHandler(const Event& event) {
const auto* mouse_event = DynamicTo<MouseEvent>(event);
const auto* gesture_event = DynamicTo<GestureEvent>(event);
@@ -709,7 +722,7 @@ bool ListBoxSelectType::DefaultEventHandler(const Event& event) {
if (Page* page = select_->GetDocument().GetPage()) {
page->GetAutoscrollController().StartAutoscrollForSelection(
- layout_object);
+ select_->GetLayoutObject());
}
}
// Mousedown didn't happen in this element.
@@ -851,7 +864,7 @@ bool ListBoxSelectType::DefaultEventHandler(const Event& event) {
select_->SetActiveSelectionAnchor(select_->active_selection_end_.Get());
}
- select_->ScrollToOption(end_option);
+ ScrollToOption(end_option);
if (select_new_item || is_in_non_contiguous_selection_) {
if (select_new_item) {
UpdateListBoxSelection(deselect_others);
@@ -896,13 +909,18 @@ bool ListBoxSelectType::DefaultEventHandler(const Event& event) {
return false;
}
+void ListBoxSelectType::OptionRemoved(HTMLOptionElement& option) {
+ if (option_to_scroll_to_ == &option)
+ option_to_scroll_to_.Clear();
+}
+
void ListBoxSelectType::DidBlur() {
ClearLastOnChangeSelection();
}
void ListBoxSelectType::DidSetSuggestedOption(HTMLOptionElement* option) {
if (select_->GetLayoutObject())
- select_->ScrollToOption(option);
+ ScrollToOption(option);
}
void ListBoxSelectType::SaveLastSelection() {
@@ -928,6 +946,48 @@ void ListBoxSelectType::UpdateMultiSelectFocus() {
select_->ScrollToSelection();
}
+void ListBoxSelectType::ScrollToOption(HTMLOptionElement* option) {
+ if (!option)
+ return;
+ bool has_pending_task = option_to_scroll_to_;
+ // We'd like to keep an HTMLOptionElement reference rather than the index of
+ // the option because the task should work even if unselected option is
+ // inserted before executing ScrollToOptionTask().
+ option_to_scroll_to_ = option;
+ if (!has_pending_task) {
+ select_->GetDocument()
+ .GetTaskRunner(TaskType::kUserInteraction)
+ ->PostTask(FROM_HERE, WTF::Bind(&ListBoxSelectType::ScrollToOptionTask,
+ WrapPersistent(this)));
+ }
+}
+
+void ListBoxSelectType::ScrollToOptionTask() {
+ HTMLOptionElement* option = option_to_scroll_to_.Release();
+ if (!option || !select_->isConnected() || will_be_destroyed_)
+ return;
+ // OptionRemoved() makes sure option_to_scroll_to_ doesn't have an option
+ // with another owner.
+ DCHECK_EQ(option->OwnerSelectElement(), select_);
+ select_->GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kScroll);
+ if (!select_->GetLayoutObject())
+ return;
+ PhysicalRect bounds = option->BoundingBoxForScrollIntoView();
+
+ // The following code will not scroll parent boxes unlike ScrollRectToVisible.
+ auto* box = select_->GetLayoutBox();
+ if (!box->HasOverflowClip())
+ return;
+ DCHECK(box->Layer());
+ DCHECK(box->Layer()->GetScrollableArea());
+ box->Layer()->GetScrollableArea()->ScrollIntoView(
+ bounds,
+ ScrollAlignment::CreateScrollIntoViewParams(
+ ScrollAlignment::ToEdgeIfNeeded(), ScrollAlignment::ToEdgeIfNeeded(),
+ mojom::blink::ScrollType::kProgrammatic, false,
+ mojom::blink::ScrollBehavior::kInstant));
+}
+
void ListBoxSelectType::SelectAll() {
if (!select_->GetLayoutObject() || !select_->is_multiple_)
return;
@@ -1142,6 +1202,8 @@ void SelectType::DidSelectOption(HTMLOptionElement*,
select_->SetNeedsValidityCheck();
}
+void SelectType::OptionRemoved(HTMLOptionElement& option) {}
+
void SelectType::DidDetachLayoutTree() {}
void SelectType::DidRecalcStyle(const StyleRecalcChange) {}
@@ -1162,6 +1224,8 @@ const ComputedStyle* SelectType::OptionStyle() const {
void SelectType::MaximumOptionWidthMightBeChanged() const {}
+void SelectType::ScrollToOption(HTMLOptionElement* option) {}
+
void SelectType::SelectAll() {
NOTREACHED();
}
diff --git a/chromium/third_party/blink/renderer/core/html/forms/select_type.h b/chromium/third_party/blink/renderer/core/html/forms/select_type.h
index 2ce4e1bcb56..e6eb23d62d9 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/select_type.h
+++ b/chromium/third_party/blink/renderer/core/html/forms/select_type.h
@@ -28,6 +28,7 @@ class SelectType : public GarbageCollected<SelectType> {
HTMLSelectElement::SelectOptionFlags flags,
bool should_update_popup);
+ virtual void OptionRemoved(HTMLOptionElement& option);
virtual void DidBlur() = 0;
virtual void DidDetachLayoutTree();
virtual void DidRecalcStyle(const StyleRecalcChange change);
@@ -45,6 +46,7 @@ class SelectType : public GarbageCollected<SelectType> {
virtual const ComputedStyle* OptionStyle() const;
virtual void MaximumOptionWidthMightBeChanged() const;
+ virtual void ScrollToOption(HTMLOptionElement* option);
virtual void SelectAll();
virtual void SaveListboxActiveSelection();
virtual void HandleMouseRelease();
diff --git a/chromium/third_party/blink/renderer/core/html/forms/spin_button_element.cc b/chromium/third_party/blink/renderer/core/html/forms/spin_button_element.cc
index 24ea89a2682..bb7179bb155 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/spin_button_element.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/spin_button_element.cc
@@ -26,7 +26,6 @@
#include "third_party/blink/renderer/core/html/forms/spin_button_element.h"
-#include "build/build_config.h"
#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/renderer/core/event_interface_names.h"
#include "third_party/blink/renderer/core/events/mouse_event.h"
@@ -47,8 +46,8 @@ SpinButtonElement::SpinButtonElement(Document& document,
: HTMLDivElement(document),
spin_button_owner_(&spin_button_owner),
capturing_(false),
- up_down_state_(kIndeterminate),
- press_starting_state_(kIndeterminate),
+ up_down_state_(kDown),
+ press_starting_state_(kDown),
repeating_timer_(document.GetTaskRunner(TaskType::kInternalDefault),
this,
&SpinButtonElement::RepeatingTimerFired) {
@@ -87,11 +86,9 @@ void SpinButtonElement::DefaultEventHandler(Event& event) {
if (mouse_event->type() == event_type_names::kMousedown &&
mouse_event->button() ==
static_cast<int16_t>(WebPointerProperties::Button::kLeft)) {
- if (box->PixelSnappedBorderBoxRect().Contains(local)) {
if (spin_button_owner_)
spin_button_owner_->FocusAndSelectSpinButtonOwner();
if (GetLayoutObject()) {
- if (up_down_state_ != kIndeterminate) {
// A JavaScript event handler called in doStepAction() below
// might change the element state and we might need to
// cancel the repeating timer by the state change. If we
@@ -99,7 +96,6 @@ void SpinButtonElement::DefaultEventHandler(Event& event) {
// chance to cancel the timer.
StartRepeatingTimer();
DoStepAction(up_down_state_ == kUp ? 1 : -1);
- }
}
// Check |GetLayoutObject| again to make sure element is not removed by
// |DoStepAction|
@@ -113,21 +109,16 @@ void SpinButtonElement::DefaultEventHandler(Event& event) {
}
}
event.SetDefaultHandled();
- }
} else if (mouse_event->type() == event_type_names::kMouseup &&
mouse_event->button() ==
static_cast<int16_t>(WebPointerProperties::Button::kLeft)) {
ReleaseCapture();
} else if (event.type() == event_type_names::kMousemove) {
- if (box->PixelSnappedBorderBoxRect().Contains(local)) {
UpDownState old_up_down_state = up_down_state_;
up_down_state_ = (local.Y() < box->Size().Height() / 2) ? kUp : kDown;
- if (up_down_state_ != old_up_down_state)
+ if (up_down_state_ != old_up_down_state) {
GetLayoutObject()->SetShouldDoFullPaintInvalidation();
- } else {
- ReleaseCapture();
- up_down_state_ = kIndeterminate;
- }
+ }
}
if (!event.DefaultHandled())
@@ -136,7 +127,6 @@ void SpinButtonElement::DefaultEventHandler(Event& event) {
void SpinButtonElement::WillOpenPopup() {
ReleaseCapture();
- up_down_state_ = kIndeterminate;
}
void SpinButtonElement::ForwardEvent(Event& event) {
@@ -219,27 +209,13 @@ void SpinButtonElement::StopRepeatingTimer() {
void SpinButtonElement::Step(int amount) {
if (!ShouldRespondToMouseEvents())
return;
-// On Mac OS, NSStepper updates the value for the button under the mouse
-// cursor regardless of the button pressed at the beginning. So the
-// following check is not needed for Mac OS.
-#if !defined(OS_MACOSX)
- if (up_down_state_ != press_starting_state_)
- return;
-#endif
DoStepAction(amount);
}
void SpinButtonElement::RepeatingTimerFired(TimerBase*) {
- if (up_down_state_ != kIndeterminate)
Step(up_down_state_ == kUp ? 1 : -1);
}
-void SpinButtonElement::SetHovered(bool hovered) {
- if (!hovered)
- up_down_state_ = kIndeterminate;
- HTMLDivElement::SetHovered(hovered);
-}
-
bool SpinButtonElement::ShouldRespondToMouseEvents() {
return !spin_button_owner_ ||
spin_button_owner_->ShouldSpinButtonRespondToMouseEvents();
diff --git a/chromium/third_party/blink/renderer/core/html/forms/spin_button_element.h b/chromium/third_party/blink/renderer/core/html/forms/spin_button_element.h
index fdbe80f8b26..65f3284f0c7 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/spin_button_element.h
+++ b/chromium/third_party/blink/renderer/core/html/forms/spin_button_element.h
@@ -40,7 +40,6 @@ class CORE_EXPORT SpinButtonElement final : public HTMLDivElement,
public:
enum UpDownState {
- kIndeterminate, // Hovered, but the event is not handled.
kDown,
kUp,
};
@@ -91,7 +90,6 @@ class CORE_EXPORT SpinButtonElement final : public HTMLDivElement,
void StartRepeatingTimer();
void StopRepeatingTimer();
void RepeatingTimerFired(TimerBase*);
- void SetHovered(bool hovered) override;
bool ShouldRespondToMouseEvents();
bool IsMouseFocusable() const override { return false; }
diff --git a/chromium/third_party/blink/renderer/core/html/forms/text_control_element.cc b/chromium/third_party/blink/renderer/core/html/forms/text_control_element.cc
index 3792c0037a5..69211bb4443 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/text_control_element.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/text_control_element.cc
@@ -43,6 +43,7 @@
#include "third_party/blink/renderer/core/editing/selection_template.h"
#include "third_party/blink/renderer/core/editing/serializers/serialization.h"
#include "third_party/blink/renderer/core/editing/set_selection_options.h"
+#include "third_party/blink/renderer/core/editing/spellcheck/spell_checker.h"
#include "third_party/blink/renderer/core/editing/text_affinity.h"
#include "third_party/blink/renderer/core/editing/visible_position.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
@@ -253,6 +254,9 @@ void TextControlElement::SetFocused(bool flag,
if (!flag)
DispatchFormControlChangeEvent();
+
+ if (auto* inner_editor = InnerEditorElement())
+ inner_editor->FocusChanged();
}
void TextControlElement::DispatchFormControlChangeEvent() {
@@ -773,6 +777,13 @@ void TextControlElement::ParseAttribute(
params.name == html_names::kDisabledAttr) {
DisabledOrReadonlyAttributeChanged(params.name);
HTMLFormControlElementWithState::ParseAttribute(params);
+ if (params.new_value.IsNull())
+ return;
+
+ if (HTMLElement* inner_editor = InnerEditorElement()) {
+ if (auto* frame = GetDocument().GetFrame())
+ frame->GetSpellChecker().RemoveSpellingAndGrammarMarkers(*inner_editor);
+ }
} else {
HTMLFormControlElementWithState::ParseAttribute(params);
}
diff --git a/chromium/third_party/blink/renderer/core/html/forms/text_control_inner_elements.cc b/chromium/third_party/blink/renderer/core/html/forms/text_control_inner_elements.cc
index c1f64e3421c..ebd2942a7fb 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/text_control_inner_elements.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/text_control_inner_elements.cc
@@ -111,6 +111,13 @@ void TextControlInnerEditorElement::SetVisibility(bool is_visible) {
}
}
+void TextControlInnerEditorElement::FocusChanged() {
+ // When the focus changes for the host element, we may need to recalc style
+ // for text-overflow. See TextControlElement::ValueForTextOverflow().
+ SetNeedsStyleRecalc(kLocalStyleChange, StyleChangeReasonForTracing::Create(
+ style_change_reason::kControl));
+}
+
LayoutObject* TextControlInnerEditorElement::CreateLayoutObject(
const ComputedStyle&,
LegacyLayout) {
diff --git a/chromium/third_party/blink/renderer/core/html/forms/text_control_inner_elements.h b/chromium/third_party/blink/renderer/core/html/forms/text_control_inner_elements.h
index f800144a200..77206a9df82 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/text_control_inner_elements.h
+++ b/chromium/third_party/blink/renderer/core/html/forms/text_control_inner_elements.h
@@ -51,6 +51,7 @@ class TextControlInnerEditorElement final : public HTMLDivElement {
void DefaultEventHandler(Event&) override;
void SetVisibility(bool is_visible);
+ void FocusChanged();
scoped_refptr<ComputedStyle> CreateInnerEditorStyle() const;
private:
diff --git a/chromium/third_party/blink/renderer/core/html/forms/text_field_input_type.cc b/chromium/third_party/blink/renderer/core/html/forms/text_field_input_type.cc
index efb2e1ef525..07164ddc329 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/text_field_input_type.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/text_field_input_type.cc
@@ -66,6 +66,7 @@ class DataListIndicatorElement final : public HTMLDivElement {
LayoutObject* CreateLayoutObject(const ComputedStyle&,
LegacyLayout) override {
+ UseCounter::Count(GetDocument(), WebFeature::kLegacyLayoutByDetailsMarker);
return new LayoutDetailsMarker(this);
}
@@ -288,6 +289,8 @@ bool TextFieldInputType::TypeShouldForceLegacyLayout() const {
LayoutObject* TextFieldInputType::CreateLayoutObject(const ComputedStyle&,
LegacyLayout) const {
+ UseCounter::Count(GetElement().GetDocument(),
+ WebFeature::kLegacyLayoutByTextControl);
return new LayoutTextControlSingleLine(&GetElement());
}
diff --git a/chromium/third_party/blink/renderer/core/html/forms/type_ahead_test.cc b/chromium/third_party/blink/renderer/core/html/forms/type_ahead_test.cc
index dc43dbf7bb4..11f128069e0 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/type_ahead_test.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/type_ahead_test.cc
@@ -48,7 +48,7 @@ class TypeAheadTest : public ::testing::Test {
TEST_F(TypeAheadTest, HasActiveSessionAtStart) {
WebKeyboardEvent web_event(
- WebInputEvent::kChar, 0,
+ WebInputEvent::Type::kChar, 0,
base::TimeTicks() + base::TimeDelta::FromMilliseconds(500));
web_event.text[0] = ' ';
auto& event = *KeyboardEvent::Create(web_event, nullptr);
@@ -59,7 +59,7 @@ TEST_F(TypeAheadTest, HasActiveSessionAtStart) {
TEST_F(TypeAheadTest, HasActiveSessionAfterHandleEvent) {
{
WebKeyboardEvent web_event(
- WebInputEvent::kChar, 0,
+ WebInputEvent::Type::kChar, 0,
base::TimeTicks() + base::TimeDelta::FromMilliseconds(500));
web_event.text[0] = ' ';
auto& event = *KeyboardEvent::Create(web_event, nullptr);
@@ -73,7 +73,7 @@ TEST_F(TypeAheadTest, HasActiveSessionAfterHandleEvent) {
{
// Should still be active after 1 second elapses.
WebKeyboardEvent web_event(
- WebInputEvent::kChar, 0,
+ WebInputEvent::Type::kChar, 0,
base::TimeTicks() + base::TimeDelta::FromMilliseconds(1500));
web_event.text[0] = ' ';
auto& event = *KeyboardEvent::Create(web_event, nullptr);
@@ -83,7 +83,7 @@ TEST_F(TypeAheadTest, HasActiveSessionAfterHandleEvent) {
{
// But more than 1 second should be considered inactive.
WebKeyboardEvent web_event(
- WebInputEvent::kChar, 0,
+ WebInputEvent::Type::kChar, 0,
base::TimeTicks() + base::TimeDelta::FromMilliseconds(1501));
web_event.text[0] = ' ';
auto& event = *KeyboardEvent::Create(web_event, nullptr);
@@ -93,7 +93,7 @@ TEST_F(TypeAheadTest, HasActiveSessionAfterHandleEvent) {
TEST_F(TypeAheadTest, HasActiveSessionAfterResetSession) {
WebKeyboardEvent web_event(
- WebInputEvent::kChar, 0,
+ WebInputEvent::Type::kChar, 0,
base::TimeTicks() + base::TimeDelta::FromMilliseconds(500));
web_event.text[0] = ' ';
auto& event = *KeyboardEvent::Create(web_event, nullptr);
diff --git a/chromium/third_party/blink/renderer/core/html/html_anchor_element.cc b/chromium/third_party/blink/renderer/core/html/html_anchor_element.cc
index eb2c6a47cfb..3c913396405 100644
--- a/chromium/third_party/blink/renderer/core/html/html_anchor_element.cc
+++ b/chromium/third_party/blink/renderer/core/html/html_anchor_element.cc
@@ -25,7 +25,9 @@
#include "third_party/blink/renderer/core/html/html_anchor_element.h"
#include "base/metrics/histogram_macros.h"
+#include "base/time/time.h"
#include "third_party/blink/public/common/features.h"
+#include "third_party/blink/public/mojom/feature_policy/feature_policy_feature.mojom-blink.h"
#include "third_party/blink/public/mojom/input/focus_type.mojom-blink.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/web_prescient_networking.h"
@@ -40,6 +42,8 @@
#include "third_party/blink/renderer/core/html/anchor_element_metrics_sender.h"
#include "third_party/blink/renderer/core/html/html_image_element.h"
#include "third_party/blink/renderer/core/html/parser/html_parser_idioms.h"
+#include "third_party/blink/renderer/core/html_names.h"
+#include "third_party/blink/renderer/core/inspector/console_message.h"
#include "third_party/blink/renderer/core/layout/layout_box.h"
#include "third_party/blink/renderer/core/loader/frame_load_request.h"
#include "third_party/blink/renderer/core/loader/navigation_policy.h"
@@ -50,6 +54,7 @@
#include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
+#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
#include "third_party/blink/renderer/platform/weborigin/security_policy.h"
namespace blink {
@@ -78,7 +83,8 @@ bool ShouldInterveneDownloadByFramePolicy(LocalFrame* frame) {
should_intervene_download = true;
}
}
- if (document.IsSandboxed(mojom::blink::WebSandboxFlags::kDownloads)) {
+ if (document.IsSandboxed(
+ network::mojom::blink::WebSandboxFlags::kDownloads)) {
UseCounter::Count(document, WebFeature::kDownloadInSandbox);
if (RuntimeEnabledFeatures::BlockingDownloadsInSandboxEnabled())
should_intervene_download = true;
@@ -336,6 +342,86 @@ bool HTMLAnchorElement::IsLiveLink() const {
return IsLink() && !HasEditableStyle(*this);
}
+bool HTMLAnchorElement::HasImpression() const {
+ return hasAttribute(html_names::kImpressiondataAttr) &&
+ hasAttribute(html_names::kConversiondestinationAttr);
+}
+
+base::Optional<WebImpression> HTMLAnchorElement::GetImpressionForNavigation()
+ const {
+ DCHECK(HasImpression());
+
+ if (!GetExecutionContext()->IsFeatureEnabled(
+ mojom::blink::FeaturePolicyFeature::kConversionMeasurement)) {
+ String message =
+ "The 'conversion-measurement' feature policy must be enabled to "
+ "declare an impression.";
+ GetExecutionContext()->AddConsoleMessage(
+ MakeGarbageCollected<ConsoleMessage>(
+ mojom::blink::ConsoleMessageSource::kOther,
+ mojom::blink::ConsoleMessageLevel::kError, message));
+ return base::nullopt;
+ }
+
+ // Conversion measurement is only allowed when both the frame and the main
+ // frame (if different) have a secure origin.
+ LocalFrame* frame = GetDocument().GetFrame();
+ const Frame& main_frame = frame->Tree().Top();
+ if (!main_frame.GetSecurityContext()
+ ->GetSecurityOrigin()
+ ->IsPotentiallyTrustworthy()) {
+ return base::nullopt;
+ }
+ if (!frame->IsMainFrame() && !frame->GetSecurityContext()
+ ->GetSecurityOrigin()
+ ->IsPotentiallyTrustworthy()) {
+ return base::nullopt;
+ }
+
+ const AtomicString& conversion_destination_string =
+ FastGetAttribute(html_names::kConversiondestinationAttr);
+ scoped_refptr<const SecurityOrigin> conversion_destination =
+ SecurityOrigin::CreateFromString(conversion_destination_string);
+ if (!conversion_destination->IsPotentiallyTrustworthy())
+ return base::nullopt;
+
+ bool impression_data_is_valid = false;
+ uint64_t impression_data = FastGetAttribute(html_names::kImpressiondataAttr)
+ .GetString()
+ .HexToUInt64Strict(&impression_data_is_valid);
+
+ // Provide a default of 0 if the impression data was not valid.
+ impression_data = impression_data_is_valid ? impression_data : 0UL;
+
+ // Reporting origin is an optional attribute. Reporting origins must be
+ // secure.
+ base::Optional<WebSecurityOrigin> reporting_origin;
+ if (hasAttribute(html_names::kReportingoriginAttr)) {
+ const AtomicString& reporting_origin_string =
+ FastGetAttribute(html_names::kReportingoriginAttr);
+ reporting_origin =
+ SecurityOrigin::CreateFromString(reporting_origin_string);
+
+ if (!reporting_origin->IsPotentiallyTrustworthy())
+ return base::nullopt;
+ }
+
+ // Impression expiry is an optional attribute.
+ base::Optional<base::TimeDelta> expiry;
+ if (hasAttribute(html_names::kImpressionexpiryAttr)) {
+ bool expiry_is_valid = false;
+ uint64_t expiry_milliseconds =
+ FastGetAttribute(html_names::kImpressionexpiryAttr)
+ .GetString()
+ .ToUInt64Strict(&expiry_is_valid);
+ if (expiry_is_valid)
+ expiry = base::TimeDelta::FromMilliseconds(expiry_milliseconds);
+ }
+
+ return WebImpression{conversion_destination, reporting_origin,
+ impression_data, expiry};
+}
+
void HTMLAnchorElement::SendPings(const KURL& destination_url) const {
const AtomicString& ping_value = FastGetAttribute(html_names::kPingAttr);
if (ping_value.IsNull() || !GetDocument().GetSettings() ||
@@ -454,28 +540,17 @@ void HTMLAnchorElement::HandleClick(Event& event) {
WebFeature::kHTMLAnchorElementHrefTranslateAttribute);
}
- if (target_frame) {
- // If we also have a pending form submission, make sure this anchor
- // navigation takes precedence over it, except in the case of href being
- // a fragment, in which case pending form submissions should go through.
- // In the case of a target RemoteFrame, don't cancel form submissions
- // because we can't be sure what the remote document's urlForBinding is.
- // In the case of href="javascript:", don't cancel form submissions because
- // we have always let form submissions take precedence in this case.
- // TODO(crbug.com/1053679): Remove this after making anchor navigations
- // async like the spec says to do, which will also provide the desired
- // behavior.
- if (LocalFrame* target_local_frame = DynamicTo<LocalFrame>(target_frame)) {
- KURL document_url = target_local_frame->GetDocument()->urlForBinding();
- bool equal_ignoring_fragment =
- completed_url.HasFragmentIdentifier() &&
- EqualIgnoringFragmentIdentifier(completed_url, document_url);
- if (!equal_ignoring_fragment && !completed_url.ProtocolIsJavaScript())
- target_frame->CancelFormSubmission();
- }
+ // Only attach impressions for main frame navigations.
+ if (RuntimeEnabledFeatures::ConversionMeasurementEnabled() && target_frame &&
+ target_frame->IsMainFrame() && request.HasUserGesture() &&
+ HasImpression()) {
+ base::Optional<WebImpression> impression = GetImpressionForNavigation();
+ if (impression)
+ frame_request.SetImpression(*impression);
+ }
+ if (target_frame)
target_frame->Navigate(frame_request, WebFrameLoadType::kStandard);
- }
}
bool IsEnterKeyKeydownEvent(Event& event) {
diff --git a/chromium/third_party/blink/renderer/core/html/html_anchor_element.h b/chromium/third_party/blink/renderer/core/html/html_anchor_element.h
index 64a4e63e5b2..a76f6ce870c 100644
--- a/chromium/third_party/blink/renderer/core/html/html_anchor_element.h
+++ b/chromium/third_party/blink/renderer/core/html/html_anchor_element.h
@@ -24,6 +24,8 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_HTML_HTML_ANCHOR_ELEMENT_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_HTML_ANCHOR_ELEMENT_H_
+#include "base/optional.h"
+#include "third_party/blink/public/platform/web_impression.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/html/html_element.h"
@@ -90,6 +92,15 @@ class CORE_EXPORT HTMLAnchorElement : public HTMLElement, public DOMURLUtils {
LinkHash VisitedLinkHash() const;
void InvalidateCachedVisitedLinkHash() { cached_visited_link_hash_ = 0; }
+ // Returns whether this element is a valid impression declaration tag. This is
+ // determined by looking at the presence of required attributes.
+ bool HasImpression() const;
+
+ // Returns the WebImpression struct with all data declared by impression
+ // related attributes on |this|. If the impression attributes do not contain
+ // allowed values, base::nullopt is returned.
+ base::Optional<WebImpression> GetImpressionForNavigation() const;
+
void SendPings(const KURL& destination_url) const;
void Trace(Visitor*) override;
diff --git a/chromium/third_party/blink/renderer/core/html/html_attribute_names.json5 b/chromium/third_party/blink/renderer/core/html/html_attribute_names.json5
index 084b45e3e6e..f73ebeab331 100644
--- a/chromium/third_party/blink/renderer/core/html/html_attribute_names.json5
+++ b/chromium/third_party/blink/renderer/core/html/html_attribute_names.json5
@@ -57,6 +57,7 @@
"contenteditable",
"controls",
"controlslist",
+ "conversiondestination",
"coords",
"crossorigin",
"csp",
@@ -104,6 +105,8 @@
"imagesizes",
"imagesrcset",
"importance",
+ "impressiondata",
+ "impressionexpiry",
"incremental",
"inert",
"inputmode",
@@ -147,7 +150,6 @@
"nowrap",
"object",
"onabort",
- "onactivateinvisible",
"onafterprint",
"onanimationstart",
"onanimationiteration",
@@ -279,6 +281,7 @@
"readonly",
"referrerpolicy",
"rel",
+ "reportingorigin",
"required",
"rev",
"reversed",
diff --git a/chromium/third_party/blink/renderer/core/html/html_body_element.cc b/chromium/third_party/blink/renderer/core/html/html_body_element.cc
index eedcfd69ef1..f7bd4b515e7 100644
--- a/chromium/third_party/blink/renderer/core/html/html_body_element.cc
+++ b/chromium/third_party/blink/renderer/core/html/html_body_element.cc
@@ -68,7 +68,7 @@ void HTMLBodyElement::CollectStyleForPresentationAttribute(
url, GetDocument().CompleteURL(url),
Referrer(GetDocument().OutgoingReferrer(),
GetDocument().GetReferrerPolicy()),
- OriginClean::kTrue);
+ OriginClean::kTrue, false /* is_ad_related */);
image_value->SetInitiator(localName());
style->SetProperty(
CSSPropertyValue(GetCSSPropertyBackgroundImage(), *image_value));
diff --git a/chromium/third_party/blink/renderer/core/html/html_body_element.h b/chromium/third_party/blink/renderer/core/html/html_body_element.h
index cbd7c2047c1..9c22380ffe0 100644
--- a/chromium/third_party/blink/renderer/core/html/html_body_element.h
+++ b/chromium/third_party/blink/renderer/core/html/html_body_element.h
@@ -39,6 +39,9 @@ class CORE_EXPORT HTMLBodyElement final : public HTMLElement {
explicit HTMLBodyElement(Document&);
~HTMLBodyElement() override;
+ // HTMLElement override
+ bool IsHTMLBodyElement() const override { return true; }
+
DEFINE_WINDOW_ATTRIBUTE_EVENT_LISTENER(blur, kBlur)
DEFINE_WINDOW_ATTRIBUTE_EVENT_LISTENER(error, kError)
DEFINE_WINDOW_ATTRIBUTE_EVENT_LISTENER(focus, kFocus)
diff --git a/chromium/third_party/blink/renderer/core/html/html_body_element.idl b/chromium/third_party/blink/renderer/core/html/html_body_element.idl
index 53a8f4be820..cd5106207bc 100644
--- a/chromium/third_party/blink/renderer/core/html/html_body_element.idl
+++ b/chromium/third_party/blink/renderer/core/html/html_body_element.idl
@@ -36,7 +36,7 @@
// HTMLElement (which includes GlobalEventHandlers), but have different
// behavior. See https://www.w3.org/Bugs/Public/show_bug.cgi?id=28166
attribute EventHandler onblur;
- attribute EventHandler onerror;
+ attribute OnErrorEventHandler onerror;
attribute EventHandler onfocus;
attribute EventHandler onload;
attribute EventHandler onresize;
diff --git a/chromium/third_party/blink/renderer/core/html/html_collection.idl b/chromium/third_party/blink/renderer/core/html/html_collection.idl
index a07779e6de7..9efafff6f56 100644
--- a/chromium/third_party/blink/renderer/core/html/html_collection.idl
+++ b/chromium/third_party/blink/renderer/core/html/html_collection.idl
@@ -22,6 +22,7 @@
// https://dom.spec.whatwg.org/#interface-htmlcollection
[
+ Exposed=Window,
LegacyUnenumerableNamedProperties
] interface HTMLCollection {
[Affects=Nothing] readonly attribute unsigned long length;
diff --git a/chromium/third_party/blink/renderer/core/html/html_content_element.idl b/chromium/third_party/blink/renderer/core/html/html_content_element.idl
index 937de47eba2..609d07a68ac 100644
--- a/chromium/third_party/blink/renderer/core/html/html_content_element.idl
+++ b/chromium/third_party/blink/renderer/core/html/html_content_element.idl
@@ -26,7 +26,9 @@
// https://w3c.github.io/webcomponents/spec/shadow/#the-content-element
-interface HTMLContentElement : HTMLElement {
+[
+ Exposed=Window
+] interface HTMLContentElement : HTMLElement {
[Reflect] attribute DOMString select;
NodeList getDistributedNodes();
};
diff --git a/chromium/third_party/blink/renderer/core/html/html_element.cc b/chromium/third_party/blink/renderer/core/html/html_element.cc
index 1c9bd6fa2c2..8e246cb080b 100644
--- a/chromium/third_party/blink/renderer/core/html/html_element.cc
+++ b/chromium/third_party/blink/renderer/core/html/html_element.cc
@@ -365,8 +365,6 @@ AttributeTriggers* HTMLElement::TriggersForAttributeName(
{html_names::kOnabortAttr, kNoWebFeature, event_type_names::kAbort,
nullptr},
- {html_names::kOnactivateinvisibleAttr, kNoWebFeature,
- event_type_names::kActivateinvisible, nullptr},
{html_names::kOnanimationendAttr, kNoWebFeature,
event_type_names::kAnimationend, nullptr},
{html_names::kOnanimationiterationAttr, kNoWebFeature,
diff --git a/chromium/third_party/blink/renderer/core/html/html_element.h b/chromium/third_party/blink/renderer/core/html/html_element.h
index 6df6aae825a..d77acf83030 100644
--- a/chromium/third_party/blink/renderer/core/html/html_element.h
+++ b/chromium/third_party/blink/renderer/core/html/html_element.h
@@ -107,16 +107,18 @@ class CORE_EXPORT HTMLElement : public Element {
bool HasDirectionAuto() const;
TextDirection DirectionalityIfhasDirAutoAttribute(bool& is_auto) const;
+ virtual bool IsHTMLBodyElement() const { return false; }
+ virtual bool IsHTMLFrameSetElement() const { return false; }
+ virtual bool IsHTMLPortalElement() const { return false; }
virtual bool IsHTMLUnknownElement() const { return false; }
virtual bool IsPluginElement() const { return false; }
- virtual bool IsHTMLPortalElement() const { return false; }
// https://html.spec.whatwg.org/C/#category-label
virtual bool IsLabelable() const;
// |labels| IDL attribute implementation for IsLabelable()==true elements.
LabelsNodeList* labels();
- // http://www.whatwg.org/specs/web-apps/current-work/multipage/elements.html#interactive-content
+ // https://html.spec.whatwg.org/C/#interactive-content
virtual bool IsInteractiveContent() const;
void DefaultEventHandler(Event&) override;
diff --git a/chromium/third_party/blink/renderer/core/html/html_embed_element.h b/chromium/third_party/blink/renderer/core/html/html_embed_element.h
index cb5b4713444..6d6b54e95cd 100644
--- a/chromium/third_party/blink/renderer/core/html/html_embed_element.h
+++ b/chromium/third_party/blink/renderer/core/html/html_embed_element.h
@@ -23,7 +23,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_HTML_HTML_EMBED_ELEMENT_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_HTML_EMBED_ELEMENT_H_
-#include "third_party/blink/public/common/frame/frame_owner_element_type.h"
+#include "third_party/blink/public/mojom/frame/frame_owner_element_type.mojom-blink.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/html/html_plugin_element.h"
@@ -40,8 +40,8 @@ class CORE_EXPORT HTMLEmbedElement final : public HTMLPlugInElement {
bool IsExposed() const;
- FrameOwnerElementType OwnerType() const final {
- return FrameOwnerElementType::kEmbed;
+ mojom::blink::FrameOwnerElementType OwnerType() const final {
+ return mojom::blink::FrameOwnerElementType::kEmbed;
}
private:
diff --git a/chromium/third_party/blink/renderer/core/html/html_frame_element.cc b/chromium/third_party/blink/renderer/core/html/html_frame_element.cc
index fd0fbfb5cea..a55bde6e05b 100644
--- a/chromium/third_party/blink/renderer/core/html/html_frame_element.cc
+++ b/chromium/third_party/blink/renderer/core/html/html_frame_element.cc
@@ -83,8 +83,7 @@ ParsedFeaturePolicy HTMLFrameElement::ConstructContainerPolicy(
// https://fullscreen.spec.whatwg.org/#model
ParsedFeaturePolicy container_policy;
ParsedFeaturePolicyDeclaration allowlist(
- mojom::blink::FeaturePolicyFeature::kFullscreen,
- mojom::blink::PolicyValueType::kBool);
+ mojom::blink::FeaturePolicyFeature::kFullscreen);
container_policy.push_back(allowlist);
return container_policy;
}
diff --git a/chromium/third_party/blink/renderer/core/html/html_frame_element.h b/chromium/third_party/blink/renderer/core/html/html_frame_element.h
index f51994b88a7..30f604c98a7 100644
--- a/chromium/third_party/blink/renderer/core/html/html_frame_element.h
+++ b/chromium/third_party/blink/renderer/core/html/html_frame_element.h
@@ -25,7 +25,7 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_HTML_FRAME_ELEMENT_H_
#include "third_party/blink/public/common/feature_policy/feature_policy.h"
-#include "third_party/blink/public/common/frame/frame_owner_element_type.h"
+#include "third_party/blink/public/mojom/frame/frame_owner_element_type.mojom-blink.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/html/html_frame_element_base.h"
@@ -44,8 +44,8 @@ class CORE_EXPORT HTMLFrameElement final : public HTMLFrameElementBase {
ParsedFeaturePolicy ConstructContainerPolicy(
Vector<String>* /* messages */) const override;
- FrameOwnerElementType OwnerType() const final {
- return FrameOwnerElementType::kFrame;
+ mojom::blink::FrameOwnerElementType OwnerType() const final {
+ return mojom::blink::FrameOwnerElementType::kFrame;
}
private:
diff --git a/chromium/third_party/blink/renderer/core/html/html_frame_element_base.cc b/chromium/third_party/blink/renderer/core/html/html_frame_element_base.cc
index c4018d9db27..ac51562aefa 100644
--- a/chromium/third_party/blink/renderer/core/html/html_frame_element_base.cc
+++ b/chromium/third_party/blink/renderer/core/html/html_frame_element_base.cc
@@ -23,6 +23,8 @@
#include "third_party/blink/renderer/core/html/html_frame_element_base.h"
+#include "services/network/public/cpp/web_sandbox_flags.h"
+#include "services/network/public/mojom/web_sandbox_flags.mojom-blink.h"
#include "third_party/blink/renderer/bindings/core/v8/binding_security.h"
#include "third_party/blink/renderer/bindings/core/v8/script_controller.h"
#include "third_party/blink/renderer/bindings/core/v8/script_event_listener.h"
@@ -162,9 +164,10 @@ scoped_refptr<const SecurityOrigin>
HTMLFrameElementBase::GetOriginForFeaturePolicy() const {
// Sandboxed frames have a unique origin.
if ((GetFramePolicy().sandbox_flags &
- mojom::blink::WebSandboxFlags::kOrigin) !=
- mojom::blink::WebSandboxFlags::kNone)
+ network::mojom::blink::WebSandboxFlags::kOrigin) !=
+ network::mojom::blink::WebSandboxFlags::kNone) {
return SecurityOrigin::CreateUniqueOpaque();
+ }
// If the frame will inherit its origin from the owner, then use the owner's
// origin when constructing the container policy.
diff --git a/chromium/third_party/blink/renderer/core/html/html_frame_element_test.cc b/chromium/third_party/blink/renderer/core/html/html_frame_element_test.cc
index 8169d96f858..8545ba9e64f 100644
--- a/chromium/third_party/blink/renderer/core/html/html_frame_element_test.cc
+++ b/chromium/third_party/blink/renderer/core/html/html_frame_element_test.cc
@@ -36,8 +36,8 @@ TEST_F(HTMLFrameElementTest, DefaultContainerPolicy) {
// Fullscreen should be disabled in this frame
EXPECT_EQ(mojom::blink::FeaturePolicyFeature::kFullscreen,
container_policy[0].feature);
- EXPECT_EQ(0UL, container_policy[0].values.size());
- EXPECT_GE(PolicyValue(false), container_policy[0].fallback_value);
+ EXPECT_TRUE(container_policy[0].allowed_origins.empty());
+ EXPECT_GE(false, container_policy[0].fallback_value);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/html_frame_owner_element.cc b/chromium/third_party/blink/renderer/core/html/html_frame_owner_element.cc
index 9be37732a9c..08ae305ad65 100644
--- a/chromium/third_party/blink/renderer/core/html/html_frame_owner_element.cc
+++ b/chromium/third_party/blink/renderer/core/html/html_frame_owner_element.cc
@@ -23,6 +23,7 @@
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/mojom/feature_policy/feature_policy.mojom-blink.h"
#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h"
+#include "third_party/blink/public/mojom/frame/frame_owner_properties.mojom-blink.h"
#include "third_party/blink/renderer/core/accessibility/ax_object_cache.h"
#include "third_party/blink/renderer/core/css/style_change_reason.h"
#include "third_party/blink/renderer/core/dom/events/event.h"
@@ -274,7 +275,7 @@ DOMWindow* HTMLFrameOwnerElement::contentWindow() const {
}
void HTMLFrameOwnerElement::SetSandboxFlags(
- mojom::blink::WebSandboxFlags flags) {
+ network::mojom::blink::WebSandboxFlags flags) {
frame_policy_.sandbox_flags = flags;
// Recalculate the container policy in case the allow-same-origin flag has
// changed.
@@ -322,11 +323,12 @@ void HTMLFrameOwnerElement::UpdateContainerPolicy(Vector<String>* messages) {
void HTMLFrameOwnerElement::UpdateRequiredPolicy() {
const auto* frame = GetDocument().GetFrame();
- DCHECK(frame);
DocumentPolicy::FeatureState new_required_policy =
- DocumentPolicy::MergeFeatureState(
- ConstructRequiredPolicy(), /* self_required_policy */
- frame->GetRequiredDocumentPolicy() /* parent_required_policy */);
+ frame
+ ? DocumentPolicy::MergeFeatureState(
+ ConstructRequiredPolicy(), /* self_required_policy */
+ frame->GetRequiredDocumentPolicy() /* parent_required_policy */)
+ : ConstructRequiredPolicy();
// Filter out policies that are disabled by origin trials.
frame_policy_.required_document_policy.clear();
@@ -352,9 +354,28 @@ void HTMLFrameOwnerElement::FrameOwnerPropertiesChanged() {
// the subframe hasn't been created yet; or if we are in the middle of
// swapping one frame for another, in which case the final state of
// properties will be propagated at the end of the swapping operation.
- if (!is_swapping_frames_ && ContentFrame()) {
- GetDocument().GetFrame()->Client()->DidChangeFrameOwnerProperties(this);
- }
+ if (is_swapping_frames_ || !ContentFrame())
+ return;
+
+ mojom::blink::FrameOwnerPropertiesPtr properties =
+ mojom::blink::FrameOwnerProperties::New();
+ properties->name = BrowsingContextContainerName().IsNull()
+ ? WTF::g_empty_string
+ : BrowsingContextContainerName(),
+ properties->scrollbar_mode = ScrollbarMode();
+ properties->margin_width = MarginWidth();
+ properties->margin_height = MarginHeight();
+ properties->allow_fullscreen = AllowFullscreen();
+ properties->allow_payment_request = AllowPaymentRequest();
+ properties->is_display_none = IsDisplayNone();
+ properties->required_csp =
+ RequiredCsp().IsNull() ? WTF::g_empty_string : RequiredCsp();
+
+ GetDocument()
+ .GetFrame()
+ ->GetLocalFrameHostRemote()
+ .DidChangeFrameOwnerProperties(ContentFrame()->GetFrameToken(),
+ std::move(properties));
}
void HTMLFrameOwnerElement::AddResourceTiming(const ResourceTimingInfo& info) {
diff --git a/chromium/third_party/blink/renderer/core/html/html_frame_owner_element.h b/chromium/third_party/blink/renderer/core/html/html_frame_owner_element.h
index 92cb4da9957..17b942a129d 100644
--- a/chromium/third_party/blink/renderer/core/html/html_frame_owner_element.h
+++ b/chromium/third_party/blink/renderer/core/html/html_frame_owner_element.h
@@ -22,7 +22,7 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_HTML_FRAME_OWNER_ELEMENT_H_
#include "services/network/public/mojom/trust_tokens.mojom-blink-forward.h"
-#include "third_party/blink/public/common/frame/frame_owner_element_type.h"
+#include "third_party/blink/public/mojom/frame/frame_owner_element_type.mojom-blink.h"
#include "third_party/blink/public/mojom/scroll/scrollbar_mode.mojom-blink.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/dom/document.h"
@@ -66,7 +66,7 @@ class CORE_EXPORT HTMLFrameOwnerElement : public HTMLElement,
// is, to remove it from the layout as if it did not exist.
virtual void SetCollapsed(bool) {}
- virtual FrameOwnerElementType OwnerType() const = 0;
+ virtual mojom::blink::FrameOwnerElementType OwnerType() const = 0;
Document* getSVGDocument(ExceptionState&) const;
@@ -140,7 +140,7 @@ class CORE_EXPORT HTMLFrameOwnerElement : public HTMLElement,
protected:
HTMLFrameOwnerElement(const QualifiedName& tag_name, Document&);
- void SetSandboxFlags(mojom::blink::WebSandboxFlags);
+ void SetSandboxFlags(network::mojom::blink::WebSandboxFlags);
void SetAllowedToDownload(bool allowed) {
frame_policy_.allowed_to_download = allowed;
}
diff --git a/chromium/third_party/blink/renderer/core/html/html_frame_set_element.h b/chromium/third_party/blink/renderer/core/html/html_frame_set_element.h
index 4ce9a8a3190..c5d59a57976 100644
--- a/chromium/third_party/blink/renderer/core/html/html_frame_set_element.h
+++ b/chromium/third_party/blink/renderer/core/html/html_frame_set_element.h
@@ -37,6 +37,9 @@ class HTMLFrameSetElement final : public HTMLElement {
public:
explicit HTMLFrameSetElement(Document&);
+ // HTMLElement override
+ bool IsHTMLFrameSetElement() const override { return true; }
+
bool HasFrameBorder() const { return frameborder_; }
bool NoResize() const { return noresize_; }
diff --git a/chromium/third_party/blink/renderer/core/html/html_frame_set_element.idl b/chromium/third_party/blink/renderer/core/html/html_frame_set_element.idl
index 2b8e2b112b6..edbccede66b 100644
--- a/chromium/third_party/blink/renderer/core/html/html_frame_set_element.idl
+++ b/chromium/third_party/blink/renderer/core/html/html_frame_set_element.idl
@@ -33,7 +33,7 @@
// HTMLElement (which includes GlobalEventHandlers), but have different
// behavior. See https://www.w3.org/Bugs/Public/show_bug.cgi?id=28166
attribute EventHandler onblur;
- attribute EventHandler onerror;
+ attribute OnErrorEventHandler onerror;
attribute EventHandler onfocus;
attribute EventHandler onload;
attribute EventHandler onresize;
diff --git a/chromium/third_party/blink/renderer/core/html/html_iframe_element.cc b/chromium/third_party/blink/renderer/core/html/html_iframe_element.cc
index 8056ae5eb8b..742e867f733 100644
--- a/chromium/third_party/blink/renderer/core/html/html_iframe_element.cc
+++ b/chromium/third_party/blink/renderer/core/html/html_iframe_element.cc
@@ -24,7 +24,10 @@
#include "third_party/blink/renderer/core/html/html_iframe_element.h"
+#include "base/metrics/histogram_macros.h"
+#include "services/network/public/cpp/web_sandbox_flags.h"
#include "services/network/public/mojom/trust_tokens.mojom-blink.h"
+#include "services/network/public/mojom/web_sandbox_flags.mojom-blink.h"
#include "third_party/blink/public/mojom/feature_policy/feature_policy.mojom-blink.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_html_iframe_element.h"
#include "third_party/blink/renderer/core/css/css_property_names.h"
@@ -33,6 +36,7 @@
#include "third_party/blink/renderer/core/feature_policy/document_policy_parser.h"
#include "third_party/blink/renderer/core/feature_policy/feature_policy_parser.h"
#include "third_party/blink/renderer/core/feature_policy/iframe_policy.h"
+#include "third_party/blink/renderer/core/fetch/trust_token_issuance_authorization.h"
#include "third_party/blink/renderer/core/frame/csp/content_security_policy.h"
#include "third_party/blink/renderer/core/frame/sandbox_flags.h"
#include "third_party/blink/renderer/core/html/html_document.h"
@@ -148,25 +152,42 @@ void HTMLIFrameElement::ParseAttribute(
FrameOwnerPropertiesChanged();
} else if (name == html_names::kSandboxAttr) {
sandbox_->DidUpdateAttributeValue(params.old_value, value);
- String invalid_tokens;
bool feature_policy_for_sandbox =
RuntimeEnabledFeatures::FeaturePolicyForSandboxEnabled();
- mojom::blink::WebSandboxFlags current_flags =
- value.IsNull()
- ? mojom::blink::WebSandboxFlags::kNone
- : ParseSandboxPolicy(sandbox_->TokenSet(), invalid_tokens);
+
+ network::mojom::blink::WebSandboxFlags current_flags =
+ network::mojom::blink::WebSandboxFlags::kNone;
+ if (!value.IsNull()) {
+ using network::mojom::blink::WebSandboxFlags;
+ WebSandboxFlags ignored_flags =
+ !RuntimeEnabledFeatures::StorageAccessAPIEnabled()
+ ? WebSandboxFlags::kStorageAccessByUserActivation
+ : WebSandboxFlags::kNone;
+
+ auto parsed = network::ParseWebSandboxPolicy(sandbox_->value().Utf8(),
+ ignored_flags);
+ current_flags = parsed.flags;
+ if (!parsed.error_message.empty()) {
+ GetDocument().AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>(
+ mojom::blink::ConsoleMessageSource::kOther,
+ mojom::blink::ConsoleMessageLevel::kError,
+ WebString::FromUTF8(
+ "Error while parsing the 'sandbox' attribute: " +
+ parsed.error_message)));
+ }
+ }
SetAllowedToDownload(
- (current_flags & mojom::blink::WebSandboxFlags::kDownloads) ==
- mojom::blink::WebSandboxFlags::kNone);
+ (current_flags & network::mojom::blink::WebSandboxFlags::kDownloads) ==
+ network::mojom::blink::WebSandboxFlags::kNone);
// With FeaturePolicyForSandbox, sandbox flags are represented as part of
// the container policies. However, not all sandbox flags are yet converted
// and for now the residue will stay around in the stored flags.
// (see https://crbug.com/812381).
- mojom::blink::WebSandboxFlags sandbox_to_set = current_flags;
+ network::mojom::blink::WebSandboxFlags sandbox_to_set = current_flags;
sandbox_flags_converted_to_feature_policies_ =
- mojom::blink::WebSandboxFlags::kNone;
+ network::mojom::blink::WebSandboxFlags::kNone;
if (feature_policy_for_sandbox &&
- current_flags != mojom::blink::WebSandboxFlags::kNone) {
+ current_flags != network::mojom::blink::WebSandboxFlags::kNone) {
// Residue sandbox which will not be mapped to feature policies.
sandbox_to_set =
GetSandboxFlagsNotImplementedAsFeaturePolicy(current_flags);
@@ -175,12 +196,6 @@ void HTMLIFrameElement::ParseAttribute(
current_flags & ~sandbox_to_set;
}
SetSandboxFlags(sandbox_to_set);
- if (!invalid_tokens.IsNull()) {
- GetDocument().AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>(
- mojom::ConsoleMessageSource::kOther,
- mojom::ConsoleMessageLevel::kError,
- "Error while parsing the 'sandbox' attribute: " + invalid_tokens));
- }
if (RuntimeEnabledFeatures::FeaturePolicyForSandboxEnabled()) {
Vector<String> messages;
UpdateContainerPolicy(&messages);
@@ -236,6 +251,7 @@ void HTMLIFrameElement::ParseAttribute(
if (required_csp_ != value) {
required_csp_ = value;
FrameOwnerPropertiesChanged();
+ UseCounter::Count(GetDocument(), WebFeature::kIFrameCSPAttribute);
}
} else if (name == html_names::kAllowAttr) {
if (allow_ != value) {
@@ -293,13 +309,43 @@ void HTMLIFrameElement::ParseAttribute(
}
}
-// TODO(crbug.com/993790): Emit error message 'endpoint cannot be specified
-// on iframe attribute.'.
DocumentPolicy::FeatureState HTMLIFrameElement::ConstructRequiredPolicy()
const {
- return DocumentPolicyParser::Parse(required_policy_)
- .value_or(DocumentPolicy::ParsedDocumentPolicy{})
- .feature_state;
+ if (!RuntimeEnabledFeatures::DocumentPolicyEnabled(&GetDocument()))
+ return {};
+
+ if (!required_policy_.IsEmpty()) {
+ UseCounter::Count(
+ GetDocument(),
+ mojom::blink::WebFeature::kDocumentPolicyIframePolicyAttribute);
+ }
+
+ PolicyParserMessageBuffer logger;
+ DocumentPolicy::ParsedDocumentPolicy new_required_policy =
+ DocumentPolicyParser::Parse(required_policy_, logger)
+ .value_or(DocumentPolicy::ParsedDocumentPolicy{});
+
+ for (const auto& message : logger.GetMessages()) {
+ GetDocument().AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>(
+ mojom::blink::ConsoleMessageSource::kOther, message.level,
+ message.content));
+ }
+
+ if (!new_required_policy.endpoint_map.empty()) {
+ GetDocument().AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>(
+ mojom::blink::ConsoleMessageSource::kOther,
+ mojom::blink::ConsoleMessageLevel::kWarning,
+ "Iframe policy attribute cannot specify reporting endpoint."));
+ }
+
+ for (const auto& policy_entry : new_required_policy.feature_state) {
+ mojom::blink::DocumentPolicyFeature feature = policy_entry.first;
+ if (!GetDocument().DocumentPolicyFeatureObserved(feature)) {
+ UMA_HISTOGRAM_ENUMERATION(
+ "Blink.UseCounter.DocumentPolicy.PolicyAttribute", feature);
+ }
+ }
+ return new_required_policy.feature_state;
}
ParsedFeaturePolicy HTMLIFrameElement::ConstructContainerPolicy(
@@ -318,11 +364,11 @@ ParsedFeaturePolicy HTMLIFrameElement::ConstructContainerPolicy(
// If the frame is sandboxed at all, then warn if feature policy attributes
// will override the sandbox attributes.
if (messages && (sandbox_flags_converted_to_feature_policies_ &
- mojom::blink::WebSandboxFlags::kNavigation) !=
- mojom::blink::WebSandboxFlags::kNone) {
+ network::mojom::blink::WebSandboxFlags::kNavigation) !=
+ network::mojom::blink::WebSandboxFlags::kNone) {
for (const auto& pair : SandboxFlagsWithFeaturePolicies()) {
if ((sandbox_flags_converted_to_feature_policies_ & pair.first) !=
- mojom::blink::WebSandboxFlags::kNone &&
+ network::mojom::blink::WebSandboxFlags::kNone &&
IsFeatureDeclared(pair.second, container_policy)) {
messages->push_back(String::Format(
"Allow and Sandbox attributes both mention '%s'. Allow will take "
@@ -397,6 +443,7 @@ Node::InsertionNotificationRequest HTMLIFrameElement::InsertedInto(
if (required_csp_ != GetDocument().RequiredCSP()) {
required_csp_ = GetDocument().RequiredCSP();
FrameOwnerPropertiesChanged();
+ UseCounter::Count(GetDocument(), WebFeature::kIFrameCSPAttribute);
}
}
}
@@ -467,6 +514,18 @@ HTMLIFrameElement::ConstructTrustTokenParams() const {
return nullptr;
}
+ if (parsed_params->type ==
+ network::mojom::blink::TrustTokenOperationType::kIssuance &&
+ !IsTrustTokenIssuanceAvailableInExecutionContext(
+ *GetExecutionContext())) {
+ GetDocument().AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>(
+ mojom::blink::ConsoleMessageSource::kOther,
+ mojom::blink::ConsoleMessageLevel::kError,
+ "Trust Tokens issuance is disabled except in "
+ "contexts with the TrustTokens Origin Trial enabled."));
+ return nullptr;
+ }
+
return parsed_params;
}
diff --git a/chromium/third_party/blink/renderer/core/html/html_iframe_element.h b/chromium/third_party/blink/renderer/core/html/html_iframe_element.h
index 5040896b979..f5c1ee044bc 100644
--- a/chromium/third_party/blink/renderer/core/html/html_iframe_element.h
+++ b/chromium/third_party/blink/renderer/core/html/html_iframe_element.h
@@ -25,8 +25,9 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_HTML_IFRAME_ELEMENT_H_
#include "services/network/public/mojom/trust_tokens.mojom-blink-forward.h"
+#include "services/network/public/mojom/web_sandbox_flags.mojom-blink.h"
#include "third_party/blink/public/common/feature_policy/feature_policy.h"
-#include "third_party/blink/public/common/frame/frame_owner_element_type.h"
+#include "third_party/blink/public/mojom/frame/frame_owner_element_type.mojom-blink.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/html/html_frame_element_base.h"
#include "third_party/blink/renderer/core/html/html_iframe_element_sandbox.h"
@@ -58,12 +59,12 @@ class CORE_EXPORT HTMLIFrameElement final
Vector<String>* /* messages */) const override;
DocumentPolicy::FeatureState ConstructRequiredPolicy() const override;
- FrameOwnerElementType OwnerType() const final {
- return FrameOwnerElementType::kIframe;
+ mojom::blink::FrameOwnerElementType OwnerType() const final {
+ return mojom::blink::FrameOwnerElementType::kIframe;
}
- mojom::blink::WebSandboxFlags sandbox_flags_converted_to_feature_policies()
- const {
+ network::mojom::blink::WebSandboxFlags
+ sandbox_flags_converted_to_feature_policies() const {
return sandbox_flags_converted_to_feature_policies_;
}
@@ -111,8 +112,9 @@ class CORE_EXPORT HTMLIFrameElement final
// This represents a subset of sandbox flags set through 'sandbox' attribute
// that will be converted to feature policies as part of the container
// policies.
- mojom::blink::WebSandboxFlags sandbox_flags_converted_to_feature_policies_ =
- mojom::blink::WebSandboxFlags::kNone;
+ network::mojom::blink::WebSandboxFlags
+ sandbox_flags_converted_to_feature_policies_ =
+ network::mojom::blink::WebSandboxFlags::kNone;
network::mojom::ReferrerPolicy referrer_policy_;
};
diff --git a/chromium/third_party/blink/renderer/core/html/html_iframe_element.idl b/chromium/third_party/blink/renderer/core/html/html_iframe_element.idl
index 99283b0c160..a2ec716d1ee 100644
--- a/chromium/third_party/blink/renderer/core/html/html_iframe_element.idl
+++ b/chromium/third_party/blink/renderer/core/html/html_iframe_element.idl
@@ -55,7 +55,7 @@
[RuntimeEnabled=LazyFrameLoading, CEReactions, Reflect, ReflectOnly=("lazy", "eager", "auto"), ReflectMissing="auto", ReflectInvalid="auto"] attribute DOMString loading;
// Trust Tokens request parameters (https://github.com/wicg/trust-token-api)
- [RuntimeEnabled=TrustTokens, SecureContext, Reflect] attribute DOMString trustToken;
+ [RuntimeEnabled=TrustTokens, SecureContext, Reflect, MeasureAs=TrustTokenIframe] attribute DOMString trustToken;
// obsolete members
// https://html.spec.whatwg.org/C/#HTMLIFrameElement-partial
diff --git a/chromium/third_party/blink/renderer/core/html/html_iframe_element_test.cc b/chromium/third_party/blink/renderer/core/html/html_iframe_element_test.cc
index 71f5cd53348..379168d4327 100644
--- a/chromium/third_party/blink/renderer/core/html/html_iframe_element_test.cc
+++ b/chromium/third_party/blink/renderer/core/html/html_iframe_element_test.cc
@@ -10,6 +10,8 @@
#include "third_party/blink/renderer/core/dom/document_init.h"
#include "third_party/blink/renderer/core/feature_policy/feature_policy_parser.h"
#include "third_party/blink/renderer/core/testing/dummy_page_holder.h"
+#include "third_party/blink/renderer/core/testing/sim/sim_request.h"
+#include "third_party/blink/renderer/core/testing/sim/sim_test.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
#include "third_party/blink/renderer/platform/wtf/text/string_utf8_adaptor.h"
@@ -41,9 +43,6 @@ class HTMLIFrameElementTest : public testing::Test {
}
protected:
- const PolicyValue min_value = PolicyValue(false);
- const PolicyValue max_value = PolicyValue(true);
-
std::unique_ptr<DummyPageHolder> page_holder_;
Persistent<Document> document_;
Persistent<HTMLIFrameElement> frame_element_;
@@ -168,10 +167,10 @@ TEST_F(HTMLIFrameElementTest, AllowAttributeContainerPolicy) {
EXPECT_EQ(1UL, container_policy1.size());
EXPECT_EQ(mojom::blink::FeaturePolicyFeature::kFullscreen,
container_policy1[0].feature);
- EXPECT_GE(min_value, container_policy1[0].fallback_value);
- EXPECT_EQ(1UL, container_policy1[0].values.size());
+ EXPECT_FALSE(container_policy1[0].fallback_value);
+ EXPECT_EQ(1UL, container_policy1[0].allowed_origins.size());
EXPECT_EQ("http://example.net",
- container_policy1[0].values.begin()->first.Serialize());
+ container_policy1[0].allowed_origins.begin()->Serialize());
frame_element_->setAttribute(html_names::kAllowAttr, "payment; fullscreen");
frame_element_->UpdateContainerPolicyForTests();
@@ -187,13 +186,13 @@ TEST_F(HTMLIFrameElementTest, AllowAttributeContainerPolicy) {
mojom::blink::FeaturePolicyFeature::kPayment ||
container_policy2[1].feature ==
mojom::blink::FeaturePolicyFeature::kPayment);
- EXPECT_EQ(1UL, container_policy2[0].values.size());
+ EXPECT_EQ(1UL, container_policy2[0].allowed_origins.size());
EXPECT_EQ("http://example.net",
- container_policy2[0].values.begin()->first.Serialize());
- EXPECT_GE(min_value, container_policy2[1].fallback_value);
- EXPECT_EQ(1UL, container_policy2[1].values.size());
+ container_policy2[0].allowed_origins.begin()->Serialize());
+ EXPECT_FALSE(container_policy2[1].fallback_value);
+ EXPECT_EQ(1UL, container_policy2[1].allowed_origins.size());
EXPECT_EQ("http://example.net",
- container_policy2[1].values.begin()->first.Serialize());
+ container_policy2[1].allowed_origins.begin()->Serialize());
}
// Sandboxing an iframe should result in a container policy with an item for
@@ -235,9 +234,9 @@ TEST_F(HTMLIFrameElementTest, CrossOriginSandboxAttributeContainerPolicy) {
const ParsedFeaturePolicyDeclaration item = *container_policy_item;
EXPECT_EQ(mojom::blink::FeaturePolicyFeature::kFullscreen, item.feature);
- EXPECT_GE(min_value, item.fallback_value);
- EXPECT_LE(max_value, item.opaque_value);
- EXPECT_EQ(0UL, item.values.size());
+ EXPECT_FALSE(item.fallback_value);
+ EXPECT_TRUE(item.opaque_value);
+ EXPECT_EQ(0UL, item.allowed_origins.size());
}
// Test that the allow attribute on a sandboxed frame with the allow-same-origin
@@ -266,11 +265,11 @@ TEST_F(HTMLIFrameElementTest, SameOriginSandboxAttributeContainerPolicy) {
const ParsedFeaturePolicyDeclaration item = *container_policy_item;
EXPECT_EQ(mojom::blink::FeaturePolicyFeature::kFullscreen, item.feature);
- EXPECT_GE(min_value, item.fallback_value);
- EXPECT_GE(min_value, item.opaque_value);
- EXPECT_EQ(1UL, item.values.size());
- EXPECT_FALSE(item.values.begin()->first.opaque());
- EXPECT_EQ("http://example.net", item.values.begin()->first.Serialize());
+ EXPECT_FALSE(item.fallback_value);
+ EXPECT_FALSE(item.opaque_value);
+ EXPECT_EQ(1UL, item.allowed_origins.size());
+ EXPECT_FALSE(item.allowed_origins.begin()->opaque());
+ EXPECT_EQ("http://example.net", item.allowed_origins.begin()->Serialize());
}
// Test the ConstructContainerPolicy method when no attributes are set on the
@@ -290,14 +289,14 @@ TEST_F(HTMLIFrameElementTest, ConstructContainerPolicy) {
EXPECT_EQ(2UL, container_policy.size());
EXPECT_EQ(mojom::blink::FeaturePolicyFeature::kPayment,
container_policy[0].feature);
- EXPECT_GE(min_value, container_policy[0].fallback_value);
- EXPECT_EQ(1UL, container_policy[0].values.size());
- EXPECT_TRUE(container_policy[0].values.begin()->first.IsSameOriginWith(
+ EXPECT_FALSE(container_policy[0].fallback_value);
+ EXPECT_EQ(1UL, container_policy[0].allowed_origins.size());
+ EXPECT_TRUE(container_policy[0].allowed_origins.begin()->IsSameOriginWith(
GetOriginForFeaturePolicy(frame_element_)->ToUrlOrigin()));
EXPECT_EQ(mojom::blink::FeaturePolicyFeature::kUsb,
container_policy[1].feature);
- EXPECT_EQ(1UL, container_policy[1].values.size());
- EXPECT_TRUE(container_policy[1].values.begin()->first.IsSameOriginWith(
+ EXPECT_EQ(1UL, container_policy[1].allowed_origins.size());
+ EXPECT_TRUE(container_policy[1].allowed_origins.begin()->IsSameOriginWith(
GetOriginForFeaturePolicy(frame_element_)->ToUrlOrigin()));
}
@@ -311,7 +310,7 @@ TEST_F(HTMLIFrameElementTest, ConstructContainerPolicyWithAllowFullscreen) {
EXPECT_EQ(1UL, container_policy.size());
EXPECT_EQ(mojom::blink::FeaturePolicyFeature::kFullscreen,
container_policy[0].feature);
- EXPECT_LE(max_value, container_policy[0].fallback_value);
+ EXPECT_TRUE(container_policy[0].fallback_value);
}
// Test the ConstructContainerPolicy method when the "allowpaymentrequest"
@@ -326,9 +325,9 @@ TEST_F(HTMLIFrameElementTest, ConstructContainerPolicyWithAllowPaymentRequest) {
EXPECT_EQ(2UL, container_policy.size());
EXPECT_EQ(mojom::blink::FeaturePolicyFeature::kUsb,
container_policy[0].feature);
- EXPECT_GE(min_value, container_policy[0].fallback_value);
- EXPECT_EQ(1UL, container_policy[0].values.size());
- EXPECT_TRUE(container_policy[0].values.begin()->first.IsSameOriginWith(
+ EXPECT_FALSE(container_policy[0].fallback_value);
+ EXPECT_EQ(1UL, container_policy[0].allowed_origins.size());
+ EXPECT_TRUE(container_policy[0].allowed_origins.begin()->IsSameOriginWith(
GetOriginForFeaturePolicy(frame_element_)->ToUrlOrigin()));
EXPECT_EQ(mojom::blink::FeaturePolicyFeature::kPayment,
container_policy[1].feature);
@@ -351,17 +350,39 @@ TEST_F(HTMLIFrameElementTest, ConstructContainerPolicyWithAllowAttributes) {
EXPECT_EQ(3UL, container_policy.size());
EXPECT_EQ(mojom::blink::FeaturePolicyFeature::kPayment,
container_policy[0].feature);
- EXPECT_GE(min_value, container_policy[0].fallback_value);
- EXPECT_EQ(1UL, container_policy[0].values.size());
- EXPECT_TRUE(container_policy[0].values.begin()->first.IsSameOriginWith(
+ EXPECT_FALSE(container_policy[0].fallback_value);
+ EXPECT_EQ(1UL, container_policy[0].allowed_origins.size());
+ EXPECT_TRUE(container_policy[0].allowed_origins.begin()->IsSameOriginWith(
GetOriginForFeaturePolicy(frame_element_)->ToUrlOrigin()));
EXPECT_EQ(mojom::blink::FeaturePolicyFeature::kUsb,
container_policy[1].feature);
- EXPECT_EQ(1UL, container_policy[1].values.size());
- EXPECT_TRUE(container_policy[1].values.begin()->first.IsSameOriginWith(
+ EXPECT_EQ(1UL, container_policy[1].allowed_origins.size());
+ EXPECT_TRUE(container_policy[1].allowed_origins.begin()->IsSameOriginWith(
GetOriginForFeaturePolicy(frame_element_)->ToUrlOrigin()));
EXPECT_EQ(mojom::blink::FeaturePolicyFeature::kFullscreen,
container_policy[2].feature);
}
+using HTMLIFrameElementSimTest = SimTest;
+
+TEST_F(HTMLIFrameElementSimTest, PolicyAttributeParsingError) {
+ blink::ScopedDocumentPolicyForTest sdp(true);
+ SimRequest main_resource("https://example.com", "text/html");
+ LoadURL("https://example.com");
+ main_resource.Complete(R"(
+ <iframe policy="bad-feature-name"></iframe>
+ )");
+
+ // Note: Parsing of policy attribute string, i.e. call to
+ // HTMLFrameOwnerElement::UpdateRequiredPolicy(), happens twice in above
+ // situation:
+ // - HTMLFrameOwnerElement::LoadOrRedirectSubframe()
+ // - HTMLIFrameElement::ParseAttribute()
+ EXPECT_EQ(ConsoleMessages().size(), 2u);
+ for (const auto& message : ConsoleMessages()) {
+ EXPECT_TRUE(
+ message.StartsWith("Unrecognized document policy feature name"));
+ }
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/html_image_element.cc b/chromium/third_party/blink/renderer/core/html/html_image_element.cc
index e40958fc877..c54d6c04fa7 100644
--- a/chromium/third_party/blink/renderer/core/html/html_image_element.cc
+++ b/chromium/third_party/blink/renderer/core/html/html_image_element.cc
@@ -268,13 +268,20 @@ void HTMLImageElement::ParseAttribute(
} else if (name == html_names::kUsemapAttr) {
SetIsLink(!params.new_value.IsNull());
} else if (name == html_names::kReferrerpolicyAttr) {
+ network::mojom::ReferrerPolicy old_referrer_policy = referrer_policy_;
referrer_policy_ = network::mojom::ReferrerPolicy::kDefault;
if (!params.new_value.IsNull()) {
+ UseCounter::Count(GetDocument(),
+ WebFeature::kHTMLImageElementReferrerPolicyAttribute);
+
SecurityPolicy::ReferrerPolicyFromString(
params.new_value, kSupportReferrerPolicyLegacyKeywords,
&referrer_policy_);
- UseCounter::Count(GetDocument(),
- WebFeature::kHTMLImageElementReferrerPolicyAttribute);
+ }
+
+ if (referrer_policy_ != old_referrer_policy) {
+ GetImageLoader().UpdateFromElement(
+ ImageLoader::kUpdateIgnorePreviousError, referrer_policy_);
}
} else if (name == html_names::kDecodingAttr) {
UseCounter::Count(GetDocument(), WebFeature::kImageDecodingAttribute);
diff --git a/chromium/third_party/blink/renderer/core/html/html_object_element.h b/chromium/third_party/blink/renderer/core/html/html_object_element.h
index 41b294c6ed1..6c14c233483 100644
--- a/chromium/third_party/blink/renderer/core/html/html_object_element.h
+++ b/chromium/third_party/blink/renderer/core/html/html_object_element.h
@@ -23,7 +23,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_HTML_HTML_OBJECT_ELEMENT_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_HTML_OBJECT_ELEMENT_H_
-#include "third_party/blink/public/common/frame/frame_owner_element_type.h"
+#include "third_party/blink/public/mojom/frame/frame_owner_element_type.mojom-blink.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/html/forms/form_associated.h"
#include "third_party/blink/renderer/core/html/forms/listed_element.h"
@@ -69,8 +69,8 @@ class CORE_EXPORT HTMLObjectElement final : public HTMLPlugInElement,
bool ChildrenCanHaveStyle() const override { return UseFallbackContent(); }
- FrameOwnerElementType OwnerType() const final {
- return FrameOwnerElementType::kObject;
+ mojom::blink::FrameOwnerElementType OwnerType() const final {
+ return mojom::blink::FrameOwnerElementType::kObject;
}
// Implementations of constraint validation API.
diff --git a/chromium/third_party/blink/renderer/core/html/html_plugin_element.cc b/chromium/third_party/blink/renderer/core/html/html_plugin_element.cc
index a1564b5d615..f1211b41033 100644
--- a/chromium/third_party/blink/renderer/core/html/html_plugin_element.cc
+++ b/chromium/third_party/blink/renderer/core/html/html_plugin_element.cc
@@ -281,8 +281,7 @@ ParsedFeaturePolicy HTMLPlugInElement::ConstructContainerPolicy(
// https://fullscreen.spec.whatwg.org/#model
ParsedFeaturePolicy container_policy;
ParsedFeaturePolicyDeclaration allowlist(
- mojom::blink::FeaturePolicyFeature::kFullscreen,
- mojom::blink::PolicyValueType::kBool);
+ mojom::blink::FeaturePolicyFeature::kFullscreen);
container_policy.push_back(allowlist);
return container_policy;
}
@@ -483,7 +482,7 @@ bool HTMLPlugInElement::IsKeyboardFocusable() const {
if (HTMLFrameOwnerElement::IsKeyboardFocusable())
return true;
return GetDocument().IsActive() && PluginEmbeddedContentView() &&
- PluginEmbeddedContentView()->SupportsKeyboardFocus();
+ PluginEmbeddedContentView()->SupportsKeyboardFocus() && IsFocusable();
}
bool HTMLPlugInElement::HasCustomFocusLogic() const {
@@ -727,12 +726,14 @@ bool HTMLPlugInElement::AllowedToLoadObject(const KURL& url,
return (!mime_type.IsEmpty() && url.IsEmpty()) ||
!MixedContentChecker::ShouldBlockFetch(
frame, mojom::RequestContextType::OBJECT,
- ResourceRequest::RedirectStatus::kNoRedirect, url);
+ ResourceRequest::RedirectStatus::kNoRedirect, url,
+ /* devtools_id= */ base::nullopt);
}
bool HTMLPlugInElement::AllowedToLoadPlugin(const KURL& url,
const String& mime_type) {
- if (GetDocument().IsSandboxed(mojom::blink::WebSandboxFlags::kPlugins)) {
+ if (GetDocument().IsSandboxed(
+ network::mojom::blink::WebSandboxFlags::kPlugins)) {
GetDocument().AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>(
mojom::ConsoleMessageSource::kSecurity,
mojom::ConsoleMessageLevel::kError,
diff --git a/chromium/third_party/blink/renderer/core/html/html_rt_element.cc b/chromium/third_party/blink/renderer/core/html/html_rt_element.cc
index fba2fe9663e..e159d113a51 100644
--- a/chromium/third_party/blink/renderer/core/html/html_rt_element.cc
+++ b/chromium/third_party/blink/renderer/core/html/html_rt_element.cc
@@ -6,16 +6,27 @@
#include "third_party/blink/renderer/core/html_names.h"
#include "third_party/blink/renderer/core/layout/layout_ruby_text.h"
+#include "third_party/blink/renderer/core/layout/ng/layout_ng_ruby_text.h"
namespace blink {
HTMLRTElement::HTMLRTElement(Document& document)
: HTMLElement(html_names::kRtTag, document) {}
+bool HTMLRTElement::TypeShouldForceLegacyLayout() const {
+ return !RuntimeEnabledFeatures::LayoutNGRubyEnabled();
+}
+
LayoutObject* HTMLRTElement::CreateLayoutObject(const ComputedStyle& style,
LegacyLayout legacy) {
- if (style.Display() == EDisplay::kBlock)
- return new LayoutRubyText(this);
+ if (style.Display() == EDisplay::kBlock) {
+ if (!RuntimeEnabledFeatures::LayoutNGRubyEnabled() ||
+ legacy == LegacyLayout::kForce) {
+ UseCounter::Count(GetDocument(), WebFeature::kLegacyLayoutByRuby);
+ return new LayoutRubyText(this);
+ }
+ return new LayoutNGRubyText(this);
+ }
return LayoutObject::CreateObject(this, style, legacy);
}
diff --git a/chromium/third_party/blink/renderer/core/html/html_rt_element.h b/chromium/third_party/blink/renderer/core/html/html_rt_element.h
index 04a6891f955..9b296cf828b 100644
--- a/chromium/third_party/blink/renderer/core/html/html_rt_element.h
+++ b/chromium/third_party/blink/renderer/core/html/html_rt_element.h
@@ -17,7 +17,7 @@ class HTMLRTElement final : public HTMLElement {
private:
LayoutObject* CreateLayoutObject(const ComputedStyle&, LegacyLayout) override;
- bool TypeShouldForceLegacyLayout() const final { return true; }
+ bool TypeShouldForceLegacyLayout() const final;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/html_ruby_element.cc b/chromium/third_party/blink/renderer/core/html/html_ruby_element.cc
index c40fddf902f..9245cf9360a 100644
--- a/chromium/third_party/blink/renderer/core/html/html_ruby_element.cc
+++ b/chromium/third_party/blink/renderer/core/html/html_ruby_element.cc
@@ -5,19 +5,30 @@
#include "third_party/blink/renderer/core/html/html_ruby_element.h"
#include "third_party/blink/renderer/core/html_names.h"
+#include "third_party/blink/renderer/core/layout/layout_object_factory.h"
#include "third_party/blink/renderer/core/layout/layout_ruby.h"
+#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
namespace blink {
HTMLRubyElement::HTMLRubyElement(Document& document)
: HTMLElement(html_names::kRubyTag, document) {}
+bool HTMLRubyElement::TypeShouldForceLegacyLayout() const {
+ if (RuntimeEnabledFeatures::LayoutNGRubyEnabled())
+ return false;
+ UseCounter::Count(GetDocument(), WebFeature::kLegacyLayoutByRuby);
+ return true;
+}
+
LayoutObject* HTMLRubyElement::CreateLayoutObject(const ComputedStyle& style,
LegacyLayout legacy) {
if (style.Display() == EDisplay::kInline)
return new LayoutRubyAsInline(this);
- if (style.Display() == EDisplay::kBlock)
- return new LayoutRubyAsBlock(this);
+ if (style.Display() == EDisplay::kBlock) {
+ UseCounter::Count(GetDocument(), WebFeature::kRubyElementWithDisplayBlock);
+ return LayoutObjectFactory::CreateRubyAsBlock(this, style, legacy);
+ }
return LayoutObject::CreateObject(this, style, legacy);
}
diff --git a/chromium/third_party/blink/renderer/core/html/html_ruby_element.h b/chromium/third_party/blink/renderer/core/html/html_ruby_element.h
index 7f05b0fd7ed..71a4df05946 100644
--- a/chromium/third_party/blink/renderer/core/html/html_ruby_element.h
+++ b/chromium/third_party/blink/renderer/core/html/html_ruby_element.h
@@ -17,7 +17,7 @@ class HTMLRubyElement final : public HTMLElement {
private:
LayoutObject* CreateLayoutObject(const ComputedStyle&, LegacyLayout) override;
- bool TypeShouldForceLegacyLayout() const final { return true; }
+ bool TypeShouldForceLegacyLayout() const final;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/html_script_element.cc b/chromium/third_party/blink/renderer/core/html/html_script_element.cc
index 1fda09d556e..fd8290a81c4 100644
--- a/chromium/third_party/blink/renderer/core/html/html_script_element.cc
+++ b/chromium/third_party/blink/renderer/core/html/html_script_element.cc
@@ -279,6 +279,10 @@ Document& HTMLScriptElement::GetDocument() const {
return Node::GetDocument();
}
+ExecutionContext* HTMLScriptElement::GetExecutionContext() const {
+ return Node::GetExecutionContext();
+}
+
void HTMLScriptElement::DispatchLoadEvent() {
DispatchEvent(*Event::Create(event_type_names::kLoad));
}
diff --git a/chromium/third_party/blink/renderer/core/html/html_script_element.h b/chromium/third_party/blink/renderer/core/html/html_script_element.h
index dc5f7fb99a6..6315197c09a 100644
--- a/chromium/third_party/blink/renderer/core/html/html_script_element.h
+++ b/chromium/third_party/blink/renderer/core/html/html_script_element.h
@@ -62,6 +62,7 @@ class CORE_EXPORT HTMLScriptElement final : public HTMLElement,
bool IsScriptElement() const override { return true; }
Document& GetDocument() const override;
+ ExecutionContext* GetExecutionContext() const override;
void Trace(Visitor*) override;
diff --git a/chromium/third_party/blink/renderer/core/html/html_shadow_element.idl b/chromium/third_party/blink/renderer/core/html/html_shadow_element.idl
index 035492c5035..1939442db51 100644
--- a/chromium/third_party/blink/renderer/core/html/html_shadow_element.idl
+++ b/chromium/third_party/blink/renderer/core/html/html_shadow_element.idl
@@ -30,6 +30,8 @@
// https://w3c.github.io/webcomponents/spec/shadow/#the-shadow-element
-interface HTMLShadowElement : HTMLElement {
+[
+ Exposed=Window
+] interface HTMLShadowElement : HTMLElement {
NodeList getDistributedNodes();
};
diff --git a/chromium/third_party/blink/renderer/core/html/html_slot_element.cc b/chromium/third_party/blink/renderer/core/html/html_slot_element.cc
index fd8cc754219..c0d3b990d97 100644
--- a/chromium/third_party/blink/renderer/core/html/html_slot_element.cc
+++ b/chromium/third_party/blink/renderer/core/html/html_slot_element.cc
@@ -72,8 +72,6 @@ HTMLSlotElement* HTMLSlotElement::CreateUserAgentCustomAssignSlot(
HTMLSlotElement::HTMLSlotElement(Document& document)
: HTMLElement(html_names::kSlotTag, document) {
UseCounter::Count(document, WebFeature::kHTMLSlotElement);
- if (!RuntimeEnabledFeatures::FlatTreeStyleRecalcEnabled())
- SetHasCustomStyleCallbacks();
}
// static
@@ -171,6 +169,21 @@ const HeapVector<Member<Element>> HTMLSlotElement::AssignedElementsForBinding(
return elements;
}
+bool HTMLSlotElement::CheckNodesValidity(HeapVector<Member<Node>> nodes,
+ ExceptionState& exception_state) {
+ auto* host = OwnerShadowHost();
+ for (auto& node : nodes) {
+ if (node->parentNode() != host) {
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kNotAllowedError,
+ "Node: '" + node->nodeName() +
+ "' is invalid for manual slot assignment.");
+ return false;
+ }
+ }
+ return true;
+}
+
void HTMLSlotElement::assign(HeapVector<Member<Node>> nodes,
ExceptionState& exception_state) {
if (!SupportsAssignment() || !ContainingShadowRoot()->IsManualSlotting()) {
@@ -180,24 +193,39 @@ void HTMLSlotElement::assign(HeapVector<Member<Node>> nodes,
return;
}
- assigned_nodes_candidates_.clear();
- auto* host = OwnerShadowHost();
- bool has_invalid_node = false;
+ if (!CheckNodesValidity(nodes, exception_state))
+ return;
+
+ ContainingShadowRoot()->GetSlotAssignment().ClearCandidateNodes(
+ assigned_nodes_candidates_);
+ HeapLinkedHashSet<Member<Node>> candidates;
+ bool updated = false;
for (auto& node : nodes) {
- if (node->parentNode() != host) {
- exception_state.ThrowDOMException(
- DOMExceptionCode::kNotAllowedError,
- "Node: '" + node->nodeName() +
- "' is invalid for manual slot assignment.");
- assigned_nodes_candidates_.clear();
- has_invalid_node = true;
- break;
+ // Before assignment, see if this node belongs to another slot.
+ updated |= ContainingShadowRoot()
+ ->GetSlotAssignment()
+ .UpdateCandidateNodeAssignedSlot(*node, *this);
+ candidates.AppendOrMoveToLast(node);
+ }
+
+ bool candidates_changed =
+ (updated || (candidates.size() != assigned_nodes_candidates_.size()));
+ if (!candidates_changed) {
+ for (auto it1 = candidates.begin(),
+ it2 = assigned_nodes_candidates_.begin();
+ it1 != candidates.end(); ++it1, ++it2) {
+ if (!(*it1 == *it2)) {
+ candidates_changed = true;
+ break;
+ }
}
- assigned_nodes_candidates_.insert(node);
}
- if (!has_invalid_node)
+ if (candidates_changed) {
+ assigned_nodes_candidates_.Swap(candidates);
ContainingShadowRoot()->GetSlotAssignment().SetNeedsAssignmentRecalc();
+ DidSlotChange(SlotChangeType::kSignalSlotChangeEvent);
+ }
}
void HTMLSlotElement::AppendAssignedNode(Node& host_child) {
@@ -205,6 +233,34 @@ void HTMLSlotElement::AppendAssignedNode(Node& host_child) {
assigned_nodes_.push_back(&host_child);
}
+void HTMLSlotElement::UpdateManuallyAssignedNodesOrdering() {
+ if (assigned_nodes_.IsEmpty() || assigned_nodes_candidates_.IsEmpty())
+ return;
+
+ // TODO: (1067153) Add perf benchmark test for large assigned list.
+ HeapHashSet<Member<Node>> prev_nodes;
+ for (auto& node : assigned_nodes_) {
+ prev_nodes.insert(node);
+ }
+ assigned_nodes_.clear();
+ for (auto& node : assigned_nodes_candidates_) {
+ if (prev_nodes.Contains(node))
+ assigned_nodes_.push_back(node);
+ }
+}
+
+void HTMLSlotElement::RemoveAssignedNodeCandidate(Node& node) {
+ auto it = assigned_nodes_candidates_.find(&node);
+ if (it != assigned_nodes_candidates_.end()) {
+ assigned_nodes_candidates_.erase(it);
+ DidSlotChange(SlotChangeType::kSignalSlotChangeEvent);
+ }
+}
+
+void HTMLSlotElement::ClearAssignedNodesCandidates() {
+ assigned_nodes_candidates_.clear();
+}
+
void HTMLSlotElement::ClearAssignedNodes() {
assigned_nodes_.clear();
}
@@ -411,26 +467,8 @@ void HTMLSlotElement::RemovedFrom(ContainerNode& insertion_point) {
HTMLElement::RemovedFrom(insertion_point);
}
-void HTMLSlotElement::DidRecalcStyle(const StyleRecalcChange change) {
- DCHECK(!RuntimeEnabledFeatures::FlatTreeStyleRecalcEnabled());
- if (!change.RecalcChildren())
- return;
- for (auto& node : assigned_nodes_) {
- if (!change.TraverseChild(*node))
- continue;
- if (auto* element = DynamicTo<Element>(node.Get()))
- element->RecalcStyle(change);
- else if (auto* text_node = DynamicTo<Text>(node.Get()))
- text_node->RecalcTextStyle(change);
- }
-}
-
void HTMLSlotElement::RecalcStyleForSlotChildren(
const StyleRecalcChange change) {
- if (!RuntimeEnabledFeatures::FlatTreeStyleRecalcEnabled()) {
- RecalcDescendantStyles(change);
- return;
- }
for (auto& node : flat_tree_children_) {
if (!change.TraverseChild(*node))
continue;
diff --git a/chromium/third_party/blink/renderer/core/html/html_slot_element.h b/chromium/third_party/blink/renderer/core/html/html_slot_element.h
index f3d054d8136..dab5c1f8416 100644
--- a/chromium/third_party/blink/renderer/core/html/html_slot_element.h
+++ b/chromium/third_party/blink/renderer/core/html/html_slot_element.h
@@ -73,6 +73,7 @@ class CORE_EXPORT HTMLSlotElement final : public HTMLElement {
void WillRecalcAssignedNodes() { ClearAssignedNodes(); }
void DidRecalcAssignedNodes() {
+ UpdateManuallyAssignedNodesOrdering();
UpdateFlatTreeNodeDataForAssignedNodes();
RecalcFlatTreeChildren();
}
@@ -111,16 +112,17 @@ class CORE_EXPORT HTMLSlotElement final : public HTMLElement {
// For imperative Shadow DOM distribution APIs
void assign(HeapVector<Member<Node>> nodes, ExceptionState&);
- const HeapHashSet<Member<Node>>& AssignedNodesCandidate() const {
+ const HeapLinkedHashSet<Member<Node>>& AssignedNodesCandidates() const {
return assigned_nodes_candidates_;
}
+ void ClearAssignedNodesCandidates();
+ void RemoveAssignedNodeCandidate(Node&);
void Trace(Visitor*) override;
private:
InsertionNotificationRequest InsertedInto(ContainerNode&) final;
void RemovedFrom(ContainerNode&) final;
- void DidRecalcStyle(const StyleRecalcChange) final;
void EnqueueSlotChangeEvent();
@@ -137,7 +139,10 @@ class CORE_EXPORT HTMLSlotElement final : public HTMLElement {
const HeapVector<Member<Node>>& new_slotted);
void SetNeedsDistributionRecalcWillBeSetNeedsAssignmentRecalc();
+ bool CheckNodesValidity(HeapVector<Member<Node>> nodes, ExceptionState&);
+ // SlotAssignnment:recalc runs in tree order. Update to assigned order.
+ void UpdateManuallyAssignedNodesOrdering();
void RecalcFlatTreeChildren();
void UpdateFlatTreeNodeDataForAssignedNodes();
void ClearAssignedNodesAndFlatTreeChildren();
@@ -147,8 +152,9 @@ class CORE_EXPORT HTMLSlotElement final : public HTMLElement {
bool slotchange_event_enqueued_ = false;
- // For imperative Shadow DOM distribution APIs
- HeapHashSet<Member<Node>> assigned_nodes_candidates_;
+ // For imperative Shadow DOM distribution APIs.
+ // LinkedHashSet because candidates are ordered.
+ HeapLinkedHashSet<Member<Node>> assigned_nodes_candidates_;
template <typename T, wtf_size_t S>
struct LCSArray {
diff --git a/chromium/third_party/blink/renderer/core/html/html_slot_element.idl b/chromium/third_party/blink/renderer/core/html/html_slot_element.idl
index ce9723fd78f..1185b83777c 100644
--- a/chromium/third_party/blink/renderer/core/html/html_slot_element.idl
+++ b/chromium/third_party/blink/renderer/core/html/html_slot_element.idl
@@ -25,8 +25,10 @@
*/
// https://html.spec.whatwg.org/C/#the-slot-element
-[HTMLConstructor]
-interface HTMLSlotElement : HTMLElement {
+[
+ Exposed=Window,
+ HTMLConstructor
+] interface HTMLSlotElement : HTMLElement {
[CEReactions, Reflect] attribute DOMString name;
[ImplementedAs=AssignedNodesForBinding] sequence<Node> assignedNodes(optional AssignedNodesOptions options = {});
[ImplementedAs=AssignedElementsForBinding] sequence<Element> assignedElements(optional AssignedNodesOptions options = {});
diff --git a/chromium/third_party/blink/renderer/core/html/html_table_element.cc b/chromium/third_party/blink/renderer/core/html/html_table_element.cc
index 21a123b5a2a..b7693232ba2 100644
--- a/chromium/third_party/blink/renderer/core/html/html_table_element.cc
+++ b/chromium/third_party/blink/renderer/core/html/html_table_element.cc
@@ -331,7 +331,7 @@ void HTMLTableElement::CollectStyleForPresentationAttribute(
AtomicString(url), GetDocument().CompleteURL(url),
Referrer(GetDocument().OutgoingReferrer(),
GetDocument().GetReferrerPolicy()),
- OriginClean::kTrue);
+ OriginClean::kTrue, false /* is_ad_related */);
style->SetProperty(
CSSPropertyValue(GetCSSPropertyBackgroundImage(), *image_value));
}
diff --git a/chromium/third_party/blink/renderer/core/html/html_table_part_element.cc b/chromium/third_party/blink/renderer/core/html/html_table_part_element.cc
index 1d41ff2b6d4..5d04bf78b73 100644
--- a/chromium/third_party/blink/renderer/core/html/html_table_part_element.cc
+++ b/chromium/third_party/blink/renderer/core/html/html_table_part_element.cc
@@ -64,7 +64,7 @@ void HTMLTablePartElement::CollectStyleForPresentationAttribute(
AtomicString(url), GetDocument().CompleteURL(url),
Referrer(GetDocument().OutgoingReferrer(),
GetDocument().GetReferrerPolicy()),
- OriginClean::kTrue);
+ OriginClean::kTrue, false /* is_ad_related */);
style->SetProperty(
CSSPropertyValue(GetCSSPropertyBackgroundImage(), *image_value));
}
diff --git a/chromium/third_party/blink/renderer/core/html/html_template_element.cc b/chromium/third_party/blink/renderer/core/html/html_template_element.cc
index 56bb1f3057e..25d817119e2 100644
--- a/chromium/third_party/blink/renderer/core/html/html_template_element.cc
+++ b/chromium/third_party/blink/renderer/core/html/html_template_element.cc
@@ -45,7 +45,7 @@ HTMLTemplateElement::HTMLTemplateElement(Document& document)
HTMLTemplateElement::~HTMLTemplateElement() = default;
-DocumentFragment* HTMLTemplateElement::content() const {
+DocumentFragment* HTMLTemplateElement::ContentInternal() const {
if (!content_)
content_ = MakeGarbageCollected<TemplateContentDocumentFragment>(
GetDocument().EnsureTemplateDocument(),
@@ -54,16 +54,24 @@ DocumentFragment* HTMLTemplateElement::content() const {
return content_.Get();
}
+DocumentFragment* HTMLTemplateElement::content() const {
+ return IsDeclarativeShadowRoot() ? nullptr : ContentInternal();
+}
+
+DocumentFragment* HTMLTemplateElement::DeclarativeShadowContent() const {
+ return IsDeclarativeShadowRoot() ? ContentInternal() : nullptr;
+}
+
// https://html.spec.whatwg.org/C/#the-template-element:concept-node-clone-ext
void HTMLTemplateElement::CloneNonAttributePropertiesFrom(
const Element& source,
CloneChildrenFlag flag) {
if (flag == CloneChildrenFlag::kSkip)
return;
-
+ DCHECK_NE(flag, CloneChildrenFlag::kCloneWithShadows);
auto& html_template_element = To<HTMLTemplateElement>(source);
- if (html_template_element.content_)
- content()->CloneChildNodesFrom(*html_template_element.content());
+ if (html_template_element.content())
+ content()->CloneChildNodesFrom(*html_template_element.content(), flag);
}
void HTMLTemplateElement::DidMoveToNewDocument(Document& old_document) {
diff --git a/chromium/third_party/blink/renderer/core/html/html_template_element.h b/chromium/third_party/blink/renderer/core/html/html_template_element.h
index 81a3206d280..6cfc5b166af 100644
--- a/chromium/third_party/blink/renderer/core/html/html_template_element.h
+++ b/chromium/third_party/blink/renderer/core/html/html_template_element.h
@@ -38,6 +38,12 @@ namespace blink {
class DocumentFragment;
class TemplateContentDocumentFragment;
+enum class DeclarativeShadowRootType {
+ kNone,
+ kOpen,
+ kClosed,
+};
+
class CORE_EXPORT HTMLTemplateElement final : public HTMLElement {
DEFINE_WRAPPERTYPEINFO();
@@ -51,12 +57,32 @@ class CORE_EXPORT HTMLTemplateElement final : public HTMLElement {
DocumentFragment* content() const;
+ // This gives direct access to ContentInternal, and should *only*
+ // be used by HTMLConstructionSite.
+ DocumentFragment* TemplateContentForHTMLConstructionSite() const {
+ return ContentInternal();
+ }
+
+ DocumentFragment* DeclarativeShadowContent() const;
+ void SetDeclarativeShadowRootType(DeclarativeShadowRootType val) {
+ declarative_shadow_root_type_ = val;
+ }
+ DeclarativeShadowRootType GetDeclarativeShadowRootType() const {
+ return declarative_shadow_root_type_;
+ }
+ bool IsDeclarativeShadowRoot() const {
+ return declarative_shadow_root_type_ != DeclarativeShadowRootType::kNone;
+ }
+
private:
void CloneNonAttributePropertiesFrom(const Element&,
CloneChildrenFlag) override;
void DidMoveToNewDocument(Document& old_document) override;
+ DocumentFragment* ContentInternal() const;
+
mutable Member<TemplateContentDocumentFragment> content_;
+ DeclarativeShadowRootType declarative_shadow_root_type_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/html_template_element.idl b/chromium/third_party/blink/renderer/core/html/html_template_element.idl
index ebfd32c39ac..bf5200b02d2 100644
--- a/chromium/third_party/blink/renderer/core/html/html_template_element.idl
+++ b/chromium/third_party/blink/renderer/core/html/html_template_element.idl
@@ -34,4 +34,14 @@
HTMLConstructor
] interface HTMLTemplateElement : HTMLElement {
readonly attribute DocumentFragment content;
+
+ // This 'shadowRoot' attribute shadows Element.prototype.shadowRoot
+ // without changing any behavior. The existence of this attribute
+ // indicates support of Declarative Shadow DOM, so that this works:
+ // function supportsDeclarativeShadowDOM() {
+ // return HTMLTemplateElement.prototype.hasOwnProperty("shadowRoot");
+ // }
+ // See https://github.com/mfreed7/declarative-shadow-dom/blob/master/README.md#feature-detection-and-polyfilling
+ // for more detail.
+ [RuntimeEnabled=DeclarativeShadowDOM, Affects=Nothing, ImplementedAs=OpenShadowRoot] readonly attribute ShadowRoot? shadowRoot;
};
diff --git a/chromium/third_party/blink/renderer/core/html/image_document_test.cc b/chromium/third_party/blink/renderer/core/html/image_document_test.cc
index 5b4d48d44cb..1e7cc5c37bc 100644
--- a/chromium/third_party/blink/renderer/core/html/image_document_test.cc
+++ b/chromium/third_party/blink/renderer/core/html/image_document_test.cc
@@ -115,7 +115,7 @@ void ImageDocumentTest::CreateDocumentWithoutLoadingImage(int view_width,
DocumentInit::Create()
.WithDocumentLoader(frame.Loader().GetDocumentLoader())
.WithTypeFrom("image/jpeg");
- frame.DomWindow()->InstallNewDocument(init, false);
+ frame.DomWindow()->InstallNewDocument(init);
frame.GetDocument()->SetURL(KURL("http://www.example.com/image.jpg"));
}
diff --git a/chromium/third_party/blink/renderer/core/html/imports/html_import_loader.cc b/chromium/third_party/blink/renderer/core/html/imports/html_import_loader.cc
index 063eff44f11..a921505e787 100644
--- a/chromium/third_party/blink/renderer/core/html/imports/html_import_loader.cc
+++ b/chromium/third_party/blink/renderer/core/html/imports/html_import_loader.cc
@@ -96,8 +96,13 @@ HTMLImportLoader::State HTMLImportLoader::StartWritingAndParsing(
const ResourceResponse& response) {
DCHECK(controller_);
DCHECK(!imports_.IsEmpty());
+ Document* master = controller_->Master();
document_ = MakeGarbageCollected<HTMLDocument>(
- DocumentInit::CreateWithImportsController(controller_)
+ DocumentInit::Create()
+ .WithImportsController(controller_)
+ .WithContextDocument(master->ContextDocument())
+ .WithRegistrationContext(master->RegistrationContext())
+ .WithContentSecurityPolicy(master->GetContentSecurityPolicy())
.WithURL(response.CurrentRequestUrl()));
document_->OpenForNavigation(kAllowAsynchronousParsing, response.MimeType(),
"UTF-8");
diff --git a/chromium/third_party/blink/renderer/core/html/imports/html_imports_controller.cc b/chromium/third_party/blink/renderer/core/html/imports/html_imports_controller.cc
index 89f0c961e2a..4e9573b0311 100644
--- a/chromium/third_party/blink/renderer/core/html/imports/html_imports_controller.cc
+++ b/chromium/third_party/blink/renderer/core/html/imports/html_imports_controller.cc
@@ -121,12 +121,9 @@ HTMLImportChild* HTMLImportsController::Load(const Document& parent_document,
ResourceFetcher* fetcher = parent->GetDocument()->Fetcher();
if (parent->GetDocument()->ImportsController()) {
- Document* context_document = parent->GetDocument()->ContextDocument();
- if (!context_document)
- return nullptr;
-
- security_origin = context_document->GetSecurityOrigin();
- fetcher = context_document->Fetcher();
+ ExecutionContext* context = parent->GetDocument()->GetExecutionContext();
+ security_origin = context->GetSecurityOrigin();
+ fetcher = context->Fetcher();
}
params.SetCrossOriginAccessControl(security_origin.get(),
diff --git a/chromium/third_party/blink/renderer/core/html/lazy_load_image_observer.cc b/chromium/third_party/blink/renderer/core/html/lazy_load_image_observer.cc
index 32c4a33e9d4..67c244fa972 100644
--- a/chromium/third_party/blink/renderer/core/html/lazy_load_image_observer.cc
+++ b/chromium/third_party/blink/renderer/core/html/lazy_load_image_observer.cc
@@ -195,15 +195,7 @@ void LazyLoadImageObserver::StartMonitoringNearViewport(
"Images loaded lazily and replaced with placeholders. Load events are "
"deferred. See https://crbug.com/954323"));
}
- if (deferral_message == DeferralMessage::kMissingDimensionForLazy &&
- !is_missing_dimension_intervention_shown_) {
- is_missing_dimension_intervention_shown_ = true;
- root_document->AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>(
- mojom::ConsoleMessageSource::kIntervention,
- mojom::ConsoleMessageLevel::kInfo,
- "An <img> element was lazyloaded with loading=lazy, but had no "
- "dimensions specified. Specifying dimensions improves performance. See "
- "https://crbug.com/954323"));
+ if (deferral_message == DeferralMessage::kMissingDimensionForLazy) {
UseCounter::Count(root_document,
WebFeature::kLazyLoadImageMissingDimensionsForLazy);
}
diff --git a/chromium/third_party/blink/renderer/core/html/lazy_load_image_observer.h b/chromium/third_party/blink/renderer/core/html/lazy_load_image_observer.h
index 36941719432..5b89cd988cd 100644
--- a/chromium/third_party/blink/renderer/core/html/lazy_load_image_observer.h
+++ b/chromium/third_party/blink/renderer/core/html/lazy_load_image_observer.h
@@ -69,7 +69,6 @@ class LazyLoadImageObserver final
// Used to show the intervention console message one time only.
bool is_load_event_deferred_intervention_shown_ = false;
- bool is_missing_dimension_intervention_shown_ = false;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/lazy_load_image_observer_test.cc b/chromium/third_party/blink/renderer/core/html/lazy_load_image_observer_test.cc
index 55a3944ebcb..0b79738682d 100644
--- a/chromium/third_party/blink/renderer/core/html/lazy_load_image_observer_test.cc
+++ b/chromium/third_party/blink/renderer/core/html/lazy_load_image_observer_test.cc
@@ -40,11 +40,6 @@ const char* kLazyLoadEventsDeferredMessage =
"Images loaded lazily and replaced with placeholders. Load events are "
"deferred. See https://crbug.com/954323";
-const char* kLazyLoadMissingDimensionMessage =
- "An <img> element was lazyloaded with loading=lazy, but had no dimensions "
- "specified. Specifying dimensions improves performance. See "
- "https://crbug.com/954323";
-
Vector<char> ReadTestImage() {
return test::ReadFromFile(test::CoreTestDataPath("notifications/500x500.png"))
->CopyAs<Vector<char>>();
@@ -55,8 +50,7 @@ class LazyLoadImagesSimTest : public ::testing::WithParamInterface<bool>,
protected:
LazyLoadImagesSimTest()
: scoped_lazy_image_loading_for_test_(GetParam()),
- scoped_automatic_lazy_image_loading_for_test_(GetParam()),
- scoped_lazy_image_loading_metadata_fetch_for_test_(GetParam()) {}
+ scoped_automatic_lazy_image_loading_for_test_(GetParam()) {}
void SetLazyLoadEnabled(bool enabled) {
WebView().GetPage()->GetSettings().SetLazyLoadEnabled(enabled);
@@ -96,7 +90,6 @@ class LazyLoadImagesSimTest : public ::testing::WithParamInterface<bool>,
}
EXPECT_TRUE(is_background_image_found);
EXPECT_FALSE(ConsoleMessages().Contains(kLazyLoadEventsDeferredMessage));
- EXPECT_FALSE(ConsoleMessages().Contains(kLazyLoadMissingDimensionMessage));
EXPECT_FALSE(GetDocument().IsUseCounted(
WebFeature::kLazyLoadImageMissingDimensionsForLazy));
EXPECT_FALSE(GetDocument().IsUseCounted(
@@ -149,7 +142,6 @@ class LazyLoadImagesSimTest : public ::testing::WithParamInterface<bool>,
}
}
EXPECT_FALSE(ConsoleMessages().Contains(kLazyLoadEventsDeferredMessage));
- EXPECT_FALSE(ConsoleMessages().Contains(kLazyLoadMissingDimensionMessage));
EXPECT_FALSE(GetDocument().IsUseCounted(
WebFeature::kLazyLoadImageMissingDimensionsForLazy));
EXPECT_FALSE(GetDocument().IsUseCounted(
@@ -192,7 +184,6 @@ class LazyLoadImagesSimTest : public ::testing::WithParamInterface<bool>,
}
EXPECT_EQ(is_lazyload_image_enabled,
ConsoleMessages().Contains(kLazyLoadEventsDeferredMessage));
- EXPECT_FALSE(ConsoleMessages().Contains(kLazyLoadMissingDimensionMessage));
EXPECT_FALSE(GetDocument().IsUseCounted(
WebFeature::kLazyLoadImageMissingDimensionsForLazy));
EXPECT_FALSE(GetDocument().IsUseCounted(
@@ -205,8 +196,6 @@ class LazyLoadImagesSimTest : public ::testing::WithParamInterface<bool>,
ScopedLazyImageLoadingForTest scoped_lazy_image_loading_for_test_;
ScopedAutomaticLazyImageLoadingForTest
scoped_automatic_lazy_image_loading_for_test_;
- ScopedLazyImageLoadingMetadataFetchForTest
- scoped_lazy_image_loading_metadata_fetch_for_test_ = true;
ScopedRestrictAutomaticLazyImageLoadingToDataSaverForTest
scoped_restrict_automatic_lazy_image_loading_to_data_saver_for_test_ =
false;
@@ -321,35 +310,48 @@ TEST_P(LazyLoadImagesSimTest, LargeImageStyleHeight1Width100) {
VerifyImageElementWithDimensionDeferred("style='height: 1px; width: 100px;'");
}
-INSTANTIATE_TEST_SUITE_P(All,
- LazyLoadImagesSimTest,
- ::testing::Bool() /*is_lazyload_image_enabled*/);
+TEST_P(LazyLoadImagesSimTest, ImgSrcset) {
+ if (!GetParam()) // Only test when LazyImage is enabled.
+ return;
+ SetLazyLoadEnabled(true);
+ WebView().Resize(WebSize(100, 1));
+ LoadMainResource(R"HTML(
+ <body onload='console.log("main body onload");'>
+ <div style='height:10000px;'></div>
+ <img src="img.png" srcset="img.png?100w 100w, img.png?200w 200w"
+ loading="lazy" onload= 'console.log("deferred_image onload");'>
+ </body>)HTML");
-SimRequestBase::Params BuildRequestParamsForRangeResponse() {
- SimRequestBase::Params params;
- params.response_http_headers = {{"content-range", "bytes 0-2047/9311"}};
- params.response_http_status = 206;
- return params;
-}
+ Compositor().BeginFrame();
+ test::RunPendingTasks();
-void ExpectResourceIsFullImage(Resource* resource) {
- EXPECT_TRUE(resource);
- EXPECT_TRUE(resource->IsLoaded());
- EXPECT_FALSE(
- resource->GetResourceRequest().HttpHeaderFields().Contains("range"));
- EXPECT_EQ(ResourceType::kImage, resource->GetType());
- EXPECT_FALSE(ToImageResource(resource)->ShouldShowLazyImagePlaceholder());
-}
+ EXPECT_TRUE(ConsoleMessages().Contains("main body onload"));
+ EXPECT_FALSE(ConsoleMessages().Contains("deferred_image onload"));
-void ExpectResourceIsLazyImagePlaceholder(Resource* resource) {
- EXPECT_TRUE(resource);
- EXPECT_TRUE(resource->IsLoaded());
- EXPECT_EQ("bytes=0-2047",
- resource->GetResourceRequest().HttpHeaderField("range"));
- EXPECT_EQ(ResourceType::kImage, resource->GetType());
- EXPECT_TRUE(ToImageResource(resource)->ShouldShowLazyImagePlaceholder());
+ // Resizing should not load the image.
+ WebView().MainFrameWidget()->Resize(WebSize(200, 1));
+ Compositor().BeginFrame();
+ test::RunPendingTasks();
+ EXPECT_FALSE(ConsoleMessages().Contains("deferred_image onload"));
+
+ // Scrolling down should load the larger image.
+ GetDocument().View()->LayoutViewport()->SetScrollOffset(
+ ScrollOffset(0, 10000), mojom::blink::ScrollType::kProgrammatic);
+ SimRequest image_resource("https://example.com/img.png?200w", "image/png");
+ Compositor().BeginFrame();
+ test::RunPendingTasks();
+ image_resource.Complete(ReadTestImage());
+ test::RunPendingTasks();
+ EXPECT_TRUE(ConsoleMessages().Contains("deferred_image onload"));
+
+ EXPECT_TRUE(GetDocument().IsUseCounted(
+ WebFeature::kLazyLoadImageLoadingAttributeLazy));
}
+INSTANTIATE_TEST_SUITE_P(All,
+ LazyLoadImagesSimTest,
+ ::testing::Bool() /*is_lazyload_image_enabled*/);
+
class ScopedDataSaverSetting {
public:
explicit ScopedDataSaverSetting(bool is_data_saver_enabled)
@@ -373,9 +375,7 @@ enum class LazyImageLoadingFeatureStatus {
// LazyImageLoading is enabled, but AutomaticLazyImageLoading is disabled.
kEnabledExplicit,
// Both LazyImageLoading and AutomaticLazyImageLoading are enabled.
- kEnabledExplicitMetadataFetchDisabled, // Metadata fetch feature disabled.
kEnabledAutomatic,
- kEnabledAutomaticMetadataFetchDisabled, // Metadata fetch feature disabled.
// LazyImageLoading, AutomaticLazyImageLoading, and
// RestrictAutomaticLazyImageLoadingToDataSaver are enabled, while data saver
// is off.
@@ -410,16 +410,7 @@ class LazyLoadImagesParamsTest : public SimTest,
scoped_data_saver_setting_(
lazy_image_loading_feature_status_ ==
LazyImageLoadingFeatureStatus::
- kEnabledAutomaticRestrictedAndDataSaverOn),
- scoped_lazy_image_loading_metadata_fetch_for_test_(
- lazy_image_loading_feature_status_ !=
- LazyImageLoadingFeatureStatus::kDisabled &&
- lazy_image_loading_feature_status_ !=
- LazyImageLoadingFeatureStatus::
- kEnabledExplicitMetadataFetchDisabled &&
- lazy_image_loading_feature_status_ !=
- LazyImageLoadingFeatureStatus::
- kEnabledAutomaticMetadataFetchDisabled) {}
+ kEnabledAutomaticRestrictedAndDataSaverOn) {}
void SetUp() override {
GetNetworkStateNotifier().SetNetworkConnectionInfoOverride(
@@ -463,28 +454,15 @@ class LazyLoadImagesParamsTest : public SimTest,
case LazyImageLoadingFeatureStatus::kEnabledExplicit:
case LazyImageLoadingFeatureStatus::
kEnabledAutomaticRestrictedAndDataSaverOff:
- case LazyImageLoadingFeatureStatus::kEnabledExplicitMetadataFetchDisabled:
return false;
case LazyImageLoadingFeatureStatus::kEnabledAutomatic:
case LazyImageLoadingFeatureStatus::
kEnabledAutomaticRestrictedAndDataSaverOn:
- case LazyImageLoadingFeatureStatus::
- kEnabledAutomaticMetadataFetchDisabled:
return true;
}
NOTREACHED();
return false;
}
- bool IsMetadataFetchExpected() {
- switch (lazy_image_loading_feature_status_) {
- case LazyImageLoadingFeatureStatus::kEnabledExplicitMetadataFetchDisabled:
- case LazyImageLoadingFeatureStatus::
- kEnabledAutomaticMetadataFetchDisabled:
- return false;
- default:
- return true;
- }
- }
private:
LazyImageLoadingFeatureStatus lazy_image_loading_feature_status_;
@@ -494,8 +472,6 @@ class LazyLoadImagesParamsTest : public SimTest,
ScopedRestrictAutomaticLazyImageLoadingToDataSaverForTest
scoped_restrict_automatic_lazy_image_loading_to_data_saver_for_test_;
ScopedDataSaverSetting scoped_data_saver_setting_;
- ScopedLazyImageLoadingMetadataFetchForTest
- scoped_lazy_image_loading_metadata_fetch_for_test_;
};
TEST_P(LazyLoadImagesParamsTest, NearViewport) {
@@ -507,22 +483,9 @@ TEST_P(LazyLoadImagesParamsTest, NearViewport) {
"image/png");
base::Optional<SimSubresourceRequest> lazy_resource, auto_resource,
unset_resource;
- if (RuntimeEnabledFeatures::LazyImageLoadingEnabled() &&
- IsMetadataFetchExpected()) {
- lazy_resource.emplace("https://example.com/lazy.png", "image/png",
- BuildRequestParamsForRangeResponse());
- } else {
lazy_resource.emplace("https://example.com/lazy.png", "image/png");
- }
- if (IsAutomaticLazyImageLoadingExpected() && IsMetadataFetchExpected()) {
- auto_resource.emplace("https://example.com/auto.png", "image/png",
- BuildRequestParamsForRangeResponse());
- unset_resource.emplace("https://example.com/unset.png", "image/png",
- BuildRequestParamsForRangeResponse());
- } else {
auto_resource.emplace("https://example.com/auto.png", "image/png");
unset_resource.emplace("https://example.com/unset.png", "image/png");
- }
LoadURL("https://example.com/");
main_resource.Complete(String::Format(
@@ -551,29 +514,6 @@ TEST_P(LazyLoadImagesParamsTest, NearViewport) {
Vector<char> partial_image;
partial_image.Append(full_image.data(), 2048U);
- if (RuntimeEnabledFeatures::LazyImageLoadingEnabled() &&
- IsMetadataFetchExpected()) {
- lazy_resource->Complete(partial_image);
- ExpectResourceIsLazyImagePlaceholder(
- GetDocument().Fetcher()->CachedResource(
- KURL("https://example.com/lazy.png")));
- lazy_resource.emplace("https://example.com/lazy.png", "image/png");
- }
-
- if (IsAutomaticLazyImageLoadingExpected() && IsMetadataFetchExpected()) {
- auto_resource->Complete(partial_image);
- ExpectResourceIsLazyImagePlaceholder(
- GetDocument().Fetcher()->CachedResource(
- KURL("https://example.com/auto.png")));
- auto_resource.emplace("https://example.com/auto.png", "image/png");
-
- unset_resource->Complete(partial_image);
- ExpectResourceIsLazyImagePlaceholder(
- GetDocument().Fetcher()->CachedResource(
- KURL("https://example.com/unset.png")));
- unset_resource.emplace("https://example.com/unset.png", "image/png");
- }
-
Compositor().BeginFrame();
test::RunPendingTasks();
@@ -584,8 +524,6 @@ TEST_P(LazyLoadImagesParamsTest, NearViewport) {
EXPECT_FALSE(ConsoleMessages().Contains("unset onload"));
eager_resource.Complete(full_image);
- ExpectResourceIsFullImage(GetDocument().Fetcher()->CachedResource(
- KURL("https://example.com/eager.png")));
Compositor().BeginFrame();
test::RunPendingTasks();
@@ -593,20 +531,33 @@ TEST_P(LazyLoadImagesParamsTest, NearViewport) {
EXPECT_FALSE(ConsoleMessages().Contains("main body onload"));
EXPECT_TRUE(ConsoleMessages().Contains("eager onload"));
EXPECT_FALSE(ConsoleMessages().Contains("lazy onload"));
+ // When automatic lazy image loading is enabled, images that are not
+ // explicitly `loading=lazy` will still block the window load event.
+ // Therefore, the following two images are either:
+ // a.) Fetched eagerly, when automatic lazy image loading is disabled
+ // - And therefore block the window load event
+ // b.) Fetched lazily, when automatic lazy image loading is enabled
+ // - And still block the window load event, if fetched before it fires.
EXPECT_FALSE(ConsoleMessages().Contains("auto onload"));
EXPECT_FALSE(ConsoleMessages().Contains("unset onload"));
- lazy_resource->Complete(full_image);
- ExpectResourceIsFullImage(GetDocument().Fetcher()->CachedResource(
- KURL("https://example.com/lazy.png")));
-
auto_resource->Complete(full_image);
- ExpectResourceIsFullImage(GetDocument().Fetcher()->CachedResource(
- KURL("https://example.com/auto.png")));
-
unset_resource->Complete(full_image);
- ExpectResourceIsFullImage(GetDocument().Fetcher()->CachedResource(
- KURL("https://example.com/unset.png")));
+
+ Compositor().BeginFrame();
+ test::RunPendingTasks();
+
+ // The explicitly `loading=lazy` image never blocks the window load event.
+ if (RuntimeEnabledFeatures::LazyImageLoadingEnabled())
+ EXPECT_TRUE(ConsoleMessages().Contains("main body onload"));
+ else
+ EXPECT_FALSE(ConsoleMessages().Contains("main body onload"));
+ EXPECT_TRUE(ConsoleMessages().Contains("eager onload"));
+ EXPECT_FALSE(ConsoleMessages().Contains("lazy onload"));
+ EXPECT_TRUE(ConsoleMessages().Contains("auto onload"));
+ EXPECT_TRUE(ConsoleMessages().Contains("unset onload"));
+
+ lazy_resource->Complete(full_image);
Compositor().BeginFrame();
test::RunPendingTasks();
@@ -622,7 +573,6 @@ TEST_P(LazyLoadImagesParamsTest, NearViewport) {
case LazyImageLoadingFeatureStatus::
kEnabledAutomaticRestrictedAndDataSaverOn:
EXPECT_TRUE(ConsoleMessages().Contains(kLazyLoadEventsDeferredMessage));
- EXPECT_TRUE(ConsoleMessages().Contains(kLazyLoadMissingDimensionMessage));
EXPECT_TRUE(GetDocument().IsUseCounted(
WebFeature::kLazyLoadImageMissingDimensionsForLazy));
break;
@@ -640,22 +590,9 @@ TEST_P(LazyLoadImagesParamsTest, FarFromViewport) {
"image/png");
base::Optional<SimSubresourceRequest> lazy_resource, auto_resource,
unset_resource;
- if (RuntimeEnabledFeatures::LazyImageLoadingEnabled() &&
- IsMetadataFetchExpected()) {
- lazy_resource.emplace("https://example.com/lazy.png", "image/png",
- BuildRequestParamsForRangeResponse());
- } else {
lazy_resource.emplace("https://example.com/lazy.png", "image/png");
- }
- if (IsAutomaticLazyImageLoadingExpected() && IsMetadataFetchExpected()) {
- auto_resource.emplace("https://example.com/auto.png", "image/png",
- BuildRequestParamsForRangeResponse());
- unset_resource.emplace("https://example.com/unset.png", "image/png",
- BuildRequestParamsForRangeResponse());
- } else {
auto_resource.emplace("https://example.com/auto.png", "image/png");
unset_resource.emplace("https://example.com/unset.png", "image/png");
- }
LoadURL("https://example.com/");
@@ -695,14 +632,17 @@ TEST_P(LazyLoadImagesParamsTest, FarFromViewport) {
partial_image.Append(full_image.data(), 2048U);
eager_resource.Complete(full_image);
- ExpectResourceIsFullImage(GetDocument().Fetcher()->CachedResource(
- KURL("https://example.com/eager.png")));
Compositor().BeginFrame();
test::RunPendingTasks();
- if (std::get<LazyImageLoadingFeatureStatus>(GetParam()) !=
- LazyImageLoadingFeatureStatus::kEnabledAutomaticMetadataFetchDisabled) {
+ LazyImageLoadingFeatureStatus lazy_image_loading_feature_status =
+ std::get<LazyImageLoadingFeatureStatus>(GetParam());
+ if (lazy_image_loading_feature_status !=
+ LazyImageLoadingFeatureStatus::kEnabledAutomatic &&
+ lazy_image_loading_feature_status !=
+ LazyImageLoadingFeatureStatus::
+ kEnabledAutomaticRestrictedAndDataSaverOn) {
EXPECT_FALSE(ConsoleMessages().Contains("main body onload"));
}
EXPECT_TRUE(ConsoleMessages().Contains("eager onload"));
@@ -710,46 +650,20 @@ TEST_P(LazyLoadImagesParamsTest, FarFromViewport) {
EXPECT_FALSE(ConsoleMessages().Contains("auto onload"));
EXPECT_FALSE(ConsoleMessages().Contains("unset onload"));
- if (RuntimeEnabledFeatures::LazyImageLoadingEnabled()) {
- if (IsMetadataFetchExpected()) {
- lazy_resource->Complete(partial_image);
- ExpectResourceIsLazyImagePlaceholder(
- GetDocument().Fetcher()->CachedResource(
- KURL("https://example.com/lazy.png")));
- lazy_resource.emplace("https://example.com/lazy.png", "image/png");
- }
- } else {
+ if (!RuntimeEnabledFeatures::LazyImageLoadingEnabled()) {
lazy_resource->Complete(full_image);
- ExpectResourceIsFullImage(GetDocument().Fetcher()->CachedResource(
- KURL("https://example.com/lazy.png")));
}
- if (IsAutomaticLazyImageLoadingExpected()) {
- if (IsMetadataFetchExpected()) {
- auto_resource->Complete(partial_image);
- ExpectResourceIsLazyImagePlaceholder(
- GetDocument().Fetcher()->CachedResource(
- KURL("https://example.com/auto.png")));
-
- unset_resource->Complete(partial_image);
- ExpectResourceIsLazyImagePlaceholder(
- GetDocument().Fetcher()->CachedResource(
- KURL("https://example.com/unset.png")));
- auto_resource.emplace("https://example.com/auto.png", "image/png");
- unset_resource.emplace("https://example.com/unset.png", "image/png");
- }
- } else {
+ if (!IsAutomaticLazyImageLoadingExpected()) {
auto_resource->Complete(full_image);
- ExpectResourceIsFullImage(GetDocument().Fetcher()->CachedResource(
- KURL("https://example.com/auto.png")));
-
unset_resource->Complete(full_image);
- ExpectResourceIsFullImage(GetDocument().Fetcher()->CachedResource(
- KURL("https://example.com/unset.png")));
}
- if (std::get<LazyImageLoadingFeatureStatus>(GetParam()) !=
- LazyImageLoadingFeatureStatus::kEnabledAutomaticMetadataFetchDisabled) {
+ if (lazy_image_loading_feature_status !=
+ LazyImageLoadingFeatureStatus::kEnabledAutomatic &&
+ lazy_image_loading_feature_status !=
+ LazyImageLoadingFeatureStatus::
+ kEnabledAutomaticRestrictedAndDataSaverOn) {
Compositor().BeginFrame();
test::RunPendingTasks();
}
@@ -767,20 +681,13 @@ TEST_P(LazyLoadImagesParamsTest, FarFromViewport) {
EXPECT_FALSE(ConsoleMessages().Contains("lazy onload"));
lazy_resource->Complete(full_image);
- ExpectResourceIsFullImage(GetDocument().Fetcher()->CachedResource(
- KURL("https://example.com/lazy.png")));
if (IsAutomaticLazyImageLoadingExpected()) {
EXPECT_FALSE(ConsoleMessages().Contains("auto onload"));
EXPECT_FALSE(ConsoleMessages().Contains("unset onload"));
auto_resource->Complete(full_image);
- ExpectResourceIsFullImage(GetDocument().Fetcher()->CachedResource(
- KURL("https://example.com/auto.png")));
-
unset_resource->Complete(full_image);
- ExpectResourceIsFullImage(GetDocument().Fetcher()->CachedResource(
- KURL("https://example.com/unset.png")));
}
Compositor().BeginFrame();
@@ -798,7 +705,6 @@ TEST_P(LazyLoadImagesParamsTest, FarFromViewport) {
case LazyImageLoadingFeatureStatus::
kEnabledAutomaticRestrictedAndDataSaverOn:
EXPECT_TRUE(ConsoleMessages().Contains(kLazyLoadEventsDeferredMessage));
- EXPECT_TRUE(ConsoleMessages().Contains(kLazyLoadMissingDimensionMessage));
EXPECT_TRUE(GetDocument().IsUseCounted(
WebFeature::kLazyLoadImageMissingDimensionsForLazy));
break;
@@ -817,11 +723,7 @@ INSTANTIATE_TEST_SUITE_P(
LazyImageLoadingFeatureStatus::
kEnabledAutomaticRestrictedAndDataSaverOff,
LazyImageLoadingFeatureStatus::
- kEnabledAutomaticRestrictedAndDataSaverOn,
- LazyImageLoadingFeatureStatus::
- kEnabledExplicitMetadataFetchDisabled,
- LazyImageLoadingFeatureStatus::
- kEnabledAutomaticMetadataFetchDisabled),
+ kEnabledAutomaticRestrictedAndDataSaverOn),
::testing::Values(WebEffectiveConnectionType::kTypeUnknown,
WebEffectiveConnectionType::kTypeOffline,
WebEffectiveConnectionType::kTypeSlow2G,
@@ -883,27 +785,7 @@ class LazyLoadAutomaticImagesTest : public SimTest {
}
void TestLoadImageExpectingLazyLoad(const char* image_attributes) {
- SimSubresourceRequest image_range_resource(
- "https://example.com/image.png", "image/png",
- BuildRequestParamsForRangeResponse());
-
LoadMainResourceWithImageFarFromViewport(image_attributes);
-
- EXPECT_FALSE(ConsoleMessages().Contains("main body onload"));
- EXPECT_FALSE(ConsoleMessages().Contains("image onload"));
-
- Vector<char> partial_image = ReadTestImage();
- EXPECT_LT(2048U, partial_image.size());
- partial_image.resize(2048U);
-
- image_range_resource.Complete(partial_image);
- ExpectResourceIsLazyImagePlaceholder(
- GetDocument().Fetcher()->CachedResource(
- KURL("https://example.com/image.png")));
-
- Compositor().BeginFrame();
- test::RunPendingTasks();
-
EXPECT_TRUE(ConsoleMessages().Contains("main body onload"));
EXPECT_FALSE(ConsoleMessages().Contains("image onload"));
}
@@ -925,14 +807,11 @@ class LazyLoadAutomaticImagesTest : public SimTest {
Compositor().BeginFrame();
test::RunPendingTasks();
full_resource.Complete(ReadTestImage());
- ExpectResourceIsFullImage(GetDocument().Fetcher()->CachedResource(
- KURL("https://example.com/image.png")));
test::RunPendingTasks();
EXPECT_TRUE(ConsoleMessages().Contains("main body onload"));
EXPECT_TRUE(ConsoleMessages().Contains("image onload"));
EXPECT_TRUE(ConsoleMessages().Contains(kLazyLoadEventsDeferredMessage));
- EXPECT_FALSE(ConsoleMessages().Contains(kLazyLoadMissingDimensionMessage));
EXPECT_FALSE(GetDocument().IsUseCounted(
WebFeature::kLazyLoadImageMissingDimensionsForLazy));
EXPECT_FALSE(GetDocument().IsUseCounted(
@@ -951,8 +830,6 @@ class LazyLoadAutomaticImagesTest : public SimTest {
EXPECT_FALSE(ConsoleMessages().Contains("image onload"));
full_resource.Complete(ReadTestImage());
- ExpectResourceIsFullImage(GetDocument().Fetcher()->CachedResource(
- KURL("https://example.com/image.png")));
Compositor().BeginFrame();
test::RunPendingTasks();
@@ -960,7 +837,6 @@ class LazyLoadAutomaticImagesTest : public SimTest {
EXPECT_TRUE(ConsoleMessages().Contains("main body onload"));
EXPECT_TRUE(ConsoleMessages().Contains("image onload"));
EXPECT_FALSE(ConsoleMessages().Contains(kLazyLoadEventsDeferredMessage));
- EXPECT_FALSE(ConsoleMessages().Contains(kLazyLoadMissingDimensionMessage));
EXPECT_FALSE(GetDocument().IsUseCounted(
WebFeature::kLazyLoadImageMissingDimensionsForLazy));
EXPECT_FALSE(GetDocument().IsUseCounted(
@@ -975,8 +851,6 @@ class LazyLoadAutomaticImagesTest : public SimTest {
scoped_automatic_lazy_image_loading_for_test_;
ScopedRestrictAutomaticLazyImageLoadingToDataSaverForTest
scoped_restrict_automatic_lazy_image_loading_to_data_saver_for_test_;
- ScopedLazyImageLoadingMetadataFetchForTest
- scoped_lazy_image_loading_metadata_fetch_for_test_ = true;
ScopedLazyImageVisibleLoadTimeMetricsForTest
scoped_lazy_image_visible_load_time_metrics_for_test_ = true;
};
@@ -994,8 +868,6 @@ TEST_F(LazyLoadAutomaticImagesTest, AttributeChangedFromLazyToEager) {
test::RunPendingTasks();
full_resource.Complete(ReadTestImage());
- ExpectResourceIsFullImage(GetDocument().Fetcher()->CachedResource(
- KURL("https://example.com/image.png")));
Compositor().BeginFrame();
test::RunPendingTasks();
@@ -1003,7 +875,6 @@ TEST_F(LazyLoadAutomaticImagesTest, AttributeChangedFromLazyToEager) {
EXPECT_TRUE(ConsoleMessages().Contains("main body onload"));
EXPECT_TRUE(ConsoleMessages().Contains("image onload"));
EXPECT_FALSE(ConsoleMessages().Contains(kLazyLoadEventsDeferredMessage));
- EXPECT_TRUE(ConsoleMessages().Contains(kLazyLoadMissingDimensionMessage));
EXPECT_TRUE(GetDocument().IsUseCounted(
WebFeature::kLazyLoadImageMissingDimensionsForLazy));
EXPECT_TRUE(GetDocument().IsUseCounted(
@@ -1025,8 +896,6 @@ TEST_F(LazyLoadAutomaticImagesTest, AttributeChangedFromAutoToEager) {
test::RunPendingTasks();
full_resource.Complete(ReadTestImage());
- ExpectResourceIsFullImage(GetDocument().Fetcher()->CachedResource(
- KURL("https://example.com/image.png")));
Compositor().BeginFrame();
test::RunPendingTasks();
@@ -1034,7 +903,6 @@ TEST_F(LazyLoadAutomaticImagesTest, AttributeChangedFromAutoToEager) {
EXPECT_TRUE(ConsoleMessages().Contains("main body onload"));
EXPECT_TRUE(ConsoleMessages().Contains("image onload"));
EXPECT_TRUE(ConsoleMessages().Contains(kLazyLoadEventsDeferredMessage));
- EXPECT_FALSE(ConsoleMessages().Contains(kLazyLoadMissingDimensionMessage));
EXPECT_FALSE(GetDocument().IsUseCounted(
WebFeature::kLazyLoadImageMissingDimensionsForLazy));
EXPECT_FALSE(GetDocument().IsUseCounted(
@@ -1056,8 +924,6 @@ TEST_F(LazyLoadAutomaticImagesTest, AttributeChangedFromUnsetToEager) {
test::RunPendingTasks();
full_resource.Complete(ReadTestImage());
- ExpectResourceIsFullImage(GetDocument().Fetcher()->CachedResource(
- KURL("https://example.com/image.png")));
Compositor().BeginFrame();
test::RunPendingTasks();
@@ -1065,7 +931,6 @@ TEST_F(LazyLoadAutomaticImagesTest, AttributeChangedFromUnsetToEager) {
EXPECT_TRUE(ConsoleMessages().Contains("main body onload"));
EXPECT_TRUE(ConsoleMessages().Contains("image onload"));
EXPECT_TRUE(ConsoleMessages().Contains(kLazyLoadEventsDeferredMessage));
- EXPECT_FALSE(ConsoleMessages().Contains(kLazyLoadMissingDimensionMessage));
EXPECT_FALSE(GetDocument().IsUseCounted(
WebFeature::kLazyLoadImageMissingDimensionsForLazy));
EXPECT_FALSE(GetDocument().IsUseCounted(
@@ -1119,8 +984,6 @@ TEST_F(LazyLoadAutomaticImagesTest, TinyImageViaStyleWidth11Height1) {
}
TEST_F(LazyLoadAutomaticImagesTest, FirstKImagesLoaded) {
- ScopedLazyImageLoadingMetadataFetchForTest
- scoped_lazy_image_loading_metadata_fetch_for_test = false;
SetLazyImageFirstKFullyLoad(1);
SimRequest main_resource("https://example.com/", "text/html");
@@ -1141,8 +1004,6 @@ TEST_F(LazyLoadAutomaticImagesTest, FirstKImagesLoaded) {
// One image should be loaded fully, even though it is below viewport.
img1.Complete(ReadTestImage());
- ExpectResourceIsFullImage(GetDocument().Fetcher()->CachedResource(
- KURL("https://example.com/image.png?id=1")));
test::RunPendingTasks();
EXPECT_TRUE(ConsoleMessages().Contains("main body onload"));
@@ -1159,8 +1020,6 @@ TEST_F(LazyLoadAutomaticImagesTest, FirstKImagesLoaded) {
test::RunPendingTasks();
img2.Complete(ReadTestImage());
- ExpectResourceIsFullImage(GetDocument().Fetcher()->CachedResource(
- KURL("https://example.com/image.png?id=2")));
test::RunPendingTasks();
EXPECT_TRUE(ConsoleMessages().Contains("main body onload"));
@@ -1196,8 +1055,6 @@ TEST_F(LazyLoadAutomaticImagesTest, JavascriptCreatedImageFarFromViewport) {
EXPECT_FALSE(ConsoleMessages().Contains("my_image onload"));
image_resource.Complete(ReadTestImage());
- ExpectResourceIsFullImage(GetDocument().Fetcher()->CachedResource(
- KURL("https://example.com/image.png")));
Compositor().BeginFrame();
test::RunPendingTasks();
@@ -1235,8 +1092,6 @@ TEST_F(LazyLoadAutomaticImagesTest, JavascriptCreatedImageAddedAfterLoad) {
EXPECT_FALSE(ConsoleMessages().Contains("my_image onload"));
image_resource.Complete(ReadTestImage());
- ExpectResourceIsFullImage(GetDocument().Fetcher()->CachedResource(
- KURL("https://example.com/image.png")));
test::RunPendingTasks();
@@ -1280,9 +1135,6 @@ TEST_F(LazyLoadAutomaticImagesTest, ImageInsideLazyLoadedFrame) {
"text/css");
SimSubresourceRequest eager_resource("https://example.com/eager.png",
"image/png");
- SimSubresourceRequest lazy_range_resource(
- "https://example.com/lazy.png", "image/png",
- BuildRequestParamsForRangeResponse());
SimSubresourceRequest auto_resource("https://example.com/auto.png",
"image/png");
SimSubresourceRequest unset_resource("https://example.com/unset.png",
@@ -1322,26 +1174,9 @@ TEST_F(LazyLoadAutomaticImagesTest, ImageInsideLazyLoadedFrame) {
Vector<char> partial_image;
partial_image.Append(full_image.data(), 2048U);
- Document* child_frame_document =
- To<HTMLIFrameElement>(GetDocument().getElementById("child_frame"))
- ->contentDocument();
-
eager_resource.Complete(full_image);
- ExpectResourceIsFullImage(child_frame_document->Fetcher()->CachedResource(
- KURL("https://example.com/eager.png")));
-
- lazy_range_resource.Complete(partial_image);
- ExpectResourceIsLazyImagePlaceholder(
- child_frame_document->Fetcher()->CachedResource(
- KURL("https://example.com/lazy.png")));
-
auto_resource.Complete(full_image);
- ExpectResourceIsFullImage(child_frame_document->Fetcher()->CachedResource(
- KURL("https://example.com/auto.png")));
-
unset_resource.Complete(full_image);
- ExpectResourceIsFullImage(child_frame_document->Fetcher()->CachedResource(
- KURL("https://example.com/unset.png")));
Compositor().BeginFrame();
test::RunPendingTasks();
@@ -1365,8 +1200,6 @@ TEST_F(LazyLoadAutomaticImagesTest, ImageInsideLazyLoadedFrame) {
test::RunPendingTasks();
lazy_resource.Complete(full_image);
- ExpectResourceIsFullImage(child_frame_document->Fetcher()->CachedResource(
- KURL("https://example.com/lazy.png")));
Compositor().BeginFrame();
test::RunPendingTasks();
@@ -1381,8 +1214,6 @@ TEST_F(LazyLoadAutomaticImagesTest, ImageInsideLazyLoadedFrame) {
}
TEST_F(LazyLoadAutomaticImagesTest, LazyLoadDisabledOnReload) {
- ScopedLazyImageLoadingMetadataFetchForTest
- scoped_lazy_image_loading_metadata_fetch_for_test = false;
String main_resource_html = String::Format(
R"HTML(
<body onload='console.log("main body onload");'>
@@ -1455,8 +1286,6 @@ TEST_F(LazyLoadAutomaticImagesTest, LazyLoadDisabledOnReload) {
}
TEST_F(LazyLoadAutomaticImagesTest, AboveTheFoldImageLoadedBeforeVisible) {
- ScopedLazyImageLoadingMetadataFetchForTest
- scoped_lazy_image_loading_metadata_fetch_for_test = false;
HistogramTester histogram_tester;
// Since the image is above the fold, ensure that the image starts loading
@@ -1495,8 +1324,6 @@ TEST_F(LazyLoadAutomaticImagesTest, AboveTheFoldImageLoadedBeforeVisible) {
}
TEST_F(LazyLoadAutomaticImagesTest, AboveTheFoldImageVisibleBeforeLoaded) {
- ScopedLazyImageLoadingMetadataFetchForTest
- scoped_lazy_image_loading_metadata_fetch_for_test = false;
HistogramTester histogram_tester;
SimRequest main_resource("https://example.com/", "text/html");
@@ -1538,8 +1365,6 @@ TEST_F(LazyLoadAutomaticImagesTest, AboveTheFoldImageVisibleBeforeLoaded) {
}
TEST_F(LazyLoadAutomaticImagesTest, BelowTheFoldImageLoadedBeforeVisible) {
- ScopedLazyImageLoadingMetadataFetchForTest
- scoped_lazy_image_loading_metadata_fetch_for_test = false;
HistogramTester histogram_tester;
SimRequest main_resource("https://example.com/", "text/html");
@@ -1595,8 +1420,6 @@ TEST_F(LazyLoadAutomaticImagesTest, BelowTheFoldImageLoadedBeforeVisible) {
}
TEST_F(LazyLoadAutomaticImagesTest, BelowTheFoldImageVisibleBeforeLoaded) {
- ScopedLazyImageLoadingMetadataFetchForTest
- scoped_lazy_image_loading_metadata_fetch_for_test = false;
HistogramTester histogram_tester;
SimRequest main_resource("https://example.com/", "text/html");
diff --git a/chromium/third_party/blink/renderer/core/html/link_style.cc b/chromium/third_party/blink/renderer/core/html/link_style.cc
index 7e88349611c..ba9e774f8b2 100644
--- a/chromium/third_party/blink/renderer/core/html/link_style.cc
+++ b/chromium/third_party/blink/renderer/core/html/link_style.cc
@@ -89,6 +89,9 @@ void LinkStyle::NotifyFinished(Resource* resource) {
GetDocument(), cached_style_sheet->GetResponse().ResponseUrl(),
cached_style_sheet->GetResponse().IsCorsSameOrigin(),
cached_style_sheet->GetReferrerPolicy(), cached_style_sheet->Encoding());
+ if (cached_style_sheet->GetResourceRequest().IsAdResource()) {
+ parser_context->SetIsAdRelated();
+ }
if (StyleSheetContents* parsed_sheet =
cached_style_sheet->CreateParsedStyleSheetFromCache(parser_context)) {
diff --git a/chromium/third_party/blink/renderer/core/html/loading_attribute.cc b/chromium/third_party/blink/renderer/core/html/loading_attribute.cc
new file mode 100644
index 00000000000..d68b873d10b
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/html/loading_attribute.cc
@@ -0,0 +1,17 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/html/loading_attribute.h"
+
+namespace blink {
+
+LoadingAttributeValue GetLoadingAttributeValue(const String& value) {
+ if (EqualIgnoringASCIICase(value, "lazy"))
+ return LoadingAttributeValue::kLazy;
+ if (EqualIgnoringASCIICase(value, "eager"))
+ return LoadingAttributeValue::kEager;
+ return LoadingAttributeValue::kAuto;
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/loading_attribute.h b/chromium/third_party/blink/renderer/core/html/loading_attribute.h
new file mode 100644
index 00000000000..4f1b2ba1e96
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/html/loading_attribute.h
@@ -0,0 +1,17 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_HTML_LOADING_ATTRIBUTE_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_LOADING_ATTRIBUTE_H_
+
+#include "third_party/blink/renderer/platform/loader/fetch/loading_attribute_value.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+
+namespace blink {
+
+LoadingAttributeValue GetLoadingAttributeValue(const String& value);
+
+} // namespace blink
+
+#endif
diff --git a/chromium/third_party/blink/renderer/core/html/media/autoplay_policy.cc b/chromium/third_party/blink/renderer/core/html/media/autoplay_policy.cc
index 9e03caf66bb..f435e762221 100644
--- a/chromium/third_party/blink/renderer/core/html/media/autoplay_policy.cc
+++ b/chromium/third_party/blink/renderer/core/html/media/autoplay_policy.cc
@@ -379,8 +379,9 @@ void AutoplayPolicy::MaybeSetAutoplayInitiated() {
bool AutoplayPolicy::ShouldAutoplay() {
if (element_->GetDocument().IsSandboxed(
- mojom::blink::WebSandboxFlags::kAutomaticFeatures))
+ network::mojom::blink::WebSandboxFlags::kAutomaticFeatures)) {
return false;
+ }
return element_->can_autoplay_ && element_->paused_ && element_->Autoplay();
}
diff --git a/chromium/third_party/blink/renderer/core/html/media/html_media_element.cc b/chromium/third_party/blink/renderer/core/html/media/html_media_element.cc
index f14430417bc..2cce1250ded 100644
--- a/chromium/third_party/blink/renderer/core/html/media/html_media_element.cc
+++ b/chromium/third_party/blink/renderer/core/html/media/html_media_element.cc
@@ -1826,7 +1826,7 @@ void HTMLMediaElement::SetReadyState(ReadyState state) {
current_src_after_redirects_ == current_src_
? ResourceRequest::RedirectStatus::kNoRedirect
: ResourceRequest::RedirectStatus::kFollowedRedirect,
- current_src_after_redirects_);
+ current_src_after_redirects_, /* devtools_id= */ base::nullopt);
}
// Prior to kHaveMetadata |network_state_| may be inaccurate to avoid side
diff --git a/chromium/third_party/blink/renderer/core/html/media/html_video_element.cc b/chromium/third_party/blink/renderer/core/html/media/html_video_element.cc
index 50740ddcf2a..4805e7e2afd 100644
--- a/chromium/third_party/blink/renderer/core/html/media/html_video_element.cc
+++ b/chromium/third_party/blink/renderer/core/html/media/html_video_element.cc
@@ -645,11 +645,9 @@ IntSize HTMLVideoElement::BitmapSourceSize() const {
ScriptPromise HTMLVideoElement::CreateImageBitmap(
ScriptState* script_state,
- EventTarget& event_target,
base::Optional<IntRect> crop_rect,
const ImageBitmapOptions* options,
ExceptionState& exception_state) {
- DCHECK(event_target.ToLocalDOMWindow());
if (getNetworkState() == HTMLMediaElement::kNetworkEmpty) {
exception_state.ThrowDOMException(
DOMExceptionCode::kInvalidStateError,
@@ -664,10 +662,7 @@ ScriptPromise HTMLVideoElement::CreateImageBitmap(
}
return ImageBitmapSource::FulfillImageBitmap(
- script_state,
- MakeGarbageCollected<ImageBitmap>(
- this, crop_rect, event_target.ToLocalDOMWindow()->document(),
- options),
+ script_state, MakeGarbageCollected<ImageBitmap>(this, crop_rect, options),
exception_state);
}
diff --git a/chromium/third_party/blink/renderer/core/html/media/html_video_element.h b/chromium/third_party/blink/renderer/core/html/media/html_video_element.h
index 5fb512df678..d8ce1f17a1a 100644
--- a/chromium/third_party/blink/renderer/core/html/media/html_video_element.h
+++ b/chromium/third_party/blink/renderer/core/html/media/html_video_element.h
@@ -172,7 +172,6 @@ class CORE_EXPORT HTMLVideoElement final
// ImageBitmapSource implementation
IntSize BitmapSourceSize() const override;
ScriptPromise CreateImageBitmap(ScriptState*,
- EventTarget&,
base::Optional<IntRect> crop_rect,
const ImageBitmapOptions*,
ExceptionState&) override;
diff --git a/chromium/third_party/blink/renderer/core/html/media/media_remoting_interstitial.h b/chromium/third_party/blink/renderer/core/html/media/media_remoting_interstitial.h
index c00cfa0609a..6457522a778 100644
--- a/chromium/third_party/blink/renderer/core/html/media/media_remoting_interstitial.h
+++ b/chromium/third_party/blink/renderer/core/html/media/media_remoting_interstitial.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_HTML_MEDIA_MEDIA_REMOTING_INTERSTITIAL_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_MEDIA_MEDIA_REMOTING_INTERSTITIAL_H_
-#include "third_party/blink/public/strings/grit/blink_strings.h"
#include "third_party/blink/renderer/core/html/html_div_element.h"
#include "third_party/blink/renderer/platform/timer.h"
diff --git a/chromium/third_party/blink/renderer/core/html/media/picture_in_picture_interstitial.cc b/chromium/third_party/blink/renderer/core/html/media/picture_in_picture_interstitial.cc
index 3bee9fcdf35..40baab9412a 100644
--- a/chromium/third_party/blink/renderer/core/html/media/picture_in_picture_interstitial.cc
+++ b/chromium/third_party/blink/renderer/core/html/media/picture_in_picture_interstitial.cc
@@ -60,7 +60,7 @@ PictureInPictureInterstitial::PictureInPictureInterstitial(
HTMLVideoElement& videoElement)
: HTMLDivElement(videoElement.GetDocument()),
resize_observer_(ResizeObserver::Create(
- videoElement.GetDocument(),
+ videoElement.GetDocument().domWindow(),
MakeGarbageCollected<VideoElementResizeObserverDelegate>(this))),
interstitial_timer_(
videoElement.GetDocument().GetTaskRunner(TaskType::kInternalMedia),
@@ -127,7 +127,7 @@ Node::InsertionNotificationRequest PictureInPictureInterstitial::InsertedInto(
ContainerNode& root) {
if (GetVideoElement().isConnected() && !resize_observer_) {
resize_observer_ = ResizeObserver::Create(
- GetVideoElement().GetDocument(),
+ GetVideoElement().GetDocument().domWindow(),
MakeGarbageCollected<VideoElementResizeObserverDelegate>(this));
resize_observer_->observe(&GetVideoElement());
}
diff --git a/chromium/third_party/blink/renderer/core/html/media/video_wake_lock.cc b/chromium/third_party/blink/renderer/core/html/media/video_wake_lock.cc
index 795497623bf..5ec06cd93ab 100644
--- a/chromium/third_party/blink/renderer/core/html/media/video_wake_lock.cc
+++ b/chromium/third_party/blink/renderer/core/html/media/video_wake_lock.cc
@@ -12,6 +12,7 @@
#include "third_party/blink/renderer/core/frame/picture_in_picture_controller.h"
#include "third_party/blink/renderer/core/html/media/html_video_element.h"
#include "third_party/blink/renderer/core/html/media/remote_playback_controller.h"
+#include "third_party/blink/renderer/core/intersection_observer/intersection_observer_entry.h"
#include "third_party/blink/renderer/core/page/page.h"
namespace blink {
@@ -27,6 +28,12 @@ VideoWakeLock::VideoWakeLock(HTMLVideoElement& video)
this, true);
VideoElement().addEventListener(event_type_names::kLeavepictureinpicture,
this, true);
+ VideoElement().addEventListener(event_type_names::kVolumechange, this, true);
+
+ if (RuntimeEnabledFeatures::VideoWakeLockOptimisationHiddenMutedEnabled())
+ StartIntersectionObserver();
+ else
+ is_visible_ = true;
RemotePlaybackController* remote_playback_controller =
RemotePlaybackController::From(VideoElement());
@@ -38,17 +45,31 @@ VideoWakeLock::VideoWakeLock(HTMLVideoElement& video)
void VideoWakeLock::ElementDidMoveToNewDocument() {
SetExecutionContext(VideoElement().GetExecutionContext());
+
+ if (RuntimeEnabledFeatures::VideoWakeLockOptimisationHiddenMutedEnabled()) {
+ intersection_observer_->disconnect();
+ StartIntersectionObserver();
+ }
}
void VideoWakeLock::PageVisibilityChanged() {
Update();
}
+void VideoWakeLock::OnVisibilityChanged(
+ const HeapVector<Member<IntersectionObserverEntry>>& entries) {
+ DCHECK(RuntimeEnabledFeatures::VideoWakeLockOptimisationHiddenMutedEnabled());
+
+ is_visible_ = (entries.back()->intersectionRatio() > 0);
+ Update();
+}
+
void VideoWakeLock::Trace(Visitor* visitor) {
NativeEventListener::Trace(visitor);
PageVisibilityObserver::Trace(visitor);
ExecutionContextLifecycleStateObserver::Trace(visitor);
visitor->Trace(video_element_);
+ visitor->Trace(intersection_observer_);
}
void VideoWakeLock::Invoke(ExecutionContext*, Event* event) {
@@ -62,7 +83,8 @@ void VideoWakeLock::Invoke(ExecutionContext*, Event* event) {
playing_ = false;
} else {
DCHECK(event->type() == event_type_names::kEnterpictureinpicture ||
- event->type() == event_type_names::kLeavepictureinpicture);
+ event->type() == event_type_names::kLeavepictureinpicture ||
+ event->type() == event_type_names::kVolumechange);
}
Update();
@@ -96,7 +118,21 @@ bool VideoWakeLock::ShouldBeActive() const {
bool in_picture_in_picture =
PictureInPictureController::IsElementInPictureInPicture(&VideoElement());
- return playing_ && (page_visible || in_picture_in_picture) &&
+ // The visibility requirements are met if one of the following is true:
+ // - it's in Picture-in-Picture;
+ // - it's audibly playing on a visible page;
+ // - it's visible to the user.
+ bool visibility_requirements_met =
+ (in_picture_in_picture ||
+ (page_visible &&
+ (is_visible_ || VideoElement().EffectiveMediaVolume())));
+
+ // The video wake lock should be active iif:
+ // - it's playing;
+ // - the visibility requirements are met (see above);
+ // - it's *not* playing in Remote Playback;
+ // - the document is not paused nor destroyed.
+ return playing_ && visibility_requirements_met &&
remote_playback_state_ !=
mojom::blink::PresentationConnectionState::CONNECTED &&
!(VideoElement().GetDocument().IsContextPaused() ||
@@ -141,4 +177,13 @@ void VideoWakeLock::UpdateWakeLockService() {
wake_lock_service_->CancelWakeLock();
}
+void VideoWakeLock::StartIntersectionObserver() {
+ intersection_observer_ = IntersectionObserver::Create(
+ {}, {IntersectionObserver::kMinimumThreshold},
+ &VideoElement().GetDocument(),
+ WTF::BindRepeating(&VideoWakeLock::OnVisibilityChanged,
+ WrapWeakPersistent(this)));
+ intersection_observer_->observe(&VideoElement());
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/media/video_wake_lock.h b/chromium/third_party/blink/renderer/core/html/media/video_wake_lock.h
index 33f6d17a4de..b042b0ca13c 100644
--- a/chromium/third_party/blink/renderer/core/html/media/video_wake_lock.h
+++ b/chromium/third_party/blink/renderer/core/html/media/video_wake_lock.h
@@ -11,6 +11,7 @@
#include "third_party/blink/renderer/core/dom/events/native_event_listener.h"
#include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_state_observer.h"
#include "third_party/blink/renderer/core/html/media/remote_playback_observer.h"
+#include "third_party/blink/renderer/core/intersection_observer/intersection_observer.h"
#include "third_party/blink/renderer/core/page/page_visibility_observer.h"
namespace blink {
@@ -55,9 +56,16 @@ class CORE_EXPORT VideoWakeLock final
bool active_for_tests() const { return active_; }
private:
+ friend class VideoWakeLockTest;
+
// PageVisibilityObserver implementation.
void PageVisibilityChanged() final;
+ // Called by the IntersectionObserver instance when the visibility state of
+ // the video element has changed.
+ void OnVisibilityChanged(
+ const HeapVector<Member<IntersectionObserverEntry>>&);
+
// Called when any state is changed. Will update active state and notify the
// service if needed.
void Update();
@@ -74,6 +82,9 @@ class CORE_EXPORT VideoWakeLock final
// Notify the wake lock service of the current wake lock state.
void UpdateWakeLockService();
+ // Create a new |intersection_observer_| instance and start observing.
+ void StartIntersectionObserver();
+
HTMLVideoElement& VideoElement() { return *video_element_; }
const HTMLVideoElement& VideoElement() const { return *video_element_; }
@@ -86,6 +97,8 @@ class CORE_EXPORT VideoWakeLock final
bool active_ = false;
mojom::blink::PresentationConnectionState remote_playback_state_ =
mojom::blink::PresentationConnectionState::CLOSED;
+ Member<IntersectionObserver> intersection_observer_;
+ bool is_visible_ = false;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/media/video_wake_lock_test.cc b/chromium/third_party/blink/renderer/core/html/media/video_wake_lock_test.cc
index 1ca7a8c4e0c..407b93e81fb 100644
--- a/chromium/third_party/blink/renderer/core/html/media/video_wake_lock_test.cc
+++ b/chromium/third_party/blink/renderer/core/html/media/video_wake_lock_test.cc
@@ -11,6 +11,7 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
#include "third_party/blink/public/mojom/picture_in_picture/picture_in_picture.mojom-blink.h"
+#include "third_party/blink/renderer/core/css_value_keywords.h"
#include "third_party/blink/renderer/core/dom/events/event.h"
#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/picture_in_picture_controller.h"
@@ -106,16 +107,20 @@ class VideoWakeLockTest : public PageTestBase {
WTF::BindRepeating(&VideoWakeLockPictureInPictureService::Bind,
WTF::Unretained(&pip_service_)));
- video_ = MakeGarbageCollected<HTMLVideoElement>(GetDocument());
+ GetDocument().body()->setInnerHTML("<body><video></video></body>");
+ video_ = To<HTMLVideoElement>(GetDocument().QuerySelector("video"));
video_->SetReadyState(HTMLMediaElement::ReadyState::kHaveMetadata);
video_wake_lock_ = MakeGarbageCollected<VideoWakeLock>(*video_.Get());
- GetPage().SetVisibilityState(PageVisibilityState::kVisible, true);
+ GetPage().SetVisibilityState(mojom::blink::PageVisibilityState::kVisible,
+ true);
}
void TearDown() override {
GetDocument().GetBrowserInterfaceBroker().SetBinderForTesting(
mojom::blink::PictureInPictureService::Name_, {});
+
+ PageTestBase::TearDown();
}
HTMLVideoElement* Video() const { return video_.Get(); }
@@ -168,6 +173,19 @@ class VideoWakeLockTest : public PageTestBase {
video_->SetNetworkState(network_state);
}
+ void UpdateVisibilityObserver() {
+ UpdateAllLifecyclePhasesForTest();
+ test::RunPendingTasks();
+ }
+
+ void HideVideo() {
+ video_->SetInlineStyleProperty(CSSPropertyID::kDisplay, CSSValueID::kNone);
+ }
+
+ void ShowVideo() {
+ video_->SetInlineStyleProperty(CSSPropertyID::kDisplay, CSSValueID::kBlock);
+ }
+
private:
Persistent<HTMLVideoElement> video_;
Persistent<VideoWakeLock> video_wake_lock_;
@@ -196,32 +214,38 @@ TEST_F(VideoWakeLockTest, HiddingPageCancelsLock) {
SimulatePlaying();
EXPECT_TRUE(GetVideoWakeLock()->active_for_tests());
- GetPage().SetVisibilityState(PageVisibilityState::kHidden, false);
+ GetPage().SetVisibilityState(mojom::blink::PageVisibilityState::kHidden,
+ false);
EXPECT_FALSE(GetVideoWakeLock()->active_for_tests());
}
TEST_F(VideoWakeLockTest, PlayingWhileHiddenDoesNotRequestLock) {
- GetPage().SetVisibilityState(PageVisibilityState::kHidden, false);
+ GetPage().SetVisibilityState(mojom::blink::PageVisibilityState::kHidden,
+ false);
SimulatePlaying();
EXPECT_FALSE(GetVideoWakeLock()->active_for_tests());
}
TEST_F(VideoWakeLockTest, ShowingPageRequestsLock) {
SimulatePlaying();
- GetPage().SetVisibilityState(PageVisibilityState::kHidden, false);
+ GetPage().SetVisibilityState(mojom::blink::PageVisibilityState::kHidden,
+ false);
EXPECT_FALSE(GetVideoWakeLock()->active_for_tests());
- GetPage().SetVisibilityState(PageVisibilityState::kVisible, false);
+ GetPage().SetVisibilityState(mojom::blink::PageVisibilityState::kVisible,
+ false);
EXPECT_TRUE(GetVideoWakeLock()->active_for_tests());
}
TEST_F(VideoWakeLockTest, ShowingPageDoNotRequestsLockIfPaused) {
SimulatePlaying();
- GetPage().SetVisibilityState(PageVisibilityState::kHidden, false);
+ GetPage().SetVisibilityState(mojom::blink::PageVisibilityState::kHidden,
+ false);
EXPECT_FALSE(GetVideoWakeLock()->active_for_tests());
SimulatePause();
- GetPage().SetVisibilityState(PageVisibilityState::kVisible, false);
+ GetPage().SetVisibilityState(mojom::blink::PageVisibilityState::kVisible,
+ false);
EXPECT_FALSE(GetVideoWakeLock()->active_for_tests());
}
@@ -270,7 +294,8 @@ TEST_F(VideoWakeLockTest, PictureInPictureLocksWhenPageNotVisible) {
test::RunPendingTasks();
SimulatePlaying();
- GetPage().SetVisibilityState(PageVisibilityState::kHidden, false);
+ GetPage().SetVisibilityState(mojom::blink::PageVisibilityState::kHidden,
+ false);
EXPECT_FALSE(GetVideoWakeLock()->active_for_tests());
SimulateEnterPictureInPicture();
@@ -286,7 +311,8 @@ TEST_F(VideoWakeLockTest, PictureInPictureDoesNoLockWhenPaused) {
test::RunPendingTasks();
SimulatePlaying();
- GetPage().SetVisibilityState(PageVisibilityState::kHidden, false);
+ GetPage().SetVisibilityState(mojom::blink::PageVisibilityState::kHidden,
+ false);
EXPECT_FALSE(GetVideoWakeLock()->active_for_tests());
SimulatePause();
@@ -303,7 +329,8 @@ TEST_F(VideoWakeLockTest, LeavingPictureInPictureCancelsLock) {
test::RunPendingTasks();
SimulatePlaying();
- GetPage().SetVisibilityState(PageVisibilityState::kHidden, false);
+ GetPage().SetVisibilityState(mojom::blink::PageVisibilityState::kHidden,
+ false);
SimulateEnterPictureInPicture();
EXPECT_TRUE(GetVideoWakeLock()->active_for_tests());
@@ -365,4 +392,93 @@ TEST_F(VideoWakeLockTest, LoadingCancelsLock) {
EXPECT_FALSE(GetVideoWakeLock()->active_for_tests());
}
+TEST_F(VideoWakeLockTest, MutedHiddenVideoDoesNotTakeLock) {
+ Video()->setMuted(true);
+ HideVideo();
+ UpdateVisibilityObserver();
+
+ SimulatePlaying();
+
+ EXPECT_FALSE(GetVideoWakeLock()->active_for_tests());
+}
+
+TEST_F(VideoWakeLockTest, AudibleHiddenVideoTakesLock) {
+ Video()->setMuted(false);
+ HideVideo();
+ UpdateVisibilityObserver();
+
+ SimulatePlaying();
+
+ EXPECT_TRUE(GetVideoWakeLock()->active_for_tests());
+}
+
+TEST_F(VideoWakeLockTest, UnmutingHiddenVideoTakesLock) {
+ Video()->setMuted(true);
+ HideVideo();
+ UpdateVisibilityObserver();
+
+ SimulatePlaying();
+ EXPECT_FALSE(GetVideoWakeLock()->active_for_tests());
+
+ Video()->setMuted(false);
+ test::RunPendingTasks();
+ EXPECT_TRUE(GetVideoWakeLock()->active_for_tests());
+}
+
+TEST_F(VideoWakeLockTest, MutingHiddenVideoReleasesLock) {
+ Video()->setMuted(false);
+ HideVideo();
+ UpdateVisibilityObserver();
+
+ SimulatePlaying();
+ EXPECT_TRUE(GetVideoWakeLock()->active_for_tests());
+
+ Video()->setMuted(true);
+ test::RunPendingTasks();
+ EXPECT_FALSE(GetVideoWakeLock()->active_for_tests());
+}
+
+TEST_F(VideoWakeLockTest, HidingAudibleVideoDoesNotReleaseLock) {
+ Video()->setMuted(false);
+ ShowVideo();
+ UpdateVisibilityObserver();
+ SimulatePlaying();
+ EXPECT_TRUE(GetVideoWakeLock()->active_for_tests());
+
+ HideVideo();
+ UpdateVisibilityObserver();
+ EXPECT_TRUE(GetVideoWakeLock()->active_for_tests());
+}
+
+TEST_F(VideoWakeLockTest, HidingMutedVideoReleasesLock) {
+ Video()->setMuted(true);
+ ShowVideo();
+ UpdateVisibilityObserver();
+ SimulatePlaying();
+ EXPECT_TRUE(GetVideoWakeLock()->active_for_tests());
+
+ HideVideo();
+ UpdateVisibilityObserver();
+ EXPECT_FALSE(GetVideoWakeLock()->active_for_tests());
+}
+
+TEST_F(VideoWakeLockTest, HiddenMutedVideoAlwaysVisibleInPictureInPicture) {
+ // This initialeses the video element in order to not crash when the
+ // interstitial tries to show itself and so that the WebMediaPlayer is set up.
+ scoped_refptr<cc::Layer> layer = cc::Layer::Create();
+ SetFakeCcLayer(layer.get());
+ Video()->SetSrc("http://example.com/foo.mp4");
+ Video()->setMuted(true);
+ HideVideo();
+ UpdateVisibilityObserver();
+ SimulatePlaying();
+ EXPECT_FALSE(GetVideoWakeLock()->active_for_tests());
+
+ SimulateEnterPictureInPicture();
+ EXPECT_TRUE(GetVideoWakeLock()->active_for_tests());
+
+ SimulateLeavePictureInPicture();
+ EXPECT_FALSE(GetVideoWakeLock()->active_for_tests());
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/parser/html_construction_site.cc b/chromium/third_party/blink/renderer/core/html/parser/html_construction_site.cc
index 88bf8c170a1..dc384962258 100644
--- a/chromium/third_party/blink/renderer/core/html/parser/html_construction_site.cc
+++ b/chromium/third_party/blink/renderer/core/html/parser/html_construction_site.cc
@@ -111,8 +111,12 @@ static inline bool IsAllWhitespace(const String& string) {
}
static inline void Insert(HTMLConstructionSiteTask& task) {
+ // https://html.spec.whatwg.org/multipage/parsing.html#appropriate-place-for-inserting-a-node
+ // 3. If the adjusted insertion location is inside a template element, let it
+ // instead be inside the template element's template contents, after its last
+ // child (if any).
if (auto* template_element = DynamicTo<HTMLTemplateElement>(*task.parent))
- task.parent = template_element->content();
+ task.parent = template_element->TemplateContentForHTMLConstructionSite();
// https://html.spec.whatwg.org/C/#insert-a-foreign-element
// 3.1, (3) Push (pop) an element queue
@@ -702,6 +706,17 @@ void HTMLConstructionSite::InsertHTMLFormElement(AtomicHTMLToken* token,
open_elements_.Push(MakeGarbageCollected<HTMLStackItem>(form_element, token));
}
+void HTMLConstructionSite::InsertHTMLTemplateElement(
+ AtomicHTMLToken* token,
+ DeclarativeShadowRootType declarative_shadow_root_type) {
+ auto* template_element = To<HTMLTemplateElement>(
+ CreateElement(token, html_names::xhtmlNamespaceURI));
+ template_element->SetDeclarativeShadowRootType(declarative_shadow_root_type);
+ AttachLater(CurrentNode(), template_element);
+ open_elements_.Push(
+ MakeGarbageCollected<HTMLStackItem>(template_element, token));
+}
+
void HTMLConstructionSite::InsertHTMLElement(AtomicHTMLToken* token) {
Element* element = CreateElement(token, html_names::xhtmlNamespaceURI);
AttachLater(CurrentNode(), element);
@@ -780,10 +795,13 @@ void HTMLConstructionSite::InsertTextNode(const StringView& string,
if (ShouldFosterParent())
FindFosterSite(dummy_task);
- // FIXME: This probably doesn't need to be done both here and in insert(Task).
+ // TODO(crbug.com/1070669): This can likely be removed, because it is already
+ // handled in Insert().
if (auto* template_element =
- DynamicTo<HTMLTemplateElement>(*dummy_task.parent))
- dummy_task.parent = template_element->content();
+ DynamicTo<HTMLTemplateElement>(*dummy_task.parent)) {
+ dummy_task.parent =
+ template_element->TemplateContentForHTMLConstructionSite();
+ }
// Unclear when parent != case occurs. Somehow we insert text into two
// separate nodes while processing the same Token. The nextChild !=
@@ -844,8 +862,14 @@ CreateElementFlags HTMLConstructionSite::GetCreateElementFlags() const {
}
Document& HTMLConstructionSite::OwnerDocumentForCurrentNode() {
- if (auto* template_element = DynamicTo<HTMLTemplateElement>(*CurrentNode()))
- return template_element->content()->GetDocument();
+ // TODO(crbug.com/1070667): For <template> elements, many operations need to
+ // be re-targeted to the .content() document of the template. This function is
+ // used in those places. The spec needs to be updated to reflect this
+ // behavior, and when that happens, a link to the spec should be placed here.
+ if (auto* template_element = DynamicTo<HTMLTemplateElement>(*CurrentNode())) {
+ return template_element->TemplateContentForHTMLConstructionSite()
+ ->GetDocument();
+ }
return CurrentNode()->GetDocument();
}
diff --git a/chromium/third_party/blink/renderer/core/html/parser/html_construction_site.h b/chromium/third_party/blink/renderer/core/html/parser/html_construction_site.h
index 132b8a9be68..6e40ad8438f 100644
--- a/chromium/third_party/blink/renderer/core/html/parser/html_construction_site.h
+++ b/chromium/third_party/blink/renderer/core/html/parser/html_construction_site.h
@@ -102,6 +102,7 @@ class Document;
class Element;
class HTMLFormElement;
class HTMLParserReentryPermit;
+enum class DeclarativeShadowRootType;
class HTMLConstructionSite final {
DISALLOW_NEW();
@@ -148,6 +149,9 @@ class HTMLConstructionSite final {
void InsertCommentOnDocument(AtomicHTMLToken*);
void InsertCommentOnHTMLHtmlElement(AtomicHTMLToken*);
void InsertHTMLElement(AtomicHTMLToken*);
+ void InsertHTMLTemplateElement(
+ AtomicHTMLToken*,
+ DeclarativeShadowRootType declarative_shadow_root_type);
void InsertSelfClosingHTMLElementDestroyingToken(AtomicHTMLToken*);
void InsertFormattingElement(AtomicHTMLToken*);
void InsertHTMLHeadElement(AtomicHTMLToken*);
diff --git a/chromium/third_party/blink/renderer/core/html/parser/html_preload_scanner.cc b/chromium/third_party/blink/renderer/core/html/parser/html_preload_scanner.cc
index c2410ab5a27..f80ec1268db 100644
--- a/chromium/third_party/blink/renderer/core/html/parser/html_preload_scanner.cc
+++ b/chromium/third_party/blink/renderer/core/html/parser/html_preload_scanner.cc
@@ -302,53 +302,20 @@ class TokenPreloadScanner::StartTagScanner {
document_parameters.lazyload_policy_enforced) {
effective_loading_attr_value = LoadingAttrValue::kAuto;
}
- if (type == ResourceType::kImage) {
- bool is_lazy_load_image_enabled = false;
- switch (effective_loading_attr_value) {
- case LoadingAttrValue::kEager:
- is_lazy_load_image_enabled = false;
- break;
- case LoadingAttrValue::kLazy:
- is_lazy_load_image_enabled =
- document_parameters.lazy_load_image_setting !=
- LocalFrame::LazyLoadImageSetting::kDisabled;
- break;
- case LoadingAttrValue::kAuto:
- if ((width_attr_dimension_type_ ==
- HTMLImageElement::LazyLoadDimensionType::kAbsoluteSmall &&
- height_attr_dimension_type_ ==
- HTMLImageElement::LazyLoadDimensionType::kAbsoluteSmall) ||
- inline_style_dimensions_type_ ==
- HTMLImageElement::LazyLoadDimensionType::kAbsoluteSmall) {
- is_lazy_load_image_enabled = false;
- } else {
- is_lazy_load_image_enabled =
- document_parameters.lazy_load_image_setting ==
- LocalFrame::LazyLoadImageSetting::kEnabledAutomatic;
- }
- break;
- }
- // Do not preload if lazyload is possible but metadata fetch is disabled.
- if (is_lazy_load_image_enabled &&
- !RuntimeEnabledFeatures::LazyImageLoadingMetadataFetchEnabled()) {
- return nullptr;
- }
- // LazyLoad: Do not preload if absolute dimensions are mentioned in width
- // and height attributes or in the inline style, and the dimensions are
- // not small enough.
- if (is_lazy_load_image_enabled &&
- ((width_attr_dimension_type_ ==
- HTMLImageElement::LazyLoadDimensionType::kAbsoluteNotSmall &&
- height_attr_dimension_type_ ==
- HTMLImageElement::LazyLoadDimensionType::kAbsoluteNotSmall) ||
- inline_style_dimensions_type_ ==
- HTMLImageElement::LazyLoadDimensionType::kAbsoluteNotSmall)) {
- return nullptr;
- }
- request->SetIsLazyLoadImageEnabled(is_lazy_load_image_enabled);
+ if (type == ResourceType::kImage && Match(tag_impl_, html_names::kImgTag) &&
+ IsLazyLoadImageDeferable(document_parameters)) {
+ return nullptr;
+ }
+ // Do not set integrity metadata for <link> elements for destinations not
+ // supporting SRI (crbug.com/1058045).
+ // A corresponding check for non-preload-scanner code path is in
+ // PreloadHelper::PreloadIfNeeded().
+ // TODO(crbug.com/981419): Honor the integrity attribute value for all
+ // supported preload destinations, not just the destinations that support
+ // SRI in the first place.
+ if (type == ResourceType::kScript || type == ResourceType::kCSSStyleSheet) {
+ request->SetIntegrityMetadata(integrity_metadata_);
}
-
- request->SetIntegrityMetadata(integrity_metadata_);
if (scanner_type_ == ScannerType::kInsertion)
request->SetFromInsertionScanner(true);
@@ -579,6 +546,50 @@ class TokenPreloadScanner::StartTagScanner {
ProcessVideoAttribute(attribute_name, attribute_value);
}
+ bool IsLazyLoadImageDeferable(
+ const CachedDocumentParameters& document_parameters) {
+ if (!document_parameters.lazy_load_image_observer)
+ return false;
+
+ bool is_fully_loadable =
+ document_parameters.lazy_load_image_observer
+ ->IsFullyLoadableFirstKImageAndDecrementCount();
+ if (document_parameters.lazy_load_image_setting ==
+ LocalFrame::LazyLoadImageSetting::kDisabled) {
+ return false;
+ }
+
+ // If the 'lazyload' feature policy is enforced, the attribute value
+ // loading='eager' is considered as 'auto'.
+ LoadingAttrValue effective_loading_attr_value = loading_attr_value_;
+ if (effective_loading_attr_value == LoadingAttrValue::kEager &&
+ document_parameters.lazyload_policy_enforced) {
+ effective_loading_attr_value = LoadingAttrValue::kAuto;
+ }
+ switch (effective_loading_attr_value) {
+ case LoadingAttrValue::kEager:
+ return false;
+ case LoadingAttrValue::kLazy:
+ return true;
+ case LoadingAttrValue::kAuto:
+ if ((width_attr_dimension_type_ ==
+ HTMLImageElement::LazyLoadDimensionType::kAbsoluteSmall &&
+ height_attr_dimension_type_ ==
+ HTMLImageElement::LazyLoadDimensionType::kAbsoluteSmall) ||
+ inline_style_dimensions_type_ ==
+ HTMLImageElement::LazyLoadDimensionType::kAbsoluteSmall) {
+ // Fetch small images eagerly.
+ return false;
+ } else if (is_fully_loadable ||
+ document_parameters.lazy_load_image_setting !=
+ LocalFrame::LazyLoadImageSetting::kEnabledAutomatic) {
+ return false;
+ }
+ break;
+ }
+ return true;
+ }
+
void SetUrlToLoad(const String& value, URLReplacement replacement) {
// We only respect the first src/href, per HTML5:
// http://www.whatwg.org/specs/web-apps/current-work/multipage/tokenization.html#attribute-name-state
@@ -972,7 +983,8 @@ void TokenPreloadScanner::ScanCommon(
token.GetAttributeItem(html_names::kContentAttr);
if (content_attribute) {
client_hints_preferences_.UpdateFromAcceptClientHintsHeader(
- content_attribute->Value(), document_url_, nullptr);
+ content_attribute->Value(), document_url_,
+ ClientHintsPreferences::UpdateMode::kMerge, nullptr);
}
}
return;
@@ -1106,6 +1118,7 @@ CachedDocumentParameters::CachedDocumentParameters(Document* document) {
if (document->Loader() && document->Loader()->GetFrame()) {
lazy_load_image_setting =
document->Loader()->GetFrame()->GetLazyLoadImageSetting();
+ lazy_load_image_observer = document->EnsureLazyLoadImageObserver();
} else {
lazy_load_image_setting = LocalFrame::LazyLoadImageSetting::kDisabled;
}
diff --git a/chromium/third_party/blink/renderer/core/html/parser/html_preload_scanner.h b/chromium/third_party/blink/renderer/core/html/parser/html_preload_scanner.h
index d621de64499..429b1495788 100644
--- a/chromium/third_party/blink/renderer/core/html/parser/html_preload_scanner.h
+++ b/chromium/third_party/blink/renderer/core/html/parser/html_preload_scanner.h
@@ -41,6 +41,7 @@
#include "third_party/blink/renderer/core/html/parser/html_token.h"
#include "third_party/blink/renderer/core/html/parser/preload_request.h"
#include "third_party/blink/renderer/core/page/viewport_description.h"
+#include "third_party/blink/renderer/platform/heap/persistent.h"
#include "third_party/blink/renderer/platform/text/segmented_string.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
@@ -50,6 +51,7 @@ typedef wtf_size_t TokenPreloadScannerCheckpoint;
class HTMLParserOptions;
class HTMLTokenizer;
+class LazyLoadImageObserver;
class SegmentedString;
struct CORE_EXPORT CachedDocumentParameters {
@@ -67,6 +69,7 @@ struct CORE_EXPORT CachedDocumentParameters {
SubresourceIntegrity::IntegrityFeatures integrity_features;
bool lazyload_policy_enforced;
LocalFrame::LazyLoadImageSetting lazy_load_image_setting;
+ WeakPersistent<LazyLoadImageObserver> lazy_load_image_observer;
};
class TokenPreloadScanner {
diff --git a/chromium/third_party/blink/renderer/core/html/parser/html_preload_scanner_test.cc b/chromium/third_party/blink/renderer/core/html/parser/html_preload_scanner_test.cc
index 9ac9b6412bf..a19d93de8d2 100644
--- a/chromium/third_party/blink/renderer/core/html/parser/html_preload_scanner_test.cc
+++ b/chromium/third_party/blink/renderer/core/html/parser/html_preload_scanner_test.cc
@@ -110,17 +110,18 @@ class HTMLMockHTMLResourcePreloader : public ResourcePreloader {
EXPECT_EQ(url, preload_request_->ResourceURL());
EXPECT_EQ(base_url, preload_request_->BaseURL().GetString());
EXPECT_EQ(width, preload_request_->ResourceWidth());
- EXPECT_EQ(preferences.ShouldSend(mojom::WebClientHintsType::kDpr),
- preload_request_->Preferences().ShouldSend(
- mojom::WebClientHintsType::kDpr));
- EXPECT_EQ(
- preferences.ShouldSend(mojom::WebClientHintsType::kResourceWidth),
- preload_request_->Preferences().ShouldSend(
- mojom::WebClientHintsType::kResourceWidth));
EXPECT_EQ(
- preferences.ShouldSend(mojom::WebClientHintsType::kViewportWidth),
+ preferences.ShouldSend(network::mojom::WebClientHintsType::kDpr),
preload_request_->Preferences().ShouldSend(
- mojom::WebClientHintsType::kViewportWidth));
+ network::mojom::WebClientHintsType::kDpr));
+ EXPECT_EQ(preferences.ShouldSend(
+ network::mojom::WebClientHintsType::kResourceWidth),
+ preload_request_->Preferences().ShouldSend(
+ network::mojom::WebClientHintsType::kResourceWidth));
+ EXPECT_EQ(preferences.ShouldSend(
+ network::mojom::WebClientHintsType::kViewportWidth),
+ preload_request_->Preferences().ShouldSend(
+ network::mojom::WebClientHintsType::kViewportWidth));
}
}
@@ -193,9 +194,11 @@ class HTMLMockHTMLResourcePreloader : public ResourcePreloader {
}
void LazyLoadImageEnabledVerification(bool expected_enabled) {
- ASSERT_TRUE(preload_request_.get());
- EXPECT_EQ(expected_enabled,
- preload_request_->IsLazyLoadImageEnabledForTesting());
+ if (expected_enabled) {
+ EXPECT_FALSE(preload_request_) << preload_request_->ResourceURL();
+ } else {
+ ASSERT_TRUE(preload_request_.get());
+ }
}
protected:
@@ -612,14 +615,16 @@ TEST_F(HTMLPreloadScannerTest, testMetaAcceptCH) {
ClientHintsPreferences resource_width;
ClientHintsPreferences all;
ClientHintsPreferences viewport_width;
- dpr.SetShouldSendForTesting(mojom::WebClientHintsType::kDpr);
- all.SetShouldSendForTesting(mojom::WebClientHintsType::kDpr);
+ dpr.SetShouldSendForTesting(network::mojom::WebClientHintsType::kDpr);
+ all.SetShouldSendForTesting(network::mojom::WebClientHintsType::kDpr);
resource_width.SetShouldSendForTesting(
- mojom::WebClientHintsType::kResourceWidth);
- all.SetShouldSendForTesting(mojom::WebClientHintsType::kResourceWidth);
+ network::mojom::WebClientHintsType::kResourceWidth);
+ all.SetShouldSendForTesting(
+ network::mojom::WebClientHintsType::kResourceWidth);
viewport_width.SetShouldSendForTesting(
- mojom::WebClientHintsType::kViewportWidth);
- all.SetShouldSendForTesting(mojom::WebClientHintsType::kViewportWidth);
+ network::mojom::WebClientHintsType::kViewportWidth);
+ all.SetShouldSendForTesting(
+ network::mojom::WebClientHintsType::kViewportWidth);
PreloadScannerTestCase test_cases[] = {
{"http://example.test",
"<meta http-equiv='accept-ch' content='bla'><img srcset='bla.gif 320w, "
@@ -678,9 +683,11 @@ TEST_F(HTMLPreloadScannerTest, testMetaAcceptCH) {
TEST_F(HTMLPreloadScannerTest, testMetaAcceptCHInsecureDocument) {
ClientHintsPreferences all;
- all.SetShouldSendForTesting(mojom::WebClientHintsType::kDpr);
- all.SetShouldSendForTesting(mojom::WebClientHintsType::kResourceWidth);
- all.SetShouldSendForTesting(mojom::WebClientHintsType::kViewportWidth);
+ all.SetShouldSendForTesting(network::mojom::WebClientHintsType::kDpr);
+ all.SetShouldSendForTesting(
+ network::mojom::WebClientHintsType::kResourceWidth);
+ all.SetShouldSendForTesting(
+ network::mojom::WebClientHintsType::kViewportWidth);
const PreloadScannerTestCase expect_no_client_hint = {
"http://example.test",
@@ -1215,8 +1222,6 @@ TEST_F(HTMLPreloadScannerTest, LazyLoadImage_DisabledForSmallImages) {
ScopedLazyImageLoadingForTest scoped_lazy_image_loading_for_test(true);
ScopedAutomaticLazyImageLoadingForTest
scoped_automatic_lazy_image_loading_for_test(true);
- ScopedLazyImageLoadingMetadataFetchForTest
- scoped_lazy_image_loading_metadata_fetch_for_test(true);
ScopedRestrictAutomaticLazyImageLoadingToDataSaverForTest
scoped_restrict_automatic_lazy_image_loading_to_data_saver_for_test(
false);
@@ -1256,8 +1261,6 @@ TEST_F(HTMLPreloadScannerTest,
ScopedLazyImageLoadingForTest scoped_lazy_image_loading_for_test(true);
ScopedAutomaticLazyImageLoadingForTest
scoped_automatic_lazy_image_loading_for_test(true);
- ScopedLazyImageLoadingMetadataFetchForTest
- scoped_lazy_image_loading_metadata_fetch_for_test(true);
ScopedRestrictAutomaticLazyImageLoadingToDataSaverForTest
scoped_restrict_automatic_lazy_image_loading_to_data_saver_for_test(
false);
@@ -1279,8 +1282,6 @@ TEST_F(HTMLPreloadScannerTest,
TEST_F(HTMLPreloadScannerTest,
LazyLoadImage_FeatureExplicitEnabledWithAttribute) {
ScopedLazyImageLoadingForTest scoped_lazy_image_loading_for_test(true);
- ScopedLazyImageLoadingMetadataFetchForTest
- scoped_lazy_image_loading_metadata_fetch_for_test(true);
GetDocument().GetSettings()->SetLazyLoadEnabled(true);
RunSetUp(kViewportEnabled);
LazyLoadImageTestCase test_cases[] = {
@@ -1298,8 +1299,6 @@ TEST_F(HTMLPreloadScannerTest,
ScopedLazyImageLoadingForTest scoped_lazy_image_loading_for_test(true);
ScopedAutomaticLazyImageLoadingForTest
scoped_automatic_lazy_image_loading_for_test(true);
- ScopedLazyImageLoadingMetadataFetchForTest
- scoped_lazy_image_loading_metadata_fetch_for_test(true);
ScopedRestrictAutomaticLazyImageLoadingToDataSaverForTest
scoped_restrict_automatic_lazy_image_loading_to_data_saver_for_test(
false);
@@ -1341,8 +1340,6 @@ TEST_F(HTMLPreloadScannerTest,
LazyLoadImage_FeatureExplicitPreloadForLargeImages) {
// Large images should not be preloaded, when loading is lazy.
ScopedLazyImageLoadingForTest scoped_lazy_image_loading_for_test(true);
- ScopedLazyImageLoadingMetadataFetchForTest
- scoped_lazy_image_loading_metadata_fetch_for_test(true);
GetDocument().GetSettings()->SetLazyLoadEnabled(true);
RunSetUp(kViewportEnabled);
PreloadScannerTestCase test_cases[] = {
@@ -1372,7 +1369,6 @@ TEST_F(HTMLPreloadScannerTest,
TEST_F(HTMLPreloadScannerTest, LazyLoadImage_DisableMetadataFetch) {
GetDocument().GetSettings()->SetLazyLoadEnabled(true);
struct TestCase {
- bool metadata_fetch_feature_enabled;
bool automatic_lazy_image_loading_enabled;
const char* loading_attr_value;
bool expected_is_preload;
@@ -1383,28 +1379,19 @@ TEST_F(HTMLPreloadScannerTest, LazyLoadImage_DisableMetadataFetch) {
// The lazyload eligible cases should not trigger any preload when
// metadata fetch feature disabled, and trigger placeholder fetch if
// metadata fetch feature is active.
- {false, false, "lazy", false, false},
- {false, true, "lazy", false, false},
- {false, true, "auto", false, false},
- {true, false, "lazy", true, true},
- {true, true, "lazy", true, true},
- {true, true, "auto", true, true},
+ {false, "lazy", false, false},
+ {true, "lazy", false, false},
+ {true, "auto", false, false},
// Lazyload ineligible case.
- {false, false, "auto", true, false},
- {true, false, "auto", true, false},
+ {false, "auto", true, false},
// Full image should be fetched when loading='eager' irrespective of
// automatic lazyload or metadata fetch feature states.
- {false, false, "eager", true, false},
- {false, true, "eager", true, false},
- {true, false, "eager", true, false},
- {true, true, "eager", true, false},
+ {false, "eager", true, false},
+ {true, "eager", true, false},
};
for (const auto& test_case : test_cases) {
- ScopedLazyImageLoadingMetadataFetchForTest
- scoped_lazy_image_loading_metadata_fetch_for_test(
- test_case.metadata_fetch_feature_enabled);
ScopedAutomaticLazyImageLoadingForTest
scoped_automatic_lazy_image_loading_for_test(
test_case.automatic_lazy_image_loading_enabled);
@@ -1427,4 +1414,58 @@ TEST_F(HTMLPreloadScannerTest, LazyLoadImage_DisableMetadataFetch) {
}
}
+TEST_F(HTMLPreloadScannerTest,
+ LazyLoadImage_FirstKImagesNotAppliesForExplicit) {
+ ScopedAutomaticLazyImageLoadingForTest
+ scoped_automatic_lazy_image_loading_for_test(false);
+ ScopedRestrictAutomaticLazyImageLoadingToDataSaverForTest
+ scoped_restrict_automatic_lazy_image_loading_to_data_saver_for_test(
+ false);
+ GetDocument().GetSettings()->SetLazyLoadEnabled(true);
+ GetDocument().GetSettings()->SetLazyImageFirstKFullyLoadUnknown(1);
+ RunSetUp(kViewportEnabled);
+
+ // Neither of the images should be preloaded.
+ LazyLoadImageTestCase test1 = {"<img src='foo.jpg' loading='lazy'>", true};
+ Test(test1);
+ LazyLoadImageTestCase test2 = {"<img src='bar.jpg' loading='lazy'>", true};
+ Test(test2);
+}
+
+TEST_F(HTMLPreloadScannerTest, LazyLoadImage_FirstKImagesAppliesForAutomatic) {
+ ScopedAutomaticLazyImageLoadingForTest
+ scoped_automatic_lazy_image_loading_for_test(true);
+ ScopedRestrictAutomaticLazyImageLoadingToDataSaverForTest
+ scoped_restrict_automatic_lazy_image_loading_to_data_saver_for_test(
+ false);
+ GetDocument().GetSettings()->SetLazyLoadEnabled(true);
+ GetDocument().GetSettings()->SetLazyImageFirstKFullyLoadUnknown(1);
+ RunSetUp(kViewportEnabled);
+
+ // Only the first image should get preloaded
+ LazyLoadImageTestCase test1 = {"<img src='foo.jpg'>", false};
+ Test(test1);
+ LazyLoadImageTestCase test2 = {"<img src='bar.jpg'>", true};
+ Test(test2);
+}
+
+TEST_F(HTMLPreloadScannerTest,
+ LazyLoadImage_ExplicitImageCountedForFirstKImages) {
+ ScopedAutomaticLazyImageLoadingForTest
+ scoped_automatic_lazy_image_loading_for_test(true);
+ ScopedRestrictAutomaticLazyImageLoadingToDataSaverForTest
+ scoped_restrict_automatic_lazy_image_loading_to_data_saver_for_test(
+ false);
+ GetDocument().GetSettings()->SetLazyLoadEnabled(true);
+ GetDocument().GetSettings()->SetLazyImageFirstKFullyLoadUnknown(1);
+ RunSetUp(kViewportEnabled);
+
+ // The first image should be counted towards first K images limit, even though
+ // it has loading='lazy'.
+ LazyLoadImageTestCase test1 = {"<img src='foo.jpg' loading='lazy'>", true};
+ Test(test1);
+ LazyLoadImageTestCase test2 = {"<img src='bar.jpg'>", true};
+ Test(test2);
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/parser/html_tree_builder.cc b/chromium/third_party/blink/renderer/core/html/parser/html_tree_builder.cc
index 24f19c4dc6e..c6551c6cfea 100644
--- a/chromium/third_party/blink/renderer/core/html/parser/html_tree_builder.cc
+++ b/chromium/third_party/blink/renderer/core/html/parser/html_tree_builder.cc
@@ -893,7 +893,29 @@ void HTMLTreeBuilder::ProcessStartTagForInBody(AtomicHTMLToken* token) {
void HTMLTreeBuilder::ProcessTemplateStartTag(AtomicHTMLToken* token) {
tree_.ActiveFormattingElements()->AppendMarker();
- tree_.InsertHTMLElement(token);
+
+ DeclarativeShadowRootType declarative_shadow_root_type(
+ DeclarativeShadowRootType::kNone);
+ if (RuntimeEnabledFeatures::DeclarativeShadowDOMEnabled()) {
+ if (Attribute* type_attribute =
+ token->GetAttributeItem(html_names::kShadowrootAttr)) {
+ String shadow_mode = type_attribute->Value();
+ if (EqualIgnoringASCIICase(shadow_mode, "open")) {
+ declarative_shadow_root_type = DeclarativeShadowRootType::kOpen;
+ } else if (EqualIgnoringASCIICase(shadow_mode, "closed")) {
+ declarative_shadow_root_type = DeclarativeShadowRootType::kClosed;
+ } else {
+ tree_.OwnerDocumentForCurrentNode().AddConsoleMessage(
+ MakeGarbageCollected<ConsoleMessage>(
+ mojom::blink::ConsoleMessageSource::kOther,
+ mojom::blink::ConsoleMessageLevel::kWarning,
+ "Invalid declarative shadowroot attribute value \"" +
+ shadow_mode +
+ "\". Valid values include \"open\" and \"closed\"."));
+ }
+ }
+ }
+ tree_.InsertHTMLTemplateElement(token, declarative_shadow_root_type);
frameset_ok_ = false;
template_insertion_modes_.push_back(kTemplateContentsMode);
SetInsertionMode(kTemplateContentsMode);
@@ -920,39 +942,38 @@ bool HTMLTreeBuilder::ProcessTemplateEndTag(AtomicHTMLToken* token) {
tree_.ActiveFormattingElements()->ClearToLastMarker();
template_insertion_modes_.pop_back();
ResetInsertionModeAppropriately();
- // Check for a declarative shadow root.
if (RuntimeEnabledFeatures::DeclarativeShadowDOMEnabled() &&
template_stack_item) {
- if (Attribute* type_attribute = template_stack_item->GetAttributeItem(
- html_names::kShadowrootAttr)) {
- String shadow_mode = type_attribute->Value();
- bool is_open = EqualIgnoringASCIICase(shadow_mode, "open");
- if (is_open || EqualIgnoringASCIICase(shadow_mode, "closed")) {
- DCHECK(template_stack_item->IsElementNode());
- DCHECK(shadow_host_stack_item);
- DCHECK(shadow_host_stack_item->IsElementNode());
- UseCounter::Count(shadow_host_stack_item->GetElement()->GetDocument(),
- WebFeature::kDeclarativeShadowRoot);
- bool delegates_focus = template_stack_item->GetAttributeItem(
- html_names::kShadowrootdelegatesfocusAttr);
- // TODO(1063157): Add an attribute for imperative slot assignment.
- bool manual_slotting = false;
- shadow_host_stack_item->GetElement()->AttachDeclarativeShadowRoot(
- DynamicTo<HTMLTemplateElement>(template_stack_item->GetElement()),
- is_open ? ShadowRootType::kOpen : ShadowRootType::kClosed,
- delegates_focus ? FocusDelegation::kDelegateFocus
- : FocusDelegation::kNone,
- manual_slotting ? SlotAssignmentMode::kManual
- : SlotAssignmentMode::kAuto);
- } else {
- tree_.OwnerDocumentForCurrentNode().AddConsoleMessage(
- MakeGarbageCollected<ConsoleMessage>(
- mojom::blink::ConsoleMessageSource::kOther,
- mojom::blink::ConsoleMessageLevel::kWarning,
- "Invalid declarative shadowroot attribute value \"" +
- shadow_mode +
- "\". Valid values include \"open\" and \"closed\"."));
- }
+ DCHECK(template_stack_item->IsElementNode());
+ HTMLTemplateElement* template_element =
+ DynamicTo<HTMLTemplateElement>(template_stack_item->GetElement());
+ // 9. If the start tag for the declarative template element did not have an
+ // attribute with the name "shadowroot" whose value was an ASCII
+ // case-insensitive match for the strings "open" or "closed", then stop this
+ // algorithm.
+ // 10. If the adjusted current node is the topmost element in the stack of
+ // open elements, then stop this algorithm.
+ if (template_element->IsDeclarativeShadowRoot() &&
+ shadow_host_stack_item->GetNode() != tree_.OpenElements()->RootNode()) {
+ DCHECK(shadow_host_stack_item);
+ DCHECK(shadow_host_stack_item->IsElementNode());
+ UseCounter::Count(shadow_host_stack_item->GetElement()->GetDocument(),
+ WebFeature::kDeclarativeShadowRoot);
+ bool delegates_focus = template_stack_item->GetAttributeItem(
+ html_names::kShadowrootdelegatesfocusAttr);
+ // TODO(crbug.com/1063157): Add an attribute for imperative slot
+ // assignment.
+ bool manual_slotting = false;
+ shadow_host_stack_item->GetElement()->AttachDeclarativeShadowRoot(
+ template_element,
+ template_element->GetDeclarativeShadowRootType() ==
+ DeclarativeShadowRootType::kOpen
+ ? ShadowRootType::kOpen
+ : ShadowRootType::kClosed,
+ delegates_focus ? FocusDelegation::kDelegateFocus
+ : FocusDelegation::kNone,
+ manual_slotting ? SlotAssignmentMode::kManual
+ : SlotAssignmentMode::kAuto);
}
}
return true;
diff --git a/chromium/third_party/blink/renderer/core/html/parser/preload_request.cc b/chromium/third_party/blink/renderer/core/html/parser/preload_request.cc
index a355cb13d0b..b2dca269a73 100644
--- a/chromium/third_party/blink/renderer/core/html/parser/preload_request.cc
+++ b/chromium/third_party/blink/renderer/core/html/parser/preload_request.cc
@@ -91,9 +91,7 @@ Resource* PreloadRequest::Start(Document* document) {
FetchParameters params(std::move(resource_request), options);
if (resource_type_ == ResourceType::kImportResource) {
- const SecurityOrigin* security_origin =
- document->ContextDocument()->GetSecurityOrigin();
- params.SetCrossOriginAccessControl(security_origin,
+ params.SetCrossOriginAccessControl(document->GetSecurityOrigin(),
kCrossOriginAttributeAnonymous);
}
@@ -140,11 +138,6 @@ Resource* PreloadRequest::Start(Document* document) {
// the async request to the blocked script here.
}
- if (resource_type_ == ResourceType::kImage &&
- params.Url().ProtocolIsInHTTPFamily() && is_lazy_load_image_enabled_) {
- params.SetLazyImagePlaceholder();
- }
-
return PreloadHelper::StartPreload(resource_type_, params, *document);
}
diff --git a/chromium/third_party/blink/renderer/core/html/parser/preload_request.h b/chromium/third_party/blink/renderer/core/html/parser/preload_request.h
index 761f071fa3f..b33b6e353ca 100644
--- a/chromium/third_party/blink/renderer/core/html/parser/preload_request.h
+++ b/chromium/third_party/blink/renderer/core/html/parser/preload_request.h
@@ -113,13 +113,6 @@ class CORE_EXPORT PreloadRequest {
return is_image_set_ == ResourceFetcher::kImageIsImageSet;
}
- void SetIsLazyLoadImageEnabled(bool is_enabled) {
- is_lazy_load_image_enabled_ = is_enabled;
- }
- bool IsLazyLoadImageEnabledForTesting() {
- return is_lazy_load_image_enabled_;
- }
-
private:
PreloadRequest(const String& initiator_name,
const TextPosition& initiator_position,
diff --git a/chromium/third_party/blink/renderer/core/html/portal/html_portal_element.h b/chromium/third_party/blink/renderer/core/html/portal/html_portal_element.h
index 42fe448d85a..1ec5984927d 100644
--- a/chromium/third_party/blink/renderer/core/html/portal/html_portal_element.h
+++ b/chromium/third_party/blink/renderer/core/html/portal/html_portal_element.h
@@ -63,8 +63,8 @@ class CORE_EXPORT HTMLPortalElement : public HTMLFrameOwnerElement {
const base::UnguessableToken& GetToken() const;
- FrameOwnerElementType OwnerType() const override {
- return FrameOwnerElementType::kPortal;
+ mojom::blink::FrameOwnerElementType OwnerType() const override {
+ return mojom::blink::FrameOwnerElementType::kPortal;
}
// Consumes the portal interface. When a Portal is activated, or if the
diff --git a/chromium/third_party/blink/renderer/core/html/portal/html_portal_element.idl b/chromium/third_party/blink/renderer/core/html/portal/html_portal_element.idl
index 088c7ff25d7..2a0d7a796b8 100644
--- a/chromium/third_party/blink/renderer/core/html/portal/html_portal_element.idl
+++ b/chromium/third_party/blink/renderer/core/html/portal/html_portal_element.idl
@@ -10,7 +10,7 @@ interface HTMLPortalElement : HTMLElement {
[CEReactions, Reflect, ReflectOnly=("","no-referrer","origin","no-referrer-when-downgrade","origin-when-cross-origin","unsafe-url"), ReflectMissing="", ReflectInvalid=""] attribute DOMString referrerPolicy;
[CallWith=ScriptState, RaisesException, Measure] Promise<void> activate(optional PortalActivateOptions options = {});
- [CallWith=ScriptState, RaisesException, Measure] void postMessage(any message, DOMString targetOrigin,
+ [CallWith=ScriptState, RaisesException, Measure] void postMessage(any message, USVString targetOrigin,
optional sequence<object> transfer = []);
[CallWith=ScriptState, RaisesException, Measure] void postMessage(any message, optional WindowPostMessageOptions options = {});
diff --git a/chromium/third_party/blink/renderer/core/html/portal/html_portal_element_test.cc b/chromium/third_party/blink/renderer/core/html/portal/html_portal_element_test.cc
index 7cbf44baa53..c7904de4aaf 100644
--- a/chromium/third_party/blink/renderer/core/html/portal/html_portal_element_test.cc
+++ b/chromium/third_party/blink/renderer/core/html/portal/html_portal_element_test.cc
@@ -4,10 +4,15 @@
#include "third_party/blink/renderer/core/html/portal/html_portal_element.h"
+#include "base/unguessable_token.h"
+#include "mojo/public/cpp/bindings/pending_associated_receiver.h"
+#include "mojo/public/cpp/bindings/pending_associated_remote.h"
+#include "third_party/blink/public/mojom/portal/portal.mojom-blink.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_portal_activate_options.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_window_post_message_options.h"
#include "third_party/blink/renderer/core/dom/document.h"
+#include "third_party/blink/renderer/core/html/portal/portal_activate_event.h"
#include "third_party/blink/renderer/core/html_names.h"
#include "third_party/blink/renderer/core/inspector/console_message.h"
#include "third_party/blink/renderer/core/inspector/console_message_storage.h"
@@ -36,7 +41,8 @@ TEST_F(HTMLPortalElementTest, PortalsDisabledInDocument) {
ScriptState* script_state = ToScriptStateForMainWorld(&GetFrame());
const auto& console_messages = GetPage().GetConsoleMessageStorage();
- portal->activate(script_state, MakeGarbageCollected<PortalActivateOptions>(),
+ portal->activate(script_state,
+ PortalActivateOptions::Create(script_state->GetIsolate()),
exception_state);
EXPECT_TRUE(exception_state.HadException());
EXPECT_EQ(DOMExceptionCode::kNotSupportedError,
@@ -65,6 +71,23 @@ TEST_F(HTMLPortalElementTest, PortalsDisabledInDocument) {
EXPECT_TRUE(console_messages.at(next_console_message)
->Message()
.Contains("was moved to a document"));
+
+ mojo::PendingAssociatedRemote<mojom::blink::Portal> portal_remote;
+ mojo::PendingAssociatedReceiver<mojom::blink::Portal> portal_receiver =
+ portal_remote.InitWithNewEndpointAndPassReceiver();
+
+ mojo::PendingAssociatedRemote<mojom::blink::PortalClient> client_remote;
+ mojo::PendingAssociatedReceiver<mojom::blink::PortalClient> client_receiver =
+ client_remote.InitWithNewEndpointAndPassReceiver();
+
+ auto* activate_event = PortalActivateEvent::Create(
+ &GetFrame(), base::UnguessableToken::Create(), std::move(portal_remote),
+ std::move(client_receiver), nullptr, nullptr, base::NullCallback());
+ activate_event->adoptPredecessor(exception_state);
+ EXPECT_TRUE(exception_state.HadException());
+ EXPECT_EQ(DOMExceptionCode::kNotSupportedError,
+ exception_state.CodeAs<DOMExceptionCode>());
+ exception_state.ClearException();
}
} // namespace
diff --git a/chromium/third_party/blink/renderer/core/html/portal/portal_activate_event.cc b/chromium/third_party/blink/renderer/core/html/portal/portal_activate_event.cc
index 17116bee848..2e685353655 100644
--- a/chromium/third_party/blink/renderer/core/html/portal/portal_activate_event.cc
+++ b/chromium/third_party/blink/renderer/core/html/portal/portal_activate_event.cc
@@ -121,6 +121,13 @@ const AtomicString& PortalActivateEvent::InterfaceName() const {
HTMLPortalElement* PortalActivateEvent::adoptPredecessor(
ExceptionState& exception_state) {
+ if (!RuntimeEnabledFeatures::PortalsEnabled(document_)) {
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kNotSupportedError,
+ "Portals is not enabled in this document.");
+ return nullptr;
+ }
+
if (!predecessor_portal_) {
exception_state.ThrowDOMException(
DOMExceptionCode::kInvalidStateError,
diff --git a/chromium/third_party/blink/renderer/core/html/portal/portal_activate_event_init.idl b/chromium/third_party/blink/renderer/core/html/portal/portal_activate_event_init.idl
index 8aeb9a7f91a..2927f2621d4 100644
--- a/chromium/third_party/blink/renderer/core/html/portal/portal_activate_event_init.idl
+++ b/chromium/third_party/blink/renderer/core/html/portal/portal_activate_event_init.idl
@@ -5,5 +5,5 @@
// https://wicg.github.io/portals/#the-portalactivateevent-interface
dictionary PortalActivateEventInit : EventInit {
- any data;
+ any data = null;
};
diff --git a/chromium/third_party/blink/renderer/core/html/portal/portal_contents.cc b/chromium/third_party/blink/renderer/core/html/portal/portal_contents.cc
index 3c6dba14fce..80f1404bc48 100644
--- a/chromium/third_party/blink/renderer/core/html/portal/portal_contents.cc
+++ b/chromium/third_party/blink/renderer/core/html/portal/portal_contents.cc
@@ -91,7 +91,8 @@ void PortalContents::OnActivateResponse(
bool should_destroy_contents = false;
switch (result) {
case mojom::blink::PortalActivateResult::kPredecessorWasAdopted:
- GetDocument().GetPage()->SetInsidePortal(true);
+ if (!GetDocument().IsContextDestroyed())
+ GetDocument().GetPage()->SetInsidePortal(true);
FALLTHROUGH;
case mojom::blink::PortalActivateResult::kPredecessorWillUnload:
activate_resolver_->Resolve();
@@ -107,6 +108,10 @@ void PortalContents::OnActivateResponse(
reject(DOMExceptionCode::kInvalidStateError,
"The portal was not yet ready or was blocked.");
break;
+ case mojom::blink::PortalActivateResult::kRejectedDueToErrorInPortal:
+ reject(DOMExceptionCode::kInvalidStateError,
+ "The portal is in an error state.");
+ break;
case mojom::blink::PortalActivateResult::kDisconnected:
// Only called when |remote_portal_| is disconnected. This usually happens
// when the browser/test runner is being shut down.
diff --git a/chromium/third_party/blink/renderer/core/html/portal/portal_host.idl b/chromium/third_party/blink/renderer/core/html/portal/portal_host.idl
index 4e2ea0c214c..df5205486cd 100644
--- a/chromium/third_party/blink/renderer/core/html/portal/portal_host.idl
+++ b/chromium/third_party/blink/renderer/core/html/portal/portal_host.idl
@@ -6,7 +6,7 @@
[Exposed=Window, RuntimeEnabled=Portals]
interface PortalHost : EventTarget {
- [RaisesException, CallWith=ScriptState, Measure] void postMessage(any message, DOMString targetOrigin,
+ [RaisesException, CallWith=ScriptState, Measure] void postMessage(any message, USVString targetOrigin,
optional sequence<object> transfer = []);
[RaisesException, CallWith=ScriptState, Measure] void postMessage(any message,
optional WindowPostMessageOptions options = {});
diff --git a/chromium/third_party/blink/renderer/core/html/rel_list.cc b/chromium/third_party/blink/renderer/core/html/rel_list.cc
index 880f90548e4..dc257118aa5 100644
--- a/chromium/third_party/blink/renderer/core/html/rel_list.cc
+++ b/chromium/third_party/blink/renderer/core/html/rel_list.cc
@@ -49,6 +49,11 @@ bool RelList::ValidateTokenValue(const AtomicString& token_value,
token_value == "modulepreload") {
return true;
}
+ if (RuntimeEnabledFeatures::SignedExchangeSubresourcePrefetchEnabled(
+ &GetElement().GetDocument()) &&
+ token_value == "allowed-alt-sxg") {
+ return true;
+ }
} else if ((GetElement().HasTagName(html_names::kATag) ||
GetElement().HasTagName(html_names::kAreaTag)) &&
SupportedTokensAnchorAndArea().Contains(token_value)) {
diff --git a/chromium/third_party/blink/renderer/core/html/resources/android.css b/chromium/third_party/blink/renderer/core/html/resources/android.css
index 82121358290..b6ee01f4569 100644
--- a/chromium/third_party/blink/renderer/core/html/resources/android.css
+++ b/chromium/third_party/blink/renderer/core/html/resources/android.css
@@ -30,6 +30,12 @@
/* These styles override other user-agent styles for Chromium on Android. */
+/* This sheet is appended to html.css before parsing which means the selectors
+ below are in the default html namespace:
+
+ @namespace "http://www.w3.org/1999/xhtml"
+*/
+
input[type="date" i]:disabled,
input[type="datetime-local" i]:disabled,
input[type="month" i]:disabled,
diff --git a/chromium/third_party/blink/renderer/core/html/resources/controls_refresh.css b/chromium/third_party/blink/renderer/core/html/resources/controls_refresh.css
index e90e0993c0b..ccf1422fad5 100644
--- a/chromium/third_party/blink/renderer/core/html/resources/controls_refresh.css
+++ b/chromium/third_party/blink/renderer/core/html/resources/controls_refresh.css
@@ -8,12 +8,31 @@
* using the refreshed controls UI.
*/
+/* This sheet is appended to html.css before parsing which means the selectors
+ below are in the default html namespace:
+
+ @namespace "http://www.w3.org/1999/xhtml"
+*/
+
select,
select:-internal-list-box,
input,
textarea {
- background-color: -internal-light-dark-color(#ffffff, #3B3B3B);
- border-color: -internal-light-dark-color(#767676, #C3C3C3);
+ background-color: -internal-light-dark(#ffffff, #3B3B3B);
+ border-color: -internal-light-dark(#767676, #C3C3C3);
+}
+
+a:-webkit-any-link:focus {
+ outline-offset: 1px;
+}
+
+input:focus, textarea:focus, select:focus {
+ outline-offset: 0;
+}
+
+input[type="checkbox" i]:focus,
+input[type="radio" i]:focus {
+ outline-offset: 2px;
}
input,
@@ -35,7 +54,7 @@ textarea:disabled {
input:disabled,
textarea:disabled {
- background-color: -internal-light-dark-color(rgba(239, 239, 239, 0.3), rgba(59, 59, 59, 0.3));
+ background-color: -internal-light-dark(rgba(239, 239, 239, 0.3), rgba(59, 59, 59, 0.3));
}
select:disabled {
@@ -48,8 +67,8 @@ input[type="reset" i],
input[type="color" i],
input[type="file" i]::-webkit-file-upload-button,
button {
- background-color: -internal-light-dark-color(#efefef, #4A4A4A);
- border-color: -internal-light-dark-color(#767676, #C3C3C3);
+ background-color: -internal-light-dark(#efefef, #4A4A4A);
+ border-color: -internal-light-dark(#767676, #C3C3C3);
}
input[type="button" i]:disabled,
@@ -58,9 +77,9 @@ input[type="reset" i]:disabled,
input[type="color" i]:disabled,
input[type="file" i]:disabled::-webkit-file-upload-button,
button:disabled {
- background-color: -internal-light-dark-color(rgba(239, 239, 239, 0.3), rgba(19, 1, 1, 0.3));
- border-color: -internal-light-dark-color(rgba(118, 118, 118, 0.3), rgba(195, 195, 195, 0.3));
- color: -internal-light-dark-color(rgba(16, 16, 16, 0.3), #aaaaaa);
+ background-color: -internal-light-dark(rgba(239, 239, 239, 0.3), rgba(19, 1, 1, 0.3));
+ border-color: -internal-light-dark(rgba(118, 118, 118, 0.3), rgba(195, 195, 195, 0.3));
+ color: -internal-light-dark(rgba(16, 16, 16, 0.3), #aaaaaa);
}
input[type="password" i]::-internal-reveal {
@@ -100,7 +119,7 @@ meter::-webkit-meter-inner-element:-internal-shadow-host-has-appearance {
}
meter::-webkit-meter-bar {
- background: -internal-light-dark-color(#efefef, #4a4a4a);
+ background: -internal-light-dark(#efefef, #4a4a4a);
border-width: thin;
grid-row-start: line1;
grid-row-end: line2;
@@ -112,15 +131,15 @@ meter::-webkit-meter-bar {
}
meter::-webkit-meter-optimum-value {
- background: -internal-light-dark-color(#107c10, #74b374)
+ background: -internal-light-dark(#107c10, #74b374)
}
meter::-webkit-meter-suboptimum-value {
- background: -internal-light-dark-color(#ffb900, #f2c812)
+ background: -internal-light-dark(#ffb900, #f2c812)
}
meter::-webkit-meter-even-less-good-value {
- background: -internal-light-dark-color(#d83b01, #e98f6d)
+ background: -internal-light-dark(#d83b01, #e98f6d)
}
input[type="date" i]::-webkit-calendar-picker-indicator,
diff --git a/chromium/third_party/blink/renderer/core/html/resources/forced_colors.css b/chromium/third_party/blink/renderer/core/html/resources/forced_colors.css
index c35e7e764aa..8752b6d2fd4 100644
--- a/chromium/third_party/blink/renderer/core/html/resources/forced_colors.css
+++ b/chromium/third_party/blink/renderer/core/html/resources/forced_colors.css
@@ -8,6 +8,12 @@
* is enabled.
*/
+/* This sheet is appended to html.css before parsing which means the selectors
+ below are in the default html namespace:
+
+ @namespace "http://www.w3.org/1999/xhtml"
+*/
+
@media forced-colors {
body {
background-color: Canvas;
@@ -223,4 +229,4 @@
background-color: Window !important;
}
-} \ No newline at end of file
+}
diff --git a/chromium/third_party/blink/renderer/core/html/resources/html.css b/chromium/third_party/blink/renderer/core/html/resources/html.css
index f348bcbcf55..7432e293ea4 100644
--- a/chromium/third_party/blink/renderer/core/html/resources/html.css
+++ b/chromium/third_party/blink/renderer/core/html/resources/html.css
@@ -407,7 +407,7 @@ input, textarea, select, button {
margin: 0__qem;
font: -webkit-small-control;
text-rendering: auto; /* FIXME: Remove when tabs work with optimizeLegibility. */
- color: -internal-light-dark-color(black, white);
+ color: -internal-light-dark(black, white);
letter-spacing: normal;
word-spacing: normal;
line-height: normal;
@@ -425,7 +425,7 @@ input[type="hidden" i] {
input {
-webkit-appearance: textfield; /* AutoAppearanceFor() should match to this. */
padding: 1px;
- background-color: -internal-light-dark-color(white, black);
+ background-color: -internal-light-dark(white, black);
border: 2px inset;
-webkit-rtl-ordering: logical;
cursor: text;
@@ -498,7 +498,7 @@ select {
textarea {
-webkit-appearance: textarea; /* AutoAppearanceFor() should match to this. */
- background-color: -internal-light-dark-color(white, black);
+ background-color: -internal-light-dark(white, black);
border: 1px solid;
-webkit-rtl-ordering: logical;
flex-direction: column;
@@ -575,7 +575,7 @@ select:-internal-autofill-previewed {
-webkit-appearance:menulist-button;
background-color: #E8F0FE !important;
background-image:none !important;
- color: -internal-light-dark-color(black, white) !important;
+ color: -internal-light-dark(black, white) !important;
}
input:-internal-autofill-selected,
@@ -584,7 +584,7 @@ select:-internal-autofill-selected {
-webkit-appearance:menulist-button;
background-color: #E8F0FE !important;
background-image:none !important;
- color: -internal-light-dark-color(black, white) !important;
+ color: -internal-light-dark(black, white) !important;
}
input[type="radio" i], input[type="checkbox" i] {
@@ -614,7 +614,7 @@ input[type="button" i], input[type="submit" i], input[type="reset" i], input[typ
align-items: flex-start;
text-align: center;
cursor: default;
- color: -internal-light-dark-color(ButtonText, #AAAAAA);
+ color: -internal-light-dark(ButtonText, #AAAAAA);
padding: 2px 6px 3px 6px;
border: 2px outset ButtonFace;
background-color: ButtonFace;
@@ -660,7 +660,7 @@ input[type="button" i]:disabled, input[type="submit" i]:disabled, input[type="re
input[type="file" i]:disabled::-webkit-file-upload-button, button:disabled,
select:disabled, optgroup:disabled, option:disabled,
select[disabled]>option {
- color: -internal-light-dark-color(GrayText, #aaa);
+ color: -internal-light-dark(GrayText, #aaa);
}
input[type="button" i]:active, input[type="submit" i]:active, input[type="reset" i]:active, input[type="file" i]:active::-webkit-file-upload-button, button:active {
@@ -672,12 +672,12 @@ input[type="button" i]:active:disabled, input[type="submit" i]:active:disabled,
}
input:disabled, textarea:disabled {
- color: -internal-light-dark-color(#545454, #aaa);
+ color: -internal-light-dark(#545454, #aaa);
cursor: default;
}
option:-internal-spatial-navigation-focus {
- outline: -internal-light-dark-color(black, white) dashed 1px;
+ outline: -internal-light-dark(black, white) dashed 1px;
outline-offset: -1px;
}
@@ -799,8 +799,8 @@ select {
border: 1px solid;
white-space: pre;
-webkit-rtl-ordering: logical;
- color: -internal-light-dark-color(black, white);
- background-color: -internal-light-dark-color(white, black);
+ color: -internal-light-dark(black, white);
+ background-color: -internal-light-dark(white, black);
cursor: default;
}
@@ -1160,8 +1160,8 @@ dialog {
margin: auto;
border: solid;
padding: 1em;
- background: -internal-light-dark-color(white, black);
- color: -internal-light-dark-color(black, white);
+ background: -internal-light-dark(white, black);
+ color: -internal-light-dark(black, white);
}
/* TODO(foolip): In the Fullscreen spec, there's a ::backdrop block with the
diff --git a/chromium/third_party/blink/renderer/core/html/resources/input_multiple_fields.css b/chromium/third_party/blink/renderer/core/html/resources/input_multiple_fields.css
index db849b0d5ff..d0591f61232 100644
--- a/chromium/third_party/blink/renderer/core/html/resources/input_multiple_fields.css
+++ b/chromium/third_party/blink/renderer/core/html/resources/input_multiple_fields.css
@@ -3,6 +3,12 @@
* found in the LICENSE file.
*/
+/* This sheet is appended to html.css before parsing which means the selectors
+ below are in the default html namespace:
+
+ @namespace "http://www.w3.org/1999/xhtml"
+*/
+
input[type="date" i],
input[type="datetime-local" i],
input[type="month" i],
diff --git a/chromium/third_party/blink/renderer/core/html/resources/linux.css b/chromium/third_party/blink/renderer/core/html/resources/linux.css
index f45f6c7678a..847265f2244 100644
--- a/chromium/third_party/blink/renderer/core/html/resources/linux.css
+++ b/chromium/third_party/blink/renderer/core/html/resources/linux.css
@@ -30,6 +30,12 @@
/* These styles override other user-agent styles for Chromium on Linux. */
+/* This sheet is appended to html.css before parsing which means the selectors
+ below are in the default html namespace:
+
+ @namespace "http://www.w3.org/1999/xhtml"
+*/
+
select:not(:-internal-list-box) {
/* Selects with popup menus look like buttons with a drop down triangle on Linux. */
background-color: ButtonFace;
diff --git a/chromium/third_party/blink/renderer/core/html/resources/mac.css b/chromium/third_party/blink/renderer/core/html/resources/mac.css
index e575c8e7ab2..1e1677ba858 100644
--- a/chromium/third_party/blink/renderer/core/html/resources/mac.css
+++ b/chromium/third_party/blink/renderer/core/html/resources/mac.css
@@ -3,6 +3,12 @@
* found in the LICENSE file.
*/
+/* This sheet is appended to html.css before parsing which means the selectors
+ below are in the default html namespace:
+
+ @namespace "http://www.w3.org/1999/xhtml"
+*/
+
select, input[type="color" i][list] {
/* TODO(tkent): Use ButtonFace and border same as buttons. */
background-color: #f8f8f8;
diff --git a/chromium/third_party/blink/renderer/core/html/resources/quirks.css b/chromium/third_party/blink/renderer/core/html/resources/quirks.css
index e880fe0e90f..4e9d8a8ea09 100644
--- a/chromium/third_party/blink/renderer/core/html/resources/quirks.css
+++ b/chromium/third_party/blink/renderer/core/html/resources/quirks.css
@@ -21,6 +21,12 @@
*
*/
+/* This sheet is appended to html.css before parsing which means the selectors
+ below are in the default html namespace:
+
+ @namespace "http://www.w3.org/1999/xhtml"
+*/
+
/* Give floated images margins of 3px */
img[align="left" i] {
margin-right: 3px;
diff --git a/chromium/third_party/blink/renderer/core/html/resources/win.css b/chromium/third_party/blink/renderer/core/html/resources/win.css
index ce9f3120007..8c9c1c3aa62 100644
--- a/chromium/third_party/blink/renderer/core/html/resources/win.css
+++ b/chromium/third_party/blink/renderer/core/html/resources/win.css
@@ -32,6 +32,12 @@
core/html/resources/tml.css. So far we have used this file exclusively
for making our form elements match Firefox's. */
+/* This sheet is appended to html.css before parsing which means the selectors
+ below are in the default html namespace:
+
+ @namespace "http://www.w3.org/1999/xhtml"
+*/
+
/*
* Update padding for all text-like types including unknown types.
* Non-text types have input[type="foo" i] with padding properties in
@@ -60,7 +66,7 @@ input[type="range" i] {
/* Not sure this is the right color. #EBEBE4 is what Firefox uses. */
textarea:disabled,
input:disabled {
- background-color: -internal-light-dark-color(#ebebe4, #2d2d2d);
+ background-color: -internal-light-dark(#ebebe4, #2d2d2d);
}
/* Cancel the above rule set for some input types. */
diff --git a/chromium/third_party/blink/renderer/core/html/resources/win_quirks.css b/chromium/third_party/blink/renderer/core/html/resources/win_quirks.css
index 196d082011d..09e5fbdbdd2 100644
--- a/chromium/third_party/blink/renderer/core/html/resources/win_quirks.css
+++ b/chromium/third_party/blink/renderer/core/html/resources/win_quirks.css
@@ -32,6 +32,12 @@
as defined in core/html/resources/quirks.css. So far we have used this
file exclusively for making our form elements match Firefox's. */
+/* This sheet is appended to html.css before parsing which means the selectors
+ below are in the default html namespace:
+
+ @namespace "http://www.w3.org/1999/xhtml"
+*/
+
textarea {
/* Matches IE's text offsets in quirksmode (causes text to wrap the same as IE). */
padding: 2px 0 0 2px;
diff --git a/chromium/third_party/blink/renderer/core/html/shadow/details_marker_control.cc b/chromium/third_party/blink/renderer/core/html/shadow/details_marker_control.cc
index d61e459cda4..2e54345f6f7 100644
--- a/chromium/third_party/blink/renderer/core/html/shadow/details_marker_control.cc
+++ b/chromium/third_party/blink/renderer/core/html/shadow/details_marker_control.cc
@@ -42,6 +42,7 @@ DetailsMarkerControl::DetailsMarkerControl(Document& document)
LayoutObject* DetailsMarkerControl::CreateLayoutObject(const ComputedStyle&,
LegacyLayout) {
+ UseCounter::Count(GetDocument(), WebFeature::kLegacyLayoutByDetailsMarker);
return new LayoutDetailsMarker(this);
}
diff --git a/chromium/third_party/blink/renderer/core/html/track/text_track_container.cc b/chromium/third_party/blink/renderer/core/html/track/text_track_container.cc
index 50a19852bdf..fccd0224a16 100644
--- a/chromium/third_party/blink/renderer/core/html/track/text_track_container.cc
+++ b/chromium/third_party/blink/renderer/core/html/track/text_track_container.cc
@@ -114,7 +114,8 @@ LayoutObject* TextTrackContainer::CreateLayoutObject(const ComputedStyle&,
void TextTrackContainer::ObserveSizeChanges(Element& element) {
video_size_observer_ = ResizeObserver::Create(
- GetDocument(), MakeGarbageCollected<VideoElementResizeDelegate>(*this));
+ GetDocument().domWindow(),
+ MakeGarbageCollected<VideoElementResizeDelegate>(*this));
video_size_observer_->observe(&element);
}
diff --git a/chromium/third_party/blink/renderer/core/html/track/vtt/vtt_cue.cc b/chromium/third_party/blink/renderer/core/html/track/vtt/vtt_cue.cc
index 80b58be649c..401575bfb08 100644
--- a/chromium/third_party/blink/renderer/core/html/track/vtt/vtt_cue.cc
+++ b/chromium/third_party/blink/renderer/core/html/track/vtt/vtt_cue.cc
@@ -237,6 +237,7 @@ LayoutObject* VTTCueBox::CreateLayoutObject(const ComputedStyle& style,
if (style.GetPosition() == EPosition::kRelative)
return HTMLDivElement::CreateLayoutObject(style, legacy);
+ UseCounter::Count(GetDocument(), WebFeature::kLegacyLayoutByVTTCue);
return new LayoutVTTCue(this, snap_to_lines_position_);
}
@@ -814,7 +815,8 @@ VTTCueBox* VTTCue::GetDisplayTree() {
CreateVTTNodeTree();
cue_background_box_->RemoveChildren();
- cue_background_box_->CloneChildNodesFrom(*vtt_node_tree_);
+ cue_background_box_->CloneChildNodesFrom(*vtt_node_tree_,
+ CloneChildrenFlag::kClone);
if (!region()) {
VTTDisplayParameters display_parameters = CalculateDisplayParameters();
diff --git a/chromium/third_party/blink/renderer/core/html/trust_token_attribute_parsing.cc b/chromium/third_party/blink/renderer/core/html/trust_token_attribute_parsing.cc
index 1143b619bda..0724901f6f1 100644
--- a/chromium/third_party/blink/renderer/core/html/trust_token_attribute_parsing.cc
+++ b/chromium/third_party/blink/renderer/core/html/trust_token_attribute_parsing.cc
@@ -5,7 +5,7 @@
#include "third_party/blink/renderer/core/html/trust_token_attribute_parsing.h"
#include "services/network/public/mojom/trust_tokens.mojom-blink.h"
#include "services/network/public/mojom/trust_tokens.mojom-shared.h"
-#include "third_party/blink/renderer/core/fetch/trust_token.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_trust_token.h"
#include "third_party/blink/renderer/platform/json/json_values.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
diff --git a/chromium/third_party/blink/renderer/core/html/trust_token_attribute_parsing.h b/chromium/third_party/blink/renderer/core/html/trust_token_attribute_parsing.h
index f5a7ab03892..ef19cfaf680 100644
--- a/chromium/third_party/blink/renderer/core/html/trust_token_attribute_parsing.h
+++ b/chromium/third_party/blink/renderer/core/html/trust_token_attribute_parsing.h
@@ -5,6 +5,8 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_HTML_TRUST_TOKEN_ATTRIBUTE_PARSING_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_TRUST_TOKEN_ATTRIBUTE_PARSING_H_
+#include <memory>
+
#include "base/optional.h"
#include "services/network/public/mojom/trust_tokens.mojom-blink-forward.h"
#include "third_party/blink/renderer/core/core_export.h"
diff --git a/chromium/third_party/blink/renderer/core/imagebitmap/image_bitmap.cc b/chromium/third_party/blink/renderer/core/imagebitmap/image_bitmap.cc
index 234ae964ad1..4a4ab8e271a 100644
--- a/chromium/third_party/blink/renderer/core/imagebitmap/image_bitmap.cc
+++ b/chromium/third_party/blink/renderer/core/imagebitmap/image_bitmap.cc
@@ -582,7 +582,6 @@ sk_sp<SkImage> ImageBitmap::GetSkImageFromDecoder(
ImageBitmap::ImageBitmap(ImageElementBase* image,
base::Optional<IntRect> crop_rect,
- Document* document,
const ImageBitmapOptions* options) {
scoped_refptr<Image> input = image->CachedImage()->GetImage();
DCHECK(!input->IsTextureBacked());
@@ -653,7 +652,6 @@ ImageBitmap::ImageBitmap(ImageElementBase* image,
ImageBitmap::ImageBitmap(HTMLVideoElement* video,
base::Optional<IntRect> crop_rect,
- Document* document,
const ImageBitmapOptions* options) {
ParsedOptions parsed_options =
ParseOptions(options, crop_rect, video->BitmapSourceSize());
@@ -923,7 +921,8 @@ void ImageBitmap::ResolvePromiseOnOriginalThread(
ScriptPromiseResolver* resolver,
bool origin_clean,
std::unique_ptr<ParsedOptions> parsed_options,
- sk_sp<SkImage> skia_image) {
+ sk_sp<SkImage> skia_image,
+ const ImageOrientationEnum orientation) {
if (!skia_image) {
resolver->Reject(
ScriptValue(resolver->GetScriptState()->GetIsolate(),
@@ -931,7 +930,8 @@ void ImageBitmap::ResolvePromiseOnOriginalThread(
return;
}
scoped_refptr<StaticBitmapImage> image =
- UnacceleratedStaticBitmapImage::Create(std::move(skia_image));
+ UnacceleratedStaticBitmapImage::Create(std::move(skia_image),
+ orientation);
DCHECK(IsMainThread());
if (!parsed_options->premultiply_alpha) {
image = GetImageWithAlphaDisposition(std::move(image), kUnpremultiplyAlpha);
@@ -958,7 +958,8 @@ void ImageBitmap::RasterizeImageOnBackgroundThread(
sk_sp<PaintRecord> paint_record,
const IntRect& dst_rect,
scoped_refptr<base::SequencedTaskRunner> task_runner,
- WTF::CrossThreadOnceFunction<void(sk_sp<SkImage>)> callback) {
+ WTF::CrossThreadOnceFunction<void(sk_sp<SkImage>,
+ const ImageOrientationEnum)> callback) {
DCHECK(!IsMainThread());
SkImageInfo info =
SkImageInfo::MakeN32Premul(dst_rect.Width(), dst_rect.Height());
@@ -970,12 +971,12 @@ void ImageBitmap::RasterizeImageOnBackgroundThread(
}
PostCrossThreadTask(
*task_runner, FROM_HERE,
- CrossThreadBindOnce(std::move(callback), std::move(skia_image)));
+ CrossThreadBindOnce(std::move(callback), std::move(skia_image),
+ kDefaultImageOrientation));
}
ScriptPromise ImageBitmap::CreateAsync(ImageElementBase* image,
base::Optional<IntRect> crop_rect,
- Document* document,
ScriptState* script_state,
const ImageBitmapOptions* options) {
auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
@@ -1070,15 +1071,17 @@ Vector<uint8_t> ImageBitmap::CopyBitmapData() {
unsigned ImageBitmap::width() const {
if (!image_)
return 0;
- DCHECK_GT(image_->width(), 0);
- return image_->width();
+ IntSize size = image_->SizeRespectingOrientation();
+ DCHECK_GT(size.Width(), 0);
+ return size.Width();
}
unsigned ImageBitmap::height() const {
if (!image_)
return 0;
- DCHECK_GT(image_->height(), 0);
- return image_->height();
+ IntSize size = image_->SizeRespectingOrientation();
+ DCHECK_GT(size.Height(), 0);
+ return size.Height();
}
bool ImageBitmap::IsAccelerated() const {
@@ -1094,7 +1097,6 @@ IntSize ImageBitmap::Size() const {
}
ScriptPromise ImageBitmap::CreateImageBitmap(ScriptState* script_state,
- EventTarget& event_target,
base::Optional<IntRect> crop_rect,
const ImageBitmapOptions* options,
ExceptionState& exception_state) {
diff --git a/chromium/third_party/blink/renderer/core/imagebitmap/image_bitmap.h b/chromium/third_party/blink/renderer/core/imagebitmap/image_bitmap.h
index 67f62c38edc..93f42fea5ab 100644
--- a/chromium/third_party/blink/renderer/core/imagebitmap/image_bitmap.h
+++ b/chromium/third_party/blink/renderer/core/imagebitmap/image_bitmap.h
@@ -23,7 +23,6 @@
#include "third_party/skia/include/core/SkRefCnt.h"
namespace blink {
-class Document;
class HTMLCanvasElement;
class HTMLVideoElement;
class ImageData;
@@ -44,18 +43,15 @@ class CORE_EXPORT ImageBitmap final : public ScriptWrappable,
static ScriptPromise CreateAsync(
ImageElementBase*,
base::Optional<IntRect>,
- Document*,
ScriptState*,
const ImageBitmapOptions* = ImageBitmapOptions::Create());
static sk_sp<SkImage> GetSkImageFromDecoder(std::unique_ptr<ImageDecoder>);
ImageBitmap(ImageElementBase*,
base::Optional<IntRect>,
- Document*,
const ImageBitmapOptions* = ImageBitmapOptions::Create());
ImageBitmap(HTMLVideoElement*,
base::Optional<IntRect>,
- Document*,
const ImageBitmapOptions* = ImageBitmapOptions::Create());
ImageBitmap(HTMLCanvasElement*,
base::Optional<IntRect>,
@@ -120,7 +116,6 @@ class CORE_EXPORT ImageBitmap final : public ScriptWrappable,
// ImageBitmapSource implementation
IntSize BitmapSourceSize() const override { return Size(); }
ScriptPromise CreateImageBitmap(ScriptState*,
- EventTarget&,
base::Optional<IntRect>,
const ImageBitmapOptions*,
ExceptionState&) override;
@@ -145,12 +140,14 @@ class CORE_EXPORT ImageBitmap final : public ScriptWrappable,
static void ResolvePromiseOnOriginalThread(ScriptPromiseResolver*,
bool origin_clean,
std::unique_ptr<ParsedOptions>,
- sk_sp<SkImage>);
+ sk_sp<SkImage>,
+ const ImageOrientationEnum);
static void RasterizeImageOnBackgroundThread(
sk_sp<PaintRecord>,
const IntRect&,
scoped_refptr<base::SequencedTaskRunner>,
- WTF::CrossThreadOnceFunction<void(sk_sp<SkImage>)> callback);
+ WTF::CrossThreadOnceFunction<void(sk_sp<SkImage>,
+ const ImageOrientationEnum)> callback);
scoped_refptr<StaticBitmapImage> image_;
bool is_neutered_ = false;
int32_t memory_usage_ = 0;
diff --git a/chromium/third_party/blink/renderer/core/imagebitmap/image_bitmap_factories.cc b/chromium/third_party/blink/renderer/core/imagebitmap/image_bitmap_factories.cc
index 7e368e714fe..2aa8f6f36e0 100644
--- a/chromium/third_party/blink/renderer/core/imagebitmap/image_bitmap_factories.cc
+++ b/chromium/third_party/blink/renderer/core/imagebitmap/image_bitmap_factories.cc
@@ -127,22 +127,20 @@ static inline ImageBitmapSource* ToImageBitmapSourceInternal(
ScriptPromise ImageBitmapFactories::CreateImageBitmapFromBlob(
ScriptState* script_state,
- EventTarget& event_target,
ImageBitmapSource* bitmap_source,
base::Optional<IntRect> crop_rect,
const ImageBitmapOptions* options) {
- Blob* blob = static_cast<Blob*>(bitmap_source);
+ DCHECK(script_state->ContextIsValid());
+ ImageBitmapFactories& factory = From(*ExecutionContext::From(script_state));
ImageBitmapLoader* loader = ImageBitmapFactories::ImageBitmapLoader::Create(
- From(event_target), crop_rect, options, script_state);
- ScriptPromise promise = loader->Promise();
- From(event_target).AddLoader(loader);
- loader->LoadBlobAsync(blob);
- return promise;
+ factory, crop_rect, options, script_state);
+ factory.AddLoader(loader);
+ loader->LoadBlobAsync(static_cast<Blob*>(bitmap_source));
+ return loader->Promise();
}
ScriptPromise ImageBitmapFactories::CreateImageBitmap(
ScriptState* script_state,
- EventTarget& event_target,
const ImageBitmapSourceUnion& bitmap_source,
const ImageBitmapOptions* options,
ExceptionState& exception_state) {
@@ -152,13 +150,12 @@ ScriptPromise ImageBitmapFactories::CreateImageBitmap(
ToImageBitmapSourceInternal(bitmap_source, options, false);
if (!bitmap_source_internal)
return ScriptPromise();
- return CreateImageBitmap(script_state, event_target, bitmap_source_internal,
+ return CreateImageBitmap(script_state, bitmap_source_internal,
base::Optional<IntRect>(), options, exception_state);
}
ScriptPromise ImageBitmapFactories::CreateImageBitmap(
ScriptState* script_state,
- EventTarget& event_target,
const ImageBitmapSourceUnion& bitmap_source,
int sx,
int sy,
@@ -173,13 +170,12 @@ ScriptPromise ImageBitmapFactories::CreateImageBitmap(
if (!bitmap_source_internal)
return ScriptPromise();
base::Optional<IntRect> crop_rect = IntRect(sx, sy, sw, sh);
- return CreateImageBitmap(script_state, event_target, bitmap_source_internal,
- crop_rect, options, exception_state);
+ return CreateImageBitmap(script_state, bitmap_source_internal, crop_rect,
+ options, exception_state);
}
ScriptPromise ImageBitmapFactories::CreateImageBitmap(
ScriptState* script_state,
- EventTarget& event_target,
ImageBitmapSource* bitmap_source,
base::Optional<IntRect> crop_rect,
const ImageBitmapOptions* options,
@@ -191,8 +187,8 @@ ScriptPromise ImageBitmapFactories::CreateImageBitmap(
}
if (bitmap_source->IsBlob()) {
- return CreateImageBitmapFromBlob(script_state, event_target, bitmap_source,
- crop_rect, options);
+ return CreateImageBitmapFromBlob(script_state, bitmap_source, crop_rect,
+ options);
}
if (bitmap_source->BitmapSourceSize().Width() == 0 ||
@@ -205,27 +201,18 @@ ScriptPromise ImageBitmapFactories::CreateImageBitmap(
return ScriptPromise();
}
- return bitmap_source->CreateImageBitmap(script_state, event_target, crop_rect,
- options, exception_state);
+ return bitmap_source->CreateImageBitmap(script_state, crop_rect, options,
+ exception_state);
}
const char ImageBitmapFactories::kSupplementName[] = "ImageBitmapFactories";
-ImageBitmapFactories& ImageBitmapFactories::From(EventTarget& event_target) {
- if (LocalDOMWindow* window = event_target.ToLocalDOMWindow())
- return FromInternal(*window);
-
- return ImageBitmapFactories::FromInternal(
- *To<WorkerGlobalScope>(event_target.GetExecutionContext()));
-}
-
-template <class GlobalObject>
-ImageBitmapFactories& ImageBitmapFactories::FromInternal(GlobalObject& object) {
+ImageBitmapFactories& ImageBitmapFactories::From(ExecutionContext& context) {
ImageBitmapFactories* supplement =
- Supplement<GlobalObject>::template From<ImageBitmapFactories>(object);
+ Supplement<ExecutionContext>::From<ImageBitmapFactories>(context);
if (!supplement) {
supplement = MakeGarbageCollected<ImageBitmapFactories>();
- Supplement<GlobalObject>::ProvideTo(object, supplement);
+ Supplement<ExecutionContext>::ProvideTo(context, supplement);
}
return *supplement;
}
@@ -241,8 +228,7 @@ void ImageBitmapFactories::DidFinishLoading(ImageBitmapLoader* loader) {
void ImageBitmapFactories::Trace(Visitor* visitor) {
visitor->Trace(pending_loaders_);
- Supplement<LocalDOMWindow>::Trace(visitor);
- Supplement<WorkerGlobalScope>::Trace(visitor);
+ Supplement<ExecutionContext>::Trace(visitor);
}
ImageBitmapFactories::ImageBitmapLoader::ImageBitmapLoader(
@@ -314,7 +300,8 @@ void DecodeImageOnDecoderThread(
ArrayBufferContents contents,
ImageDecoder::AlphaOption alpha_option,
ColorBehavior color_behavior,
- WTF::CrossThreadOnceFunction<void(sk_sp<SkImage>)> result_callback) {
+ WTF::CrossThreadOnceFunction<
+ void(sk_sp<SkImage>, const ImageOrientationEnum)> result_callback) {
const bool data_complete = true;
std::unique_ptr<ImageDecoder> decoder = ImageDecoder::Create(
SegmentReader::CreateFromSkData(
@@ -322,12 +309,14 @@ void DecodeImageOnDecoderThread(
data_complete, alpha_option, ImageDecoder::kDefaultBitDepth,
color_behavior, ImageDecoder::OverrideAllowDecodeToYuv::kDeny);
sk_sp<SkImage> frame;
+ ImageOrientationEnum orientation = kDefaultImageOrientation;
if (decoder) {
+ orientation = decoder->Orientation().Orientation();
frame = ImageBitmap::GetSkImageFromDecoder(std::move(decoder));
}
- PostCrossThreadTask(
- *task_runner, FROM_HERE,
- CrossThreadBindOnce(std::move(result_callback), std::move(frame)));
+ PostCrossThreadTask(*task_runner, FROM_HERE,
+ CrossThreadBindOnce(std::move(result_callback),
+ std::move(frame), orientation));
}
} // namespace
@@ -354,7 +343,8 @@ void ImageBitmapFactories::ImageBitmapLoader::ScheduleAsyncImageBitmapDecoding(
}
void ImageBitmapFactories::ImageBitmapLoader::ResolvePromiseOnOriginalThread(
- sk_sp<SkImage> frame) {
+ sk_sp<SkImage> frame,
+ const ImageOrientationEnum orientation) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (!frame) {
RejectPromise(kUndecodableImageBitmapRejectionReason);
@@ -362,9 +352,9 @@ void ImageBitmapFactories::ImageBitmapLoader::ResolvePromiseOnOriginalThread(
}
DCHECK(frame->width());
DCHECK(frame->height());
-
scoped_refptr<StaticBitmapImage> image =
- UnacceleratedStaticBitmapImage::Create(std::move(frame));
+ UnacceleratedStaticBitmapImage::Create(std::move(frame), orientation);
+
image->SetOriginClean(true);
auto* image_bitmap =
MakeGarbageCollected<ImageBitmap>(image, crop_rect_, options_);
diff --git a/chromium/third_party/blink/renderer/core/imagebitmap/image_bitmap_factories.h b/chromium/third_party/blink/renderer/core/imagebitmap/image_bitmap_factories.h
index 41f6461c7ac..e9dc2d79c5e 100644
--- a/chromium/third_party/blink/renderer/core/imagebitmap/image_bitmap_factories.h
+++ b/chromium/third_party/blink/renderer/core/imagebitmap/image_bitmap_factories.h
@@ -41,9 +41,7 @@
#include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.h"
#include "third_party/blink/renderer/core/fileapi/file_reader_loader.h"
#include "third_party/blink/renderer/core/fileapi/file_reader_loader_client.h"
-#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/window_or_worker_global_scope.h"
-#include "third_party/blink/renderer/core/workers/worker_global_scope.h"
#include "third_party/blink/renderer/platform/bindings/name_client.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"
#include "third_party/blink/renderer/platform/geometry/int_rect.h"
@@ -56,13 +54,12 @@ class SkImage;
namespace blink {
class Blob;
-class EventTarget;
+class ExecutionContext;
class ImageBitmapSource;
class ImageBitmapFactories final
: public GarbageCollected<ImageBitmapFactories>,
- public Supplement<LocalDOMWindow>,
- public Supplement<WorkerGlobalScope>,
+ public Supplement<ExecutionContext>,
public NameClient {
USING_GARBAGE_COLLECTED_MIXIN(ImageBitmapFactories);
@@ -70,12 +67,10 @@ class ImageBitmapFactories final
static const char kSupplementName[];
static ScriptPromise CreateImageBitmap(ScriptState*,
- EventTarget&,
const ImageBitmapSourceUnion&,
const ImageBitmapOptions*,
ExceptionState&);
static ScriptPromise CreateImageBitmap(ScriptState*,
- EventTarget&,
const ImageBitmapSourceUnion&,
int sx,
int sy,
@@ -83,18 +78,6 @@ class ImageBitmapFactories final
int sh,
const ImageBitmapOptions*,
ExceptionState&);
- static ScriptPromise CreateImageBitmap(ScriptState*,
- EventTarget&,
- ImageBitmapSource*,
- base::Optional<IntRect> crop_rect,
- const ImageBitmapOptions*,
- ExceptionState&);
- static ScriptPromise CreateImageBitmapFromBlob(
- ScriptState*,
- EventTarget&,
- ImageBitmapSource*,
- base::Optional<IntRect> crop_rect,
- const ImageBitmapOptions*);
virtual ~ImageBitmapFactories() = default;
@@ -141,7 +124,8 @@ class ImageBitmapFactories final
void RejectPromise(ImageBitmapRejectionReason);
void ScheduleAsyncImageBitmapDecoding(ArrayBufferContents);
- void ResolvePromiseOnOriginalThread(sk_sp<SkImage>);
+ void ResolvePromiseOnOriginalThread(sk_sp<SkImage>,
+ const ImageOrientationEnum);
// ExecutionContextLifecycleObserver
void ContextDestroyed() override;
@@ -159,10 +143,17 @@ class ImageBitmapFactories final
Member<const ImageBitmapOptions> options_;
};
- static ImageBitmapFactories& From(EventTarget&);
-
- template <class GlobalObject>
- static ImageBitmapFactories& FromInternal(GlobalObject&);
+ static ImageBitmapFactories& From(ExecutionContext&);
+ static ScriptPromise CreateImageBitmap(ScriptState*,
+ ImageBitmapSource*,
+ base::Optional<IntRect> crop_rect,
+ const ImageBitmapOptions*,
+ ExceptionState&);
+ static ScriptPromise CreateImageBitmapFromBlob(
+ ScriptState*,
+ ImageBitmapSource*,
+ base::Optional<IntRect> crop_rect,
+ const ImageBitmapOptions*);
void AddLoader(ImageBitmapLoader*);
void DidFinishLoading(ImageBitmapLoader*);
diff --git a/chromium/third_party/blink/renderer/core/imagebitmap/image_bitmap_source.cc b/chromium/third_party/blink/renderer/core/imagebitmap/image_bitmap_source.cc
index b6eba7436a2..e22893130e9 100644
--- a/chromium/third_party/blink/renderer/core/imagebitmap/image_bitmap_source.cc
+++ b/chromium/third_party/blink/renderer/core/imagebitmap/image_bitmap_source.cc
@@ -31,7 +31,6 @@ ScriptPromise ImageBitmapSource::FulfillImageBitmap(
ScriptPromise ImageBitmapSource::CreateImageBitmap(
ScriptState* script_state,
- EventTarget& event_target,
base::Optional<IntRect> crop_rect,
const ImageBitmapOptions* options,
ExceptionState& exception_state) {
diff --git a/chromium/third_party/blink/renderer/core/imagebitmap/image_bitmap_source.h b/chromium/third_party/blink/renderer/core/imagebitmap/image_bitmap_source.h
index 181d47b4e54..fa3d3f5df7d 100644
--- a/chromium/third_party/blink/renderer/core/imagebitmap/image_bitmap_source.h
+++ b/chromium/third_party/blink/renderer/core/imagebitmap/image_bitmap_source.h
@@ -25,7 +25,6 @@ class CORE_EXPORT ImageBitmapSource {
public:
virtual IntSize BitmapSourceSize() const { return IntSize(); }
virtual ScriptPromise CreateImageBitmap(ScriptState*,
- EventTarget&,
base::Optional<IntRect>,
const ImageBitmapOptions*,
ExceptionState&);
diff --git a/chromium/third_party/blink/renderer/core/imagebitmap/image_bitmap_test.cc b/chromium/third_party/blink/renderer/core/imagebitmap/image_bitmap_test.cc
index dcc61cb485f..e087195e860 100644
--- a/chromium/third_party/blink/renderer/core/imagebitmap/image_bitmap_test.cc
+++ b/chromium/third_party/blink/renderer/core/imagebitmap/image_bitmap_test.cc
@@ -121,26 +121,22 @@ TEST_F(ImageBitmapTest, ImageResourceConsistency) {
base::Optional<IntRect> crop_rect =
IntRect(0, 0, image_->width(), image_->height());
auto* image_bitmap_no_crop = MakeGarbageCollected<ImageBitmap>(
- image_element, crop_rect, &(image_element->GetDocument()),
- default_options);
+ image_element, crop_rect, default_options);
ASSERT_TRUE(image_bitmap_no_crop);
crop_rect = IntRect(image_->width() / 2, image_->height() / 2,
image_->width() / 2, image_->height() / 2);
auto* image_bitmap_interior_crop = MakeGarbageCollected<ImageBitmap>(
- image_element, crop_rect, &(image_element->GetDocument()),
- default_options);
+ image_element, crop_rect, default_options);
ASSERT_TRUE(image_bitmap_interior_crop);
crop_rect = IntRect(-image_->width() / 2, -image_->height() / 2,
image_->width(), image_->height());
auto* image_bitmap_exterior_crop = MakeGarbageCollected<ImageBitmap>(
- image_element, crop_rect, &(image_element->GetDocument()),
- default_options);
+ image_element, crop_rect, default_options);
ASSERT_TRUE(image_bitmap_exterior_crop);
crop_rect = IntRect(-image_->width(), -image_->height(), image_->width(),
image_->height());
auto* image_bitmap_outside_crop = MakeGarbageCollected<ImageBitmap>(
- image_element, crop_rect, &(image_element->GetDocument()),
- default_options);
+ image_element, crop_rect, default_options);
ASSERT_TRUE(image_bitmap_outside_crop);
ASSERT_EQ(image_bitmap_no_crop->BitmapImage()
@@ -192,8 +188,8 @@ TEST_F(ImageBitmapTest, ImageBitmapSourceChanged) {
const ImageBitmapOptions* default_options = ImageBitmapOptions::Create();
base::Optional<IntRect> crop_rect =
IntRect(0, 0, image_->width(), image_->height());
- auto* image_bitmap = MakeGarbageCollected<ImageBitmap>(
- image, crop_rect, &(image->GetDocument()), default_options);
+ auto* image_bitmap =
+ MakeGarbageCollected<ImageBitmap>(image, crop_rect, default_options);
ASSERT_TRUE(image_bitmap);
ASSERT_EQ(
image_bitmap->BitmapImage()->PaintImageForCurrentFrame().GetSkImage(),
@@ -345,8 +341,8 @@ TEST_F(ImageBitmapTest, ImageBitmapColorSpaceConversionHTMLImageElement) {
options->setColorSpaceConversion(
ColorCorrectionTestUtils::ColorSpaceConversionToString(
static_cast<ColorSpaceConversion>(conversion_iterator)));
- auto* image_bitmap = MakeGarbageCollected<ImageBitmap>(
- image_element, crop_rect, &(image_element->GetDocument()), options);
+ auto* image_bitmap =
+ MakeGarbageCollected<ImageBitmap>(image_element, crop_rect, options);
ASSERT_TRUE(image_bitmap);
sk_sp<SkImage> converted_image =
image_bitmap->BitmapImage()->PaintImageForCurrentFrame().GetSkImage();
diff --git a/chromium/third_party/blink/renderer/core/input/BUILD.gn b/chromium/third_party/blink/renderer/core/input/BUILD.gn
index 069a846b7cc..72733c9db2a 100644
--- a/chromium/third_party/blink/renderer/core/input/BUILD.gn
+++ b/chromium/third_party/blink/renderer/core/input/BUILD.gn
@@ -14,8 +14,6 @@ blink_core_sources("input") {
"event_handler.h",
"event_handling_util.cc",
"event_handling_util.h",
- "fallback_cursor_event_manager.cc",
- "fallback_cursor_event_manager.h",
"gesture_manager.cc",
"gesture_manager.h",
"input_device_capabilities.cc",
@@ -47,6 +45,6 @@ blink_core_sources("input") {
"//third_party/blink/public:buildflags",
"//third_party/blink/renderer/platform",
"//third_party/blink/renderer/platform/wtf",
- "//ui/base/mojom:cursor_type_blink",
+ "//ui/base/cursor/mojom:cursor_type_blink",
]
}
diff --git a/chromium/third_party/blink/renderer/core/input/event_handler.cc b/chromium/third_party/blink/renderer/core/input/event_handler.cc
index 8ada7d35b31..0ef3d79c15d 100644
--- a/chromium/third_party/blink/renderer/core/input/event_handler.cc
+++ b/chromium/third_party/blink/renderer/core/input/event_handler.cc
@@ -113,7 +113,7 @@
#include "third_party/blink/renderer/platform/wtf/math_extras.h"
#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
#include "third_party/skia/include/core/SkBitmap.h"
-#include "ui/base/mojom/cursor_type.mojom-blink.h"
+#include "ui/base/cursor/mojom/cursor_type.mojom-blink.h"
namespace blink {
@@ -243,13 +243,7 @@ EventHandler::EventHandler(LocalFrame& frame)
*selection_controller_)),
active_interval_timer_(frame.GetTaskRunner(TaskType::kUserInteraction),
this,
- &EventHandler::ActiveIntervalTimerFired) {
- if (RuntimeEnabledFeatures::FallbackCursorModeEnabled() &&
- frame.IsMainFrame()) {
- fallback_cursor_event_manager_ =
- MakeGarbageCollected<FallbackCursorEventManager>(frame);
- }
-}
+ &EventHandler::ActiveIntervalTimerFired) {}
void EventHandler::Trace(Visitor* visitor) {
visitor->Trace(frame_);
@@ -267,7 +261,6 @@ void EventHandler::Trace(Visitor* visitor) {
visitor->Trace(keyboard_event_manager_);
visitor->Trace(pointer_event_manager_);
visitor->Trace(gesture_manager_);
- visitor->Trace(fallback_cursor_event_manager_);
visitor->Trace(last_deferred_tap_element_);
}
@@ -764,14 +757,6 @@ WebInputEventResult EventHandler::HandleMousePressEvent(
frame_->GetDocument()->SetSequentialFocusNavigationStartingPoint(
mev.InnerNode());
- if (RuntimeEnabledFeatures::FallbackCursorModeEnabled()) {
- // TODO(crbug.com/944575) Should support oopif.
- DCHECK(frame_->LocalFrameRoot().IsMainFrame());
- frame_->LocalFrameRoot()
- .GetEventHandler()
- .fallback_cursor_event_manager_->HandleMousePressEvent(mouse_event);
- }
-
LocalFrame* subframe = event_handling_util::GetTargetSubframe(mev);
if (subframe) {
WebInputEventResult result = PassMousePressEventToSubframe(mev, subframe);
@@ -824,8 +809,9 @@ WebInputEventResult EventHandler::HandleMousePressEvent(
frame_->Selection().SetCaretBlinkingSuspended(true);
WebInputEventResult event_result = DispatchMousePointerEvent(
- WebInputEvent::kPointerDown, mev.InnerElement(), mev.CanvasRegionId(),
- mev.Event(), Vector<WebMouseEvent>(), Vector<WebMouseEvent>());
+ WebInputEvent::Type::kPointerDown, mev.InnerElement(),
+ mev.CanvasRegionId(), mev.Event(), Vector<WebMouseEvent>(),
+ Vector<WebMouseEvent>());
// Disabled form controls still need to resize the scrollable area.
if ((event_result == WebInputEventResult::kNotHandled ||
@@ -895,7 +881,7 @@ WebInputEventResult EventHandler::HandleMousePressEvent(
if (mev.GetHitTestResult().InnerNode() &&
mouse_event.button == WebPointerProperties::Button::kLeft) {
- DCHECK_EQ(WebInputEvent::kMouseDown, mouse_event.GetType());
+ DCHECK_EQ(WebInputEvent::Type::kMouseDown, mouse_event.GetType());
HitTestResult result = mev.GetHitTestResult();
result.SetToShadowHostIfInRestrictedShadowRoot();
frame_->GetChromeClient().OnMouseDown(*result.InnerNode());
@@ -909,7 +895,7 @@ WebInputEventResult EventHandler::HandleMouseMoveEvent(
const Vector<WebMouseEvent>& coalesced_events,
const Vector<WebMouseEvent>& predicted_events) {
TRACE_EVENT0("blink", "EventHandler::handleMouseMoveEvent");
- DCHECK(event.GetType() == WebInputEvent::kMouseMove);
+ DCHECK(event.GetType() == WebInputEvent::Type::kMouseMove);
HitTestResult hovered_node_result;
HitTestLocation location;
WebInputEventResult result =
@@ -931,20 +917,12 @@ WebInputEventResult EventHandler::HandleMouseMoveEvent(
page->GetChromeClient().MouseDidMoveOverElement(*frame_, location,
hovered_node_result);
- if (RuntimeEnabledFeatures::FallbackCursorModeEnabled()) {
- // TODO(crbug.com/944575) Should support oopif.
- DCHECK(frame_->LocalFrameRoot().IsMainFrame());
- frame_->LocalFrameRoot()
- .GetEventHandler()
- .fallback_cursor_event_manager_->HandleMouseMoveEvent(event);
- }
-
return result;
}
void EventHandler::HandleMouseLeaveEvent(const WebMouseEvent& event) {
TRACE_EVENT0("blink", "EventHandler::handleMouseLeaveEvent");
- DCHECK(event.GetType() == WebInputEvent::kMouseLeave);
+ DCHECK(event.GetType() == WebInputEvent::Type::kMouseLeave);
Page* page = frame_->GetPage();
if (page)
@@ -962,8 +940,8 @@ WebInputEventResult EventHandler::HandleMouseMoveOrLeaveEvent(
HitTestLocation* hit_test_location) {
DCHECK(frame_);
DCHECK(frame_->View());
- DCHECK(mouse_event.GetType() == WebInputEvent::kMouseMove ||
- mouse_event.GetType() == WebInputEvent::kMouseLeave);
+ DCHECK(mouse_event.GetType() == WebInputEvent::Type::kMouseMove ||
+ mouse_event.GetType() == WebInputEvent::Type::kMouseLeave);
mouse_event_manager_->SetLastKnownMousePosition(mouse_event);
hover_timer_.Stop();
@@ -993,8 +971,8 @@ WebInputEventResult EventHandler::HandleMouseMoveOrLeaveEvent(
if (frame_set_being_resized_) {
return DispatchMousePointerEvent(
- WebInputEvent::kPointerMove, frame_set_being_resized_.Get(), String(),
- mouse_event, coalesced_events, predicted_events);
+ WebInputEvent::Type::kPointerMove, frame_set_being_resized_.Get(),
+ String(), mouse_event, coalesced_events, predicted_events);
}
// Send events right to a scrollbar if the mouse is pressed.
@@ -1012,7 +990,7 @@ WebInputEventResult EventHandler::HandleMouseMoveOrLeaveEvent(
// Treat any mouse move events as readonly if the user is currently touching
// the screen.
if (pointer_event_manager_->IsAnyTouchActive() &&
- mouse_event.GetType() == WebInputEvent::kMouseMove) {
+ mouse_event.GetType() == WebInputEvent::Type::kMouseMove) {
hit_type |= HitTestRequest::kActive | HitTestRequest::kReadOnly;
}
HitTestRequest request(hit_type);
@@ -1024,7 +1002,7 @@ WebInputEventResult EventHandler::HandleMouseMoveOrLeaveEvent(
// might actually be some other frame above this one at the specified
// coordinate. So we avoid the hit test but still clear the hover/active
// state.
- if (mouse_event.GetType() == WebInputEvent::kMouseLeave) {
+ if (mouse_event.GetType() == WebInputEvent::Type::kMouseLeave) {
frame_->GetDocument()->UpdateHoverActiveState(request.Active(),
/*update_active_chain=*/false,
nullptr);
@@ -1064,7 +1042,7 @@ WebInputEventResult EventHandler::HandleMouseMoveOrLeaveEvent(
last_mouse_move_event_subframe_->Tree().IsDescendantOf(frame_) &&
last_mouse_move_event_subframe_ != current_subframe) {
WebMouseEvent event = mev.Event();
- event.SetType(WebInputEvent::kMouseLeave);
+ event.SetType(WebInputEvent::Type::kMouseLeave);
last_mouse_move_event_subframe_->GetEventHandler().HandleMouseLeaveEvent(
event);
last_mouse_move_event_subframe_->GetEventHandler()
@@ -1107,8 +1085,8 @@ WebInputEventResult EventHandler::HandleMouseMoveOrLeaveEvent(
return event_result;
event_result = DispatchMousePointerEvent(
- WebInputEvent::kPointerMove, mev.InnerElement(), mev.CanvasRegionId(),
- mev.Event(), coalesced_events, predicted_events);
+ WebInputEvent::Type::kPointerMove, mev.InnerElement(),
+ mev.CanvasRegionId(), mev.Event(), coalesced_events, predicted_events);
// TODO(crbug.com/346473): Since there is no default action for the mousemove
// event we should consider doing drag&drop even when js cancels the
// mouse move event.
@@ -1168,9 +1146,9 @@ WebInputEventResult EventHandler::HandleMouseReleaseEvent(
ReleaseMouseCaptureFromLocalRoot();
}
return DispatchMousePointerEvent(
- WebInputEvent::kPointerUp, mouse_event_manager_->GetElementUnderMouse(),
- String(), mouse_event, Vector<WebMouseEvent>(),
- Vector<WebMouseEvent>());
+ WebInputEvent::Type::kPointerUp,
+ mouse_event_manager_->GetElementUnderMouse(), String(), mouse_event,
+ Vector<WebMouseEvent>(), Vector<WebMouseEvent>());
}
// Mouse events simulated from touch should not hit-test again.
@@ -1192,8 +1170,9 @@ WebInputEventResult EventHandler::HandleMouseReleaseEvent(
event_result = WebInputEventResult::kHandledSuppressed;
} else {
event_result = DispatchMousePointerEvent(
- WebInputEvent::kPointerUp, mev.InnerElement(), mev.CanvasRegionId(),
- mev.Event(), Vector<WebMouseEvent>(), Vector<WebMouseEvent>(),
+ WebInputEvent::Type::kPointerUp, mev.InnerElement(),
+ mev.CanvasRegionId(), mev.Event(), Vector<WebMouseEvent>(),
+ Vector<WebMouseEvent>(),
(GetSelectionController().HasExtendedSelection() &&
IsSelectionOverLink(mev)));
}
@@ -1576,12 +1555,13 @@ WebInputEventResult EventHandler::HandleGestureEvent(
// etc.
DCHECK(!targeted_event.Event().IsScrollEvent());
- if (targeted_event.Event().GetType() == WebInputEvent::kGestureShowPress)
+ if (targeted_event.Event().GetType() ==
+ WebInputEvent::Type::kGestureShowPress)
last_show_press_timestamp_ = base::TimeTicks::Now();
// Update mouseout/leave/over/enter events before jumping directly to the
// inner most frame.
- if (targeted_event.Event().GetType() == WebInputEvent::kGestureTap)
+ if (targeted_event.Event().GetType() == WebInputEvent::Type::kGestureTap)
UpdateGestureTargetNodeForMouseEvent(targeted_event);
// Route to the correct frame.
@@ -1646,7 +1626,7 @@ bool EventHandler::GestureCorrespondsToAdjustedTouch(
// Gesture events start with a GestureTapDown. If GestureTapDown's unique id
// matches stored adjusted touchstart event id, then we can use the stored
// result for following gesture event.
- if (event.GetType() == WebInputEvent::kGestureTapDown) {
+ if (event.GetType() == WebInputEvent::Type::kGestureTapDown) {
should_use_touch_event_adjusted_point_ =
(event.unique_touch_event_id != 0 &&
event.unique_touch_event_id ==
@@ -1850,7 +1830,7 @@ void EventHandler::UpdateGestureTargetNodeForMouseEvent(
const WebGestureEvent& gesture_event = targeted_event.Event();
unsigned modifiers = gesture_event.GetModifiers();
WebMouseEvent fake_mouse_move(
- WebInputEvent::kMouseMove, gesture_event,
+ WebInputEvent::Type::kMouseMove, gesture_event,
WebPointerProperties::Button::kNoButton,
/* clickCount */ 0,
modifiers | WebInputEvent::Modifiers::kIsCompatibilityEventForTouch,
@@ -1893,7 +1873,7 @@ GestureEventWithHitTestResults EventHandler::TargetGestureEvent(
bool should_keep_active_for_min_interval = false;
if (read_only) {
hit_type |= HitTestRequest::kReadOnly;
- } else if (gesture_event.GetType() == WebInputEvent::kGestureTap &&
+ } else if (gesture_event.GetType() == WebInputEvent::Type::kGestureTap &&
last_show_press_timestamp_) {
// If the Tap is received very shortly after ShowPress, we want to
// delay clearing of the active state so that it's visible to the user
@@ -2005,16 +1985,16 @@ void EventHandler::ApplyTouchAdjustment(WebGestureEvent* gesture_event,
FlooredIntPoint(gesture_event->PositionInRootFrame());
bool adjusted = false;
switch (gesture_event->GetType()) {
- case WebInputEvent::kGestureTap:
- case WebInputEvent::kGestureTapUnconfirmed:
- case WebInputEvent::kGestureTapDown:
- case WebInputEvent::kGestureShowPress:
+ case WebInputEvent::Type::kGestureTap:
+ case WebInputEvent::Type::kGestureTapUnconfirmed:
+ case WebInputEvent::Type::kGestureTapDown:
+ case WebInputEvent::Type::kGestureShowPress:
adjusted = BestClickableNodeForHitTestResult(
location, *hit_test_result, adjusted_point, adjusted_node);
break;
- case WebInputEvent::kGestureLongPress:
- case WebInputEvent::kGestureLongTap:
- case WebInputEvent::kGestureTwoFingerTap:
+ case WebInputEvent::Type::kGestureLongPress:
+ case WebInputEvent::Type::kGestureLongTap:
+ case WebInputEvent::Type::kGestureTwoFingerTap:
adjusted = BestContextMenuNodeForHitTestResult(
location, *hit_test_result, adjusted_point, adjusted_node);
break;
@@ -2179,10 +2159,10 @@ WebInputEventResult EventHandler::ShowNonLocatedContextMenu(
// The contextmenu event is a mouse event even when invoked using the
// keyboard. This is required for web compatibility.
- WebInputEvent::Type event_type = WebInputEvent::kMouseDown;
+ WebInputEvent::Type event_type = WebInputEvent::Type::kMouseDown;
if (frame_->GetSettings() &&
frame_->GetSettings()->GetShowContextMenuOnMouseUp())
- event_type = WebInputEvent::kMouseUp;
+ event_type = WebInputEvent::Type::kMouseUp;
WebMouseEvent mouse_event(
event_type,
@@ -2284,14 +2264,6 @@ void EventHandler::DefaultKeyboardEventHandler(KeyboardEvent* event) {
event, mouse_event_manager_->MousePressNode());
}
-bool EventHandler::HandleFallbackCursorModeBackEvent() {
- DCHECK(RuntimeEnabledFeatures::FallbackCursorModeEnabled());
- // TODO(crbug.com/944575) Should support oopif.
- DCHECK(frame_->LocalFrameRoot().IsMainFrame());
-
- return fallback_cursor_event_manager_->HandleKeyBackEvent();
-}
-
void EventHandler::DragSourceEndedAt(const WebMouseEvent& event,
DragOperation operation) {
// Asides from routing the event to the correct frame, the hit test is also an
@@ -2452,7 +2424,7 @@ MouseEventWithHitTestResults EventHandler::GetMouseEventTarget(
// TODO(eirage): This does not handle chorded buttons yet.
if (RuntimeEnabledFeatures::UnifiedPointerCaptureInBlinkEnabled() &&
- event.GetType() != WebInputEvent::kMouseDown) {
+ event.GetType() != WebInputEvent::Type::kMouseDown) {
HitTestResult result(request, HitTestLocation(document_point));
Element* capture_target;
@@ -2505,11 +2477,4 @@ void EventHandler::ReleaseMouseCaptureFromCurrentFrame() {
capturing_subframe_element_ = nullptr;
}
-void EventHandler::SetIsFallbackCursorModeOn(bool is_on) {
- DCHECK(RuntimeEnabledFeatures::FallbackCursorModeEnabled());
- // TODO(crbug.com/944575) Should support oopif.
- DCHECK(frame_->IsMainFrame());
- fallback_cursor_event_manager_->SetIsFallbackCursorModeOn(is_on);
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/input/event_handler.h b/chromium/third_party/blink/renderer/core/input/event_handler.h
index 887ec3f9f9c..42d4cd476e6 100644
--- a/chromium/third_party/blink/renderer/core/input/event_handler.h
+++ b/chromium/third_party/blink/renderer/core/input/event_handler.h
@@ -35,7 +35,6 @@
#include "third_party/blink/public/platform/web_input_event_result.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/events/text_event_input_type.h"
-#include "third_party/blink/renderer/core/input/fallback_cursor_event_manager.h"
#include "third_party/blink/renderer/core/input/gesture_manager.h"
#include "third_party/blink/renderer/core/input/keyboard_event_manager.h"
#include "third_party/blink/renderer/core/input/mouse_event_manager.h"
@@ -225,7 +224,6 @@ class CORE_EXPORT EventHandler final : public GarbageCollected<EventHandler> {
bool HandleAccessKey(const WebKeyboardEvent&);
WebInputEventResult KeyEvent(const WebKeyboardEvent&);
void DefaultKeyboardEventHandler(KeyboardEvent*);
- bool HandleFallbackCursorModeBackEvent();
bool HandleTextInputEvent(const String& text,
Event* underlying_event = nullptr,
@@ -262,14 +260,14 @@ class CORE_EXPORT EventHandler final : public GarbageCollected<EventHandler> {
void MarkHoverStateDirty();
- void SetIsFallbackCursorModeOn(bool is_on);
-
// Reset the last mouse position so that movement after unlock will be
// restart from the lock position.
void ResetMousePositionForPointerUnlock();
bool LongTapShouldInvokeContextMenu();
+ void UpdateCursor();
+
private:
WebInputEventResult HandleMouseMoveOrLeaveEvent(
const WebMouseEvent&,
@@ -303,8 +301,6 @@ class CORE_EXPORT EventHandler final : public GarbageCollected<EventHandler> {
void CursorUpdateTimerFired(TimerBase*);
void ActiveIntervalTimerFired(TimerBase*);
- void UpdateCursor();
-
ScrollableArea* AssociatedScrollableArea(const PaintLayer*) const;
Element* EffectiveMouseEventTargetElement(Element*);
@@ -404,7 +400,6 @@ class CORE_EXPORT EventHandler final : public GarbageCollected<EventHandler> {
Member<KeyboardEventManager> keyboard_event_manager_;
Member<PointerEventManager> pointer_event_manager_;
Member<GestureManager> gesture_manager_;
- Member<FallbackCursorEventManager> fallback_cursor_event_manager_;
double max_mouse_moved_duration_;
@@ -459,13 +454,6 @@ class CORE_EXPORT EventHandler final : public GarbageCollected<EventHandler> {
CursorForInlineVerticalWritingMode);
FRIEND_TEST_ALL_PREFIXES(EventHandlerTest, CursorForBlockVerticalWritingMode);
- FRIEND_TEST_ALL_PREFIXES(FallbackCursorEventManagerTest,
- MouseMoveCursorLockOnDiv);
- FRIEND_TEST_ALL_PREFIXES(FallbackCursorEventManagerTest,
- MouseMoveCursorLockOnIFrame);
- FRIEND_TEST_ALL_PREFIXES(FallbackCursorEventManagerTest, KeyBackAndMouseMove);
- FRIEND_TEST_ALL_PREFIXES(FallbackCursorEventManagerTest, MouseDownOnEditor);
-
DISALLOW_COPY_AND_ASSIGN(EventHandler);
};
diff --git a/chromium/third_party/blink/renderer/core/input/event_handler_test.cc b/chromium/third_party/blink/renderer/core/input/event_handler_test.cc
index cca36d91ef5..84ebb36b142 100644
--- a/chromium/third_party/blink/renderer/core/input/event_handler_test.cc
+++ b/chromium/third_party/blink/renderer/core/input/event_handler_test.cc
@@ -13,6 +13,7 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/features.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/mojom/input/focus_type.mojom-blink.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/range.h"
@@ -28,6 +29,8 @@
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
#include "third_party/blink/renderer/core/frame/settings.h"
#include "third_party/blink/renderer/core/frame/visual_viewport.h"
+#include "third_party/blink/renderer/core/frame/web_frame_widget_base.h"
+#include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
#include "third_party/blink/renderer/core/html/canvas/html_canvas_element.h"
#include "third_party/blink/renderer/core/html/forms/html_input_element.h"
#include "third_party/blink/renderer/core/html/html_iframe_element.h"
@@ -48,7 +51,7 @@
#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
#include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
#include "ui/base/cursor/cursor.h"
-#include "ui/base/mojom/cursor_type.mojom-blink.h"
+#include "ui/base/cursor/mojom/cursor_type.mojom-blink.h"
#include "ui/events/keycodes/dom/dom_code.h"
#include "ui/events/keycodes/dom/dom_key.h"
@@ -64,8 +67,8 @@ class EventHandlerTest : public PageTestBase {
class EventHandlerSimTest : public SimTest {
public:
void InitializeMousePositionAndActivateView(float x, float y) {
- WebMouseEvent mouse_move_event(WebMouseEvent::kMouseMove, gfx::PointF(x, y),
- gfx::PointF(x, y),
+ WebMouseEvent mouse_move_event(WebMouseEvent::Type::kMouseMove,
+ gfx::PointF(x, y), gfx::PointF(x, y),
WebPointerProperties::Button::kNoButton, 0,
WebInputEvent::Modifiers::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests());
@@ -81,7 +84,7 @@ class EventHandlerSimTest : public SimTest {
float delta_x,
float delta_y) {
WebGestureEvent gesture_scroll_begin{
- WebInputEvent::kGestureScrollBegin, WebInputEvent::kNoModifiers,
+ WebInputEvent::Type::kGestureScrollBegin, WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests()};
gesture_scroll_begin.SetFrameScale(1);
gesture_scroll_begin.data.scroll_begin.delta_x_hint = 0;
@@ -89,30 +92,30 @@ class EventHandlerSimTest : public SimTest {
gesture_scroll_begin.data.scroll_begin.scrollable_area_element_id =
element_id;
WebView().MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(gesture_scroll_begin));
+ WebCoalescedInputEvent(gesture_scroll_begin, ui::LatencyInfo()));
WebGestureEvent gesture_scroll_update{
- WebInputEvent::kGestureScrollUpdate, WebInputEvent::kNoModifiers,
+ WebInputEvent::Type::kGestureScrollUpdate, WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests()};
gesture_scroll_update.SetFrameScale(1);
gesture_scroll_update.data.scroll_update.delta_x = delta_x;
gesture_scroll_update.data.scroll_update.delta_y = -delta_y;
WebView().MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(gesture_scroll_update));
+ WebCoalescedInputEvent(gesture_scroll_update, ui::LatencyInfo()));
WebGestureEvent gesture_scroll_end{
- WebInputEvent::kGestureScrollEnd, WebInputEvent::kNoModifiers,
+ WebInputEvent::Type::kGestureScrollEnd, WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests()};
gesture_scroll_end.SetFrameScale(1);
WebView().MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(gesture_scroll_end));
+ WebCoalescedInputEvent(gesture_scroll_end, ui::LatencyInfo()));
}
};
class TapEventBuilder : public WebGestureEvent {
public:
TapEventBuilder(FloatPoint position, int tap_count)
- : WebGestureEvent(WebInputEvent::kGestureTap,
+ : WebGestureEvent(WebInputEvent::Type::kGestureTap,
WebInputEvent::kNoModifiers,
base::TimeTicks::Now(),
WebGestureDevice::kTouchscreen) {
@@ -128,7 +131,7 @@ class TapEventBuilder : public WebGestureEvent {
class TapDownEventBuilder : public WebGestureEvent {
public:
TapDownEventBuilder(FloatPoint position)
- : WebGestureEvent(WebInputEvent::kGestureTapDown,
+ : WebGestureEvent(WebInputEvent::Type::kGestureTapDown,
WebInputEvent::kNoModifiers,
base::TimeTicks::Now(),
WebGestureDevice::kTouchscreen) {
@@ -143,7 +146,7 @@ class TapDownEventBuilder : public WebGestureEvent {
class ShowPressEventBuilder : public WebGestureEvent {
public:
ShowPressEventBuilder(FloatPoint position)
- : WebGestureEvent(WebInputEvent::kGestureShowPress,
+ : WebGestureEvent(WebInputEvent::Type::kGestureShowPress,
WebInputEvent::kNoModifiers,
base::TimeTicks::Now(),
WebGestureDevice::kTouchscreen) {
@@ -158,7 +161,7 @@ class ShowPressEventBuilder : public WebGestureEvent {
class LongPressEventBuilder : public WebGestureEvent {
public:
LongPressEventBuilder(FloatPoint position)
- : WebGestureEvent(WebInputEvent::kGestureLongPress,
+ : WebGestureEvent(WebInputEvent::Type::kGestureLongPress,
WebInputEvent::kNoModifiers,
base::TimeTicks::Now(),
WebGestureDevice::kTouchscreen) {
@@ -175,7 +178,7 @@ class MousePressEventBuilder : public WebMouseEvent {
MousePressEventBuilder(IntPoint position_param,
int click_count_param,
WebMouseEvent::Button button_param)
- : WebMouseEvent(WebInputEvent::kMouseDown,
+ : WebMouseEvent(WebInputEvent::Type::kMouseDown,
WebInputEvent::kNoModifiers,
base::TimeTicks::Now()) {
click_count = click_count_param;
@@ -222,8 +225,8 @@ TEST_F(EventHandlerTest, dragSelectionAfterScroll) {
frame_view->LayoutViewport()->SetScrollOffset(
ScrollOffset(0, 400), mojom::blink::ScrollType::kProgrammatic);
- WebMouseEvent mouse_down_event(WebInputEvent::kMouseDown, gfx::PointF(0, 0),
- gfx::PointF(100, 200),
+ WebMouseEvent mouse_down_event(WebInputEvent::Type::kMouseDown,
+ gfx::PointF(0, 0), gfx::PointF(100, 200),
WebPointerProperties::Button::kLeft, 1,
WebInputEvent::Modifiers::kLeftButtonDown,
WebInputEvent::GetStaticTimeStampForTests());
@@ -237,7 +240,7 @@ TEST_F(EventHandlerTest, dragSelectionAfterScroll) {
.GetSelectionController()
.MouseDownMayStartSelect());
- WebMouseEvent mouse_move_event(WebInputEvent::kMouseMove,
+ WebMouseEvent mouse_move_event(WebInputEvent::Type::kMouseMove,
gfx::PointF(100, 50), gfx::PointF(200, 250),
WebPointerProperties::Button::kLeft, 1,
WebInputEvent::Modifiers::kLeftButtonDown,
@@ -250,9 +253,9 @@ TEST_F(EventHandlerTest, dragSelectionAfterScroll) {
GetPage().Animator().ServiceScriptedAnimations(base::TimeTicks::Now());
WebMouseEvent mouse_up_event(
- WebMouseEvent::kMouseUp, gfx::PointF(100, 50), gfx::PointF(200, 250),
- WebPointerProperties::Button::kLeft, 1, WebInputEvent::kNoModifiers,
- WebInputEvent::GetStaticTimeStampForTests());
+ WebMouseEvent::Type::kMouseUp, gfx::PointF(100, 50),
+ gfx::PointF(200, 250), WebPointerProperties::Button::kLeft, 1,
+ WebInputEvent::kNoModifiers, WebInputEvent::GetStaticTimeStampForTests());
mouse_up_event.SetFrameScale(1);
GetDocument().GetFrame()->GetEventHandler().HandleMouseReleaseEvent(
mouse_up_event);
@@ -351,7 +354,7 @@ TEST_F(EventHandlerTest, draggedInlinePositionTest) {
"<div style='width: 300px; height: 100px;'>"
"<span class='line' draggable='true'>abcd</span>"
"</div>");
- WebMouseEvent mouse_down_event(WebMouseEvent::kMouseDown,
+ WebMouseEvent mouse_down_event(WebMouseEvent::Type::kMouseDown,
gfx::PointF(262, 29), gfx::PointF(329, 67),
WebPointerProperties::Button::kLeft, 1,
WebInputEvent::Modifiers::kLeftButtonDown,
@@ -360,7 +363,7 @@ TEST_F(EventHandlerTest, draggedInlinePositionTest) {
GetDocument().GetFrame()->GetEventHandler().HandleMousePressEvent(
mouse_down_event);
- WebMouseEvent mouse_move_event(WebMouseEvent::kMouseMove,
+ WebMouseEvent mouse_move_event(WebMouseEvent::Type::kMouseMove,
gfx::PointF(618, 298), gfx::PointF(685, 436),
WebPointerProperties::Button::kLeft, 1,
WebInputEvent::Modifiers::kLeftButtonDown,
@@ -389,7 +392,7 @@ TEST_F(EventHandlerTest, draggedSVGImagePositionTest) {
"draggable='true'/>"
"</svg>"
"</div>");
- WebMouseEvent mouse_down_event(WebMouseEvent::kMouseDown,
+ WebMouseEvent mouse_down_event(WebMouseEvent::Type::kMouseDown,
gfx::PointF(145, 144), gfx::PointF(212, 282),
WebPointerProperties::Button::kLeft, 1,
WebInputEvent::Modifiers::kLeftButtonDown,
@@ -398,7 +401,7 @@ TEST_F(EventHandlerTest, draggedSVGImagePositionTest) {
GetDocument().GetFrame()->GetEventHandler().HandleMousePressEvent(
mouse_down_event);
- WebMouseEvent mouse_move_event(WebMouseEvent::kMouseMove,
+ WebMouseEvent mouse_move_event(WebMouseEvent::Type::kMouseMove,
gfx::PointF(618, 298), gfx::PointF(685, 436),
WebPointerProperties::Button::kLeft, 1,
WebInputEvent::Modifiers::kLeftButtonDown,
@@ -788,7 +791,8 @@ TEST_F(EventHandlerTest, implicitSend) {
SetHtmlInnerHTML("<button>abc</button>");
GetDocument().GetSettings()->SetSpatialNavigationEnabled(true);
- WebKeyboardEvent e{WebInputEvent::kRawKeyDown, WebInputEvent::kNoModifiers,
+ WebKeyboardEvent e{WebInputEvent::Type::kRawKeyDown,
+ WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests()};
e.dom_code = static_cast<int>(ui::DomCode::ARROW_DOWN);
e.dom_key = ui::DomKey::ARROW_DOWN;
@@ -818,7 +822,7 @@ TEST_F(EventHandlerTest, sendContextMenuEventWithHover) {
.Collapse(Position(GetDocument().body(), 0))
.Build());
WebMouseEvent mouse_down_event(
- WebMouseEvent::kMouseDown, gfx::PointF(0, 0), gfx::PointF(100, 200),
+ WebMouseEvent::Type::kMouseDown, gfx::PointF(0, 0), gfx::PointF(100, 200),
WebPointerProperties::Button::kRight, 1,
WebInputEvent::Modifiers::kRightButtonDown, base::TimeTicks::Now());
mouse_down_event.SetFrameScale(1);
@@ -975,7 +979,7 @@ TEST_F(EventHandlerTest, dragEndInNewDrag) {
"<a class='box' href=''>Drag me</a>");
WebMouseEvent mouse_down_event(
- WebInputEvent::kMouseDown, gfx::PointF(50, 50), gfx::PointF(50, 50),
+ WebInputEvent::Type::kMouseDown, gfx::PointF(50, 50), gfx::PointF(50, 50),
WebPointerProperties::Button::kLeft, 1,
WebInputEvent::Modifiers::kLeftButtonDown, base::TimeTicks::Now());
mouse_down_event.SetFrameScale(1);
@@ -983,7 +987,7 @@ TEST_F(EventHandlerTest, dragEndInNewDrag) {
mouse_down_event);
WebMouseEvent mouse_move_event(
- WebInputEvent::kMouseMove, gfx::PointF(51, 50), gfx::PointF(51, 50),
+ WebInputEvent::Type::kMouseMove, gfx::PointF(51, 50), gfx::PointF(51, 50),
WebPointerProperties::Button::kLeft, 1,
WebInputEvent::Modifiers::kLeftButtonDown, base::TimeTicks::Now());
mouse_move_event.SetFrameScale(1);
@@ -997,9 +1001,9 @@ TEST_F(EventHandlerTest, dragEndInNewDrag) {
// dragSourceEndedAt() call could occur before a drag operation is started.
WebMouseEvent mouse_up_event(
- WebInputEvent::kMouseUp, gfx::PointF(100, 50), gfx::PointF(200, 250),
- WebPointerProperties::Button::kLeft, 1, WebInputEvent::kNoModifiers,
- base::TimeTicks::Now());
+ WebInputEvent::Type::kMouseUp, gfx::PointF(100, 50),
+ gfx::PointF(200, 250), WebPointerProperties::Button::kLeft, 1,
+ WebInputEvent::kNoModifiers, base::TimeTicks::Now());
mouse_up_event.SetFrameScale(1);
GetDocument().GetFrame()->GetEventHandler().DragSourceEndedAt(
mouse_up_event, kDragOperationNone);
@@ -1019,7 +1023,7 @@ TEST_F(EventHandlerTest, FakeMouseMoveNotStartDrag) {
"<div style='width: 300px; height: 100px;'>"
"<span class='line' draggable='true'>abcd</span>"
"</div>");
- WebMouseEvent mouse_down_event(WebMouseEvent::kMouseDown,
+ WebMouseEvent mouse_down_event(WebMouseEvent::Type::kMouseDown,
gfx::PointF(262, 29), gfx::PointF(329, 67),
WebPointerProperties::Button::kLeft, 1,
WebInputEvent::Modifiers::kLeftButtonDown,
@@ -1029,8 +1033,8 @@ TEST_F(EventHandlerTest, FakeMouseMoveNotStartDrag) {
mouse_down_event);
WebMouseEvent fake_mouse_move(
- WebMouseEvent::kMouseMove, gfx::PointF(618, 298), gfx::PointF(685, 436),
- WebPointerProperties::Button::kLeft, 1,
+ WebMouseEvent::Type::kMouseMove, gfx::PointF(618, 298),
+ gfx::PointF(685, 436), WebPointerProperties::Button::kLeft, 1,
WebInputEvent::Modifiers::kLeftButtonDown |
WebInputEvent::Modifiers::kRelativeMotionEvent,
WebInputEvent::GetStaticTimeStampForTests());
@@ -1087,7 +1091,7 @@ TEST_F(EventHandlerTooltipTest, mouseLeaveClearsTooltip) {
EXPECT_EQ(WTF::String(), LastToolTip());
WebMouseEvent mouse_move_event(
- WebInputEvent::kMouseMove, gfx::PointF(51, 50), gfx::PointF(51, 50),
+ WebInputEvent::Type::kMouseMove, gfx::PointF(51, 50), gfx::PointF(51, 50),
WebPointerProperties::Button::kNoButton, 0, WebInputEvent::kNoModifiers,
base::TimeTicks::Now());
mouse_move_event.SetFrameScale(1);
@@ -1097,7 +1101,7 @@ TEST_F(EventHandlerTooltipTest, mouseLeaveClearsTooltip) {
EXPECT_EQ("tooltip", LastToolTip());
WebMouseEvent mouse_leave_event(
- WebInputEvent::kMouseLeave, gfx::PointF(0, 0), gfx::PointF(0, 0),
+ WebInputEvent::Type::kMouseLeave, gfx::PointF(0, 0), gfx::PointF(0, 0),
WebPointerProperties::Button::kNoButton, 0, WebInputEvent::kNoModifiers,
base::TimeTicks::Now());
mouse_leave_event.SetFrameScale(1);
@@ -1156,7 +1160,7 @@ TEST_F(EventHandlerLatencyTest, NeedsUnbufferedInput) {
ASSERT_FALSE(chrome_client_->ReceivedRequestForUnbufferedInput());
WebMouseEvent mouse_press_event(
- WebInputEvent::kMouseDown, gfx::PointF(51, 50), gfx::PointF(51, 50),
+ WebInputEvent::Type::kMouseDown, gfx::PointF(51, 50), gfx::PointF(51, 50),
WebPointerProperties::Button::kLeft, 0, WebInputEvent::kNoModifiers,
base::TimeTicks::Now());
mouse_press_event.SetFrameScale(1);
@@ -1200,8 +1204,8 @@ TEST_F(EventHandlerSimTest, MouseUpOffScrollbarGeneratesScrollEnd) {
GetDocument().GetPage()->GetScrollbarTheme().AllowsHitTest();
const gfx::PointF scrollbar_forward_track(795, 560);
- WebMouseEvent mouse_down(WebInputEvent::kMouseDown, scrollbar_forward_track,
- scrollbar_forward_track,
+ WebMouseEvent mouse_down(WebInputEvent::Type::kMouseDown,
+ scrollbar_forward_track, scrollbar_forward_track,
WebPointerProperties::Button::kLeft, 0,
WebInputEvent::kNoModifiers, base::TimeTicks::Now());
mouse_down.SetFrameScale(1);
@@ -1211,15 +1215,15 @@ TEST_F(EventHandlerSimTest, MouseUpOffScrollbarGeneratesScrollEnd) {
if (scrollbar_theme_allows_hit_test) {
EXPECT_EQ(WebWidgetClient().GetInjectedScrollGestureData().size(), 2u);
EXPECT_EQ(WebWidgetClient().GetInjectedScrollGestureData()[0].type,
- WebInputEvent::kGestureScrollBegin);
+ WebInputEvent::Type::kGestureScrollBegin);
EXPECT_EQ(WebWidgetClient().GetInjectedScrollGestureData()[1].type,
- WebInputEvent::kGestureScrollUpdate);
+ WebInputEvent::Type::kGestureScrollUpdate);
} else {
EXPECT_EQ(WebWidgetClient().GetInjectedScrollGestureData().size(), 0u);
}
const gfx::PointF middle_of_page(100, 100);
- WebMouseEvent mouse_move(WebInputEvent::kMouseMove, middle_of_page,
+ WebMouseEvent mouse_move(WebInputEvent::Type::kMouseMove, middle_of_page,
middle_of_page, WebPointerProperties::Button::kLeft,
0, WebInputEvent::kNoModifiers,
base::TimeTicks::Now());
@@ -1234,7 +1238,7 @@ TEST_F(EventHandlerSimTest, MouseUpOffScrollbarGeneratesScrollEnd) {
EXPECT_EQ(WebWidgetClient().GetInjectedScrollGestureData().size(), 0u);
}
- WebMouseEvent mouse_up(WebInputEvent::kMouseUp, middle_of_page,
+ WebMouseEvent mouse_up(WebInputEvent::Type::kMouseUp, middle_of_page,
middle_of_page, WebPointerProperties::Button::kLeft, 0,
WebInputEvent::kNoModifiers, base::TimeTicks::Now());
mouse_up.SetFrameScale(1);
@@ -1244,7 +1248,7 @@ TEST_F(EventHandlerSimTest, MouseUpOffScrollbarGeneratesScrollEnd) {
if (scrollbar_theme_allows_hit_test) {
EXPECT_EQ(WebWidgetClient().GetInjectedScrollGestureData().size(), 3u);
EXPECT_EQ(WebWidgetClient().GetInjectedScrollGestureData()[2].type,
- WebInputEvent::kGestureScrollEnd);
+ WebInputEvent::Type::kGestureScrollEnd);
} else {
EXPECT_EQ(WebWidgetClient().GetInjectedScrollGestureData().size(), 0u);
}
@@ -1269,7 +1273,7 @@ TEST_F(EventHandlerSimTest, MouseUpOnlyOnScrollbar) {
// injected).
const gfx::PointF middle_of_page(100, 100);
- WebMouseEvent mouse_down(WebInputEvent::kMouseDown, middle_of_page,
+ WebMouseEvent mouse_down(WebInputEvent::Type::kMouseDown, middle_of_page,
middle_of_page, WebPointerProperties::Button::kLeft,
0, WebInputEvent::kNoModifiers,
base::TimeTicks::Now());
@@ -1280,8 +1284,8 @@ TEST_F(EventHandlerSimTest, MouseUpOnlyOnScrollbar) {
EXPECT_EQ(WebWidgetClient().GetInjectedScrollGestureData().size(), 0u);
const gfx::PointF scrollbar_forward_track(795, 560);
- WebMouseEvent mouse_move(WebInputEvent::kMouseMove, scrollbar_forward_track,
- scrollbar_forward_track,
+ WebMouseEvent mouse_move(WebInputEvent::Type::kMouseMove,
+ scrollbar_forward_track, scrollbar_forward_track,
WebPointerProperties::Button::kLeft, 0,
WebInputEvent::kNoModifiers, base::TimeTicks::Now());
mouse_move.SetFrameScale(1);
@@ -1291,7 +1295,7 @@ TEST_F(EventHandlerSimTest, MouseUpOnlyOnScrollbar) {
// Mouse move should not have generated any gestures.
EXPECT_EQ(WebWidgetClient().GetInjectedScrollGestureData().size(), 0u);
- WebMouseEvent mouse_up(WebInputEvent::kMouseUp, scrollbar_forward_track,
+ WebMouseEvent mouse_up(WebInputEvent::Type::kMouseUp, scrollbar_forward_track,
scrollbar_forward_track,
WebPointerProperties::Button::kLeft, 0,
WebInputEvent::kNoModifiers, base::TimeTicks::Now());
@@ -1321,8 +1325,8 @@ TEST_F(EventHandlerSimTest, RightClickNoGestures) {
// queued up (right click doesn't scroll scrollbars).
const gfx::PointF scrollbar_forward_track(795, 560);
- WebMouseEvent mouse_down(WebInputEvent::kMouseDown, scrollbar_forward_track,
- scrollbar_forward_track,
+ WebMouseEvent mouse_down(WebInputEvent::Type::kMouseDown,
+ scrollbar_forward_track, scrollbar_forward_track,
WebPointerProperties::Button::kRight, 0,
WebInputEvent::kNoModifiers, base::TimeTicks::Now());
mouse_down.SetFrameScale(1);
@@ -1330,7 +1334,7 @@ TEST_F(EventHandlerSimTest, RightClickNoGestures) {
EXPECT_EQ(WebWidgetClient().GetInjectedScrollGestureData().size(), 0u);
- WebMouseEvent mouse_up(WebInputEvent::kMouseUp, scrollbar_forward_track,
+ WebMouseEvent mouse_up(WebInputEvent::Type::kMouseUp, scrollbar_forward_track,
scrollbar_forward_track,
WebPointerProperties::Button::kRight, 0,
WebInputEvent::kNoModifiers, base::TimeTicks::Now());
@@ -1416,7 +1420,7 @@ TEST_F(EventHandlerSimTest, MAYBE_GestureTapWithScrollSnaps) {
EXPECT_EQ(gse_data.type, WebInputEvent::Type::kGestureScrollEnd);
// Inject the gesture sequence based on the injected data.
- WebGestureEvent gsb{WebInputEvent::kGestureScrollBegin,
+ WebGestureEvent gsb{WebInputEvent::Type::kGestureScrollBegin,
WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests()};
gsb.SetFrameScale(1);
@@ -1426,7 +1430,7 @@ TEST_F(EventHandlerSimTest, MAYBE_GestureTapWithScrollSnaps) {
gsb.data.scroll_begin.scrollable_area_element_id =
gsb_data.scrollable_area_element_id.GetStableId();
GetDocument().GetFrame()->GetEventHandler().HandleGestureEvent(gsb);
- WebGestureEvent gsu{WebInputEvent::kGestureScrollUpdate,
+ WebGestureEvent gsu{WebInputEvent::Type::kGestureScrollUpdate,
WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests()};
gsu.SetSourceDevice(WebGestureDevice::kScrollbar);
@@ -1435,7 +1439,7 @@ TEST_F(EventHandlerSimTest, MAYBE_GestureTapWithScrollSnaps) {
gsu.data.scroll_update.delta_y = -gsu_data.delta.y();
gsu.data.scroll_update.delta_units = gsu_data.granularity;
GetDocument().GetFrame()->GetEventHandler().HandleGestureEvent(gsu);
- WebGestureEvent gse{WebInputEvent::kGestureScrollEnd,
+ WebGestureEvent gse{WebInputEvent::Type::kGestureScrollEnd,
WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests()};
gse.SetSourceDevice(WebGestureDevice::kScrollbar);
@@ -1471,7 +1475,7 @@ TEST_F(EventHandlerSimTest, MAYBE_GestureTapWithScrollSnaps) {
// Test that leaving a window leaves mouse position unknown.
TEST_F(EventHandlerTest, MouseLeaveResetsUnknownState) {
SetHtmlInnerHTML("<div></div>");
- WebMouseEvent mouse_down_event(WebMouseEvent::kMouseDown,
+ WebMouseEvent mouse_down_event(WebMouseEvent::Type::kMouseDown,
gfx::PointF(262, 29), gfx::PointF(329, 67),
WebPointerProperties::Button::kLeft, 1,
WebInputEvent::Modifiers::kLeftButtonDown,
@@ -1482,7 +1486,7 @@ TEST_F(EventHandlerTest, MouseLeaveResetsUnknownState) {
EXPECT_FALSE(
GetDocument().GetFrame()->GetEventHandler().IsMousePositionUnknown());
- WebMouseEvent mouse_leave_event(WebMouseEvent::kMouseLeave,
+ WebMouseEvent mouse_leave_event(WebMouseEvent::Type::kMouseLeave,
gfx::PointF(262, 29), gfx::PointF(329, 67),
WebPointerProperties::Button::kNoButton, 1,
WebInputEvent::Modifiers::kNoModifiers,
@@ -1523,8 +1527,8 @@ TEST_F(EventHandlerSimTest, MouseLeaveIFrameResets) {
frame_resource.Complete("<!DOCTYPE html>");
Compositor().BeginFrame();
WebMouseEvent mouse_move_inside_event(
- WebMouseEvent::kMouseMove, gfx::PointF(100, 229), gfx::PointF(100, 229),
- WebPointerProperties::Button::kNoButton, 0,
+ WebMouseEvent::Type::kMouseMove, gfx::PointF(100, 229),
+ gfx::PointF(100, 229), WebPointerProperties::Button::kNoButton, 0,
WebInputEvent::Modifiers::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests());
mouse_move_inside_event.SetFrameScale(1);
@@ -1543,8 +1547,8 @@ TEST_F(EventHandlerSimTest, MouseLeaveIFrameResets) {
.IsMousePositionUnknown());
WebMouseEvent mouse_move_outside_event(
- WebMouseEvent::kMouseMove, gfx::PointF(300, 29), gfx::PointF(300, 29),
- WebPointerProperties::Button::kNoButton, 0,
+ WebMouseEvent::Type::kMouseMove, gfx::PointF(300, 29),
+ gfx::PointF(300, 29), WebPointerProperties::Button::kNoButton, 0,
WebInputEvent::Modifiers::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests());
mouse_move_outside_event.SetFrameScale(1);
@@ -1578,7 +1582,7 @@ TEST_F(EventHandlerSimTest, CursorStyleBeforeStartDragging) {
)HTML");
Compositor().BeginFrame();
- WebMouseEvent mouse_down_event(WebMouseEvent::kMouseDown,
+ WebMouseEvent mouse_down_event(WebMouseEvent::Type::kMouseDown,
gfx::PointF(150, 50), gfx::PointF(150, 50),
WebPointerProperties::Button::kLeft, 1,
WebInputEvent::Modifiers::kLeftButtonDown,
@@ -1587,7 +1591,7 @@ TEST_F(EventHandlerSimTest, CursorStyleBeforeStartDragging) {
GetDocument().GetFrame()->GetEventHandler().HandleMousePressEvent(
mouse_down_event);
- WebMouseEvent mouse_move_event(WebMouseEvent::kMouseMove,
+ WebMouseEvent mouse_move_event(WebMouseEvent::Type::kMouseMove,
gfx::PointF(151, 50), gfx::PointF(151, 50),
WebPointerProperties::Button::kLeft, 1,
WebInputEvent::Modifiers::kLeftButtonDown,
@@ -2115,8 +2119,8 @@ TEST_F(EventHandlerSimTest, LargeCustomCursorIntersectsViewport) {
// Move the cursor so no part of it intersects the viewport.
{
WebMouseEvent mouse_move_event(
- WebMouseEvent::kMouseMove, gfx::PointF(101, 101), gfx::PointF(101, 101),
- WebPointerProperties::Button::kNoButton, 0, 0,
+ WebMouseEvent::Type::kMouseMove, gfx::PointF(101, 101),
+ gfx::PointF(101, 101), WebPointerProperties::Button::kNoButton, 0, 0,
WebInputEvent::GetStaticTimeStampForTests());
mouse_move_event.SetFrameScale(1);
GetDocument().GetFrame()->GetEventHandler().HandleMouseMoveEvent(
@@ -2131,8 +2135,8 @@ TEST_F(EventHandlerSimTest, LargeCustomCursorIntersectsViewport) {
// should be removed.
{
WebMouseEvent mouse_move_event(
- WebMouseEvent::kMouseMove, gfx::PointF(99, 99), gfx::PointF(99, 99),
- WebPointerProperties::Button::kNoButton, 0, 0,
+ WebMouseEvent::Type::kMouseMove, gfx::PointF(99, 99),
+ gfx::PointF(99, 99), WebPointerProperties::Button::kNoButton, 0, 0,
WebInputEvent::GetStaticTimeStampForTests());
mouse_move_event.SetFrameScale(1);
GetDocument().GetFrame()->GetEventHandler().HandleMouseMoveEvent(
@@ -2174,8 +2178,8 @@ TEST_F(EventHandlerSimTest, SmallCustomCursorIntersectsViewport) {
// Move the cursor so no part of it intersects the viewport.
{
WebMouseEvent mouse_move_event(
- WebMouseEvent::kMouseMove, gfx::PointF(25, 25), gfx::PointF(25, 25),
- WebPointerProperties::Button::kNoButton, 0, 0,
+ WebMouseEvent::Type::kMouseMove, gfx::PointF(25, 25),
+ gfx::PointF(25, 25), WebPointerProperties::Button::kNoButton, 0, 0,
WebInputEvent::GetStaticTimeStampForTests());
mouse_move_event.SetFrameScale(1);
GetDocument().GetFrame()->GetEventHandler().HandleMouseMoveEvent(
@@ -2191,8 +2195,8 @@ TEST_F(EventHandlerSimTest, SmallCustomCursorIntersectsViewport) {
// kMaximumCursorSizeWithoutFallback.
{
WebMouseEvent mouse_move_event(
- WebMouseEvent::kMouseMove, gfx::PointF(23, 23), gfx::PointF(23, 23),
- WebPointerProperties::Button::kNoButton, 0, 0,
+ WebMouseEvent::Type::kMouseMove, gfx::PointF(23, 23),
+ gfx::PointF(23, 23), WebPointerProperties::Button::kNoButton, 0, 0,
WebInputEvent::GetStaticTimeStampForTests());
mouse_move_event.SetFrameScale(1);
GetDocument().GetFrame()->GetEventHandler().HandleMouseMoveEvent(
@@ -2211,7 +2215,8 @@ TEST_F(EventHandlerSimTest, NeverExposeKeyboardEvent) {
GetDocument().GetSettings()->SetDontSendKeyEventsToJavascript(true);
GetDocument().GetSettings()->SetScrollAnimatorEnabled(false);
GetDocument().GetSettings()->SetWebAppScope(GetDocument().Url());
- GetDocument().View()->SetDisplayMode(blink::mojom::DisplayMode::kFullscreen);
+ WebView().MainFrameImpl()->LocalRootFrameWidget()->SetDisplayMode(
+ blink::mojom::DisplayMode::kFullscreen);
request.Complete(R"HTML(
<!DOCTYPE html>
<style>
@@ -2237,7 +2242,8 @@ TEST_F(EventHandlerSimTest, NeverExposeKeyboardEvent) {
Compositor().BeginFrame();
WebElement element = GetDocument().getElementById("log");
- WebKeyboardEvent e{WebInputEvent::kRawKeyDown, WebInputEvent::kNoModifiers,
+ WebKeyboardEvent e{WebInputEvent::Type::kRawKeyDown,
+ WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests()};
e.windows_key_code = VKEY_DOWN;
// TODO(crbug.com/949766) Should cleanup these magic number.
@@ -2245,15 +2251,15 @@ TEST_F(EventHandlerSimTest, NeverExposeKeyboardEvent) {
GetDocument().GetFrame()->GetEventHandler().KeyEvent(e);
EXPECT_EQ("no event", element.InnerHTML().Utf8());
- e.SetType(WebInputEvent::kKeyUp);
+ e.SetType(WebInputEvent::Type::kKeyUp);
GetDocument().GetFrame()->GetEventHandler().KeyEvent(e);
EXPECT_EQ("no event", element.InnerHTML().Utf8());
- e.SetType(WebInputEvent::kKeyDown);
+ e.SetType(WebInputEvent::Type::kKeyDown);
GetDocument().GetFrame()->GetEventHandler().KeyEvent(e);
EXPECT_EQ("no event", element.InnerHTML().Utf8());
- e.SetType(WebInputEvent::kKeyUp);
+ e.SetType(WebInputEvent::Type::kKeyUp);
GetDocument().GetFrame()->GetEventHandler().KeyEvent(e);
EXPECT_EQ("no event", element.InnerHTML().Utf8());
@@ -2262,15 +2268,15 @@ TEST_F(EventHandlerSimTest, NeverExposeKeyboardEvent) {
GetDocument().GetFrame()->GetEventHandler().KeyEvent(e);
EXPECT_NE("no event", element.InnerHTML().Utf8());
- e.SetType(WebInputEvent::kKeyUp);
+ e.SetType(WebInputEvent::Type::kKeyUp);
GetDocument().GetFrame()->GetEventHandler().KeyEvent(e);
EXPECT_NE("no event", element.InnerHTML().Utf8());
- e.SetType(WebInputEvent::kKeyDown);
+ e.SetType(WebInputEvent::Type::kKeyDown);
GetDocument().GetFrame()->GetEventHandler().KeyEvent(e);
EXPECT_NE("no event", element.InnerHTML().Utf8());
- e.SetType(WebInputEvent::kKeyUp);
+ e.SetType(WebInputEvent::Type::kKeyUp);
GetDocument().GetFrame()->GetEventHandler().KeyEvent(e);
EXPECT_NE("no event", element.InnerHTML().Utf8());
}
@@ -2306,7 +2312,8 @@ TEST_F(EventHandlerSimTest, NotExposeKeyboardEvent) {
Compositor().BeginFrame();
WebElement element = GetDocument().getElementById("log");
- WebKeyboardEvent e{WebInputEvent::kRawKeyDown, WebInputEvent::kNoModifiers,
+ WebKeyboardEvent e{WebInputEvent::Type::kRawKeyDown,
+ WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests()};
e.windows_key_code = VKEY_DOWN;
// TODO(crbug.com/949766) Should cleanup these magic number.
@@ -2314,25 +2321,25 @@ TEST_F(EventHandlerSimTest, NotExposeKeyboardEvent) {
GetDocument().GetFrame()->GetEventHandler().KeyEvent(e);
EXPECT_EQ("no event", element.InnerHTML().Utf8());
- e.SetType(WebInputEvent::kKeyUp);
+ e.SetType(WebInputEvent::Type::kKeyUp);
GetDocument().GetFrame()->GetEventHandler().KeyEvent(e);
EXPECT_EQ("no event", element.InnerHTML().Utf8());
- e.SetType(WebInputEvent::kKeyDown);
+ e.SetType(WebInputEvent::Type::kKeyDown);
GetDocument().GetFrame()->GetEventHandler().KeyEvent(e);
EXPECT_EQ("no event", element.InnerHTML().Utf8());
- e.SetType(WebInputEvent::kKeyUp);
+ e.SetType(WebInputEvent::Type::kKeyUp);
GetDocument().GetFrame()->GetEventHandler().KeyEvent(e);
EXPECT_EQ("no event", element.InnerHTML().Utf8());
// Key send to js but not cancellable.
e.dom_key = 0x00400031;
- e.SetType(WebInputEvent::kRawKeyDown);
+ e.SetType(WebInputEvent::Type::kRawKeyDown);
GetDocument().GetFrame()->GetEventHandler().KeyEvent(e);
EXPECT_EQ("keydown cancelable=false", element.InnerHTML().Utf8());
- e.SetType(WebInputEvent::kKeyUp);
+ e.SetType(WebInputEvent::Type::kKeyUp);
GetDocument().GetFrame()->GetEventHandler().KeyEvent(e);
EXPECT_EQ("keyup cancelable=false", element.InnerHTML().Utf8());
@@ -2343,7 +2350,7 @@ TEST_F(EventHandlerSimTest, NotExposeKeyboardEvent) {
FocusParams(SelectionBehaviorOnFocus::kNone,
mojom::blink::FocusType::kNone, nullptr));
- e.SetType(WebInputEvent::kRawKeyDown);
+ e.SetType(WebInputEvent::Type::kRawKeyDown);
GetDocument().GetFrame()->GetEventHandler().KeyEvent(e);
EXPECT_EQ("keydown cancelable=true", element.InnerHTML().Utf8());
@@ -2380,7 +2387,7 @@ TEST_F(EventHandlerSimTest, DoNotScrollWithTouchpadIfOverflowIsHidden) {
Compositor().BeginFrame();
WebGestureEvent scroll_begin_event(
- WebInputEvent::kGestureScrollBegin, WebInputEvent::kNoModifiers,
+ WebInputEvent::Type::kGestureScrollBegin, WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests(),
blink::WebGestureDevice::kTouchpad);
scroll_begin_event.SetPositionInWidget(gfx::PointF(10, 10));
@@ -2388,7 +2395,7 @@ TEST_F(EventHandlerSimTest, DoNotScrollWithTouchpadIfOverflowIsHidden) {
scroll_begin_event.SetFrameScale(1);
WebGestureEvent scroll_update_event(
- WebInputEvent::kGestureScrollUpdate, WebInputEvent::kNoModifiers,
+ WebInputEvent::Type::kGestureScrollUpdate, WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests(),
blink::WebGestureDevice::kTouchpad);
scroll_update_event.data.scroll_update.delta_x = -100;
@@ -2397,7 +2404,7 @@ TEST_F(EventHandlerSimTest, DoNotScrollWithTouchpadIfOverflowIsHidden) {
scroll_update_event.SetPositionInScreen(gfx::PointF(10, 10));
scroll_update_event.SetFrameScale(1);
- WebGestureEvent scroll_end_event(WebInputEvent::kGestureScrollEnd,
+ WebGestureEvent scroll_end_event(WebInputEvent::Type::kGestureScrollEnd,
WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests(),
blink::WebGestureDevice::kTouchpad);
@@ -2405,11 +2412,11 @@ TEST_F(EventHandlerSimTest, DoNotScrollWithTouchpadIfOverflowIsHidden) {
scroll_end_event.SetPositionInScreen(gfx::PointF(10, 10));
WebView().MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(scroll_begin_event));
+ WebCoalescedInputEvent(scroll_begin_event, ui::LatencyInfo()));
WebView().MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(scroll_update_event));
+ WebCoalescedInputEvent(scroll_update_event, ui::LatencyInfo()));
WebView().MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(scroll_end_event));
+ WebCoalescedInputEvent(scroll_end_event, ui::LatencyInfo()));
EXPECT_EQ(0, GetDocument().getElementById("outer")->scrollLeft());
}
@@ -2442,7 +2449,7 @@ TEST_F(EventHandlerSimTest, GestureScrollUpdateModifiedScrollChain) {
Compositor().BeginFrame();
WebGestureEvent scroll_begin_event(
- WebInputEvent::kGestureScrollBegin, WebInputEvent::kNoModifiers,
+ WebInputEvent::Type::kGestureScrollBegin, WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests(),
blink::WebGestureDevice::kTouchpad);
scroll_begin_event.SetPositionInWidget(gfx::PointF(10, 10));
@@ -2450,7 +2457,7 @@ TEST_F(EventHandlerSimTest, GestureScrollUpdateModifiedScrollChain) {
scroll_begin_event.SetFrameScale(1);
WebGestureEvent scroll_update_event(
- WebInputEvent::kGestureScrollUpdate, WebInputEvent::kNoModifiers,
+ WebInputEvent::Type::kGestureScrollUpdate, WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests(),
blink::WebGestureDevice::kTouchpad);
scroll_update_event.data.scroll_update.delta_x = 0;
@@ -2459,7 +2466,7 @@ TEST_F(EventHandlerSimTest, GestureScrollUpdateModifiedScrollChain) {
scroll_update_event.SetPositionInScreen(gfx::PointF(10, 10));
scroll_update_event.SetFrameScale(1);
- WebGestureEvent scroll_end_event(WebInputEvent::kGestureScrollEnd,
+ WebGestureEvent scroll_end_event(WebInputEvent::Type::kGestureScrollEnd,
WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests(),
blink::WebGestureDevice::kTouchpad);
@@ -2467,7 +2474,7 @@ TEST_F(EventHandlerSimTest, GestureScrollUpdateModifiedScrollChain) {
scroll_end_event.SetPositionInScreen(gfx::PointF(10, 10));
WebView().MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(scroll_begin_event));
+ WebCoalescedInputEvent(scroll_begin_event, ui::LatencyInfo()));
// Between the GSB (when the scroll chain is computed) and GSU, update the
// scroller to be display:inline. Applying the scroll should handle this
@@ -2476,9 +2483,9 @@ TEST_F(EventHandlerSimTest, GestureScrollUpdateModifiedScrollChain) {
scroller->setAttribute("class", "inline");
WebView().MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(scroll_update_event));
+ WebCoalescedInputEvent(scroll_update_event, ui::LatencyInfo()));
WebView().MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(scroll_end_event));
+ WebCoalescedInputEvent(scroll_end_event, ui::LatencyInfo()));
EXPECT_EQ(scroller->scrollTop(), 0);
@@ -2514,7 +2521,7 @@ TEST_F(EventHandlerSimTest, ElementTargetedGestureScroll) {
// Send GSB/GSU at 0,0 to target the viewport first, then verify that
// the viewport scrolled accordingly.
WebGestureEvent gesture_scroll_begin{
- WebInputEvent::kGestureScrollBegin, WebInputEvent::kNoModifiers,
+ WebInputEvent::Type::kGestureScrollBegin, WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests()};
gesture_scroll_begin.SetFrameScale(1);
gesture_scroll_begin.data.scroll_begin.delta_x_hint = 0;
@@ -2523,7 +2530,7 @@ TEST_F(EventHandlerSimTest, ElementTargetedGestureScroll) {
gesture_scroll_begin);
WebGestureEvent gesture_scroll_update{
- WebInputEvent::kGestureScrollUpdate, WebInputEvent::kNoModifiers,
+ WebInputEvent::Type::kGestureScrollUpdate, WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests()};
gesture_scroll_update.SetFrameScale(1);
gesture_scroll_update.data.scroll_update.delta_x = 0;
@@ -2533,7 +2540,7 @@ TEST_F(EventHandlerSimTest, ElementTargetedGestureScroll) {
gesture_scroll_update);
WebGestureEvent gesture_scroll_end{
- WebInputEvent::kGestureScrollEnd, WebInputEvent::kNoModifiers,
+ WebInputEvent::Type::kGestureScrollEnd, WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests()};
gesture_scroll_end.SetFrameScale(1);
GetDocument().GetFrame()->GetEventHandler().HandleGestureEvent(
@@ -2602,7 +2609,7 @@ TEST_F(EventHandlerSimTest, ElementTargetedGestureScrollIFrame) {
// with gestures.
constexpr float delta_y = 100;
WebGestureEvent gesture_scroll_begin{
- WebInputEvent::kGestureScrollBegin, WebInputEvent::kNoModifiers,
+ WebInputEvent::Type::kGestureScrollBegin, WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests()};
gesture_scroll_begin.SetFrameScale(1);
gesture_scroll_begin.data.scroll_begin.delta_x_hint = 0;
@@ -2613,7 +2620,7 @@ TEST_F(EventHandlerSimTest, ElementTargetedGestureScrollIFrame) {
gesture_scroll_begin);
WebGestureEvent gesture_scroll_update{
- WebInputEvent::kGestureScrollUpdate, WebInputEvent::kNoModifiers,
+ WebInputEvent::Type::kGestureScrollUpdate, WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests()};
gesture_scroll_update.SetFrameScale(1);
gesture_scroll_update.data.scroll_update.delta_x = 0;
@@ -2623,7 +2630,7 @@ TEST_F(EventHandlerSimTest, ElementTargetedGestureScrollIFrame) {
gesture_scroll_update);
WebGestureEvent gesture_scroll_end{
- WebInputEvent::kGestureScrollEnd, WebInputEvent::kNoModifiers,
+ WebInputEvent::Type::kGestureScrollEnd, WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests()};
gesture_scroll_end.SetFrameScale(1);
GetDocument().GetFrame()->GetEventHandler().HandleGestureEvent(
@@ -2653,7 +2660,7 @@ TEST_F(EventHandlerSimTest, ElementTargetedGestureScrollViewport) {
GetDocument().GetPage()->GetVisualViewport();
WebGestureEvent gesture_scroll_begin{
- WebInputEvent::kGestureScrollBegin, WebInputEvent::kNoModifiers,
+ WebInputEvent::Type::kGestureScrollBegin, WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests()};
gesture_scroll_begin.SetFrameScale(1);
gesture_scroll_begin.data.scroll_begin.delta_x_hint = 0;
@@ -2665,7 +2672,7 @@ TEST_F(EventHandlerSimTest, ElementTargetedGestureScrollViewport) {
gesture_scroll_begin);
WebGestureEvent gesture_scroll_update{
- WebInputEvent::kGestureScrollUpdate, WebInputEvent::kNoModifiers,
+ WebInputEvent::Type::kGestureScrollUpdate, WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests()};
gesture_scroll_update.SetFrameScale(1);
gesture_scroll_update.data.scroll_update.delta_x = 0;
@@ -2675,7 +2682,7 @@ TEST_F(EventHandlerSimTest, ElementTargetedGestureScrollViewport) {
gesture_scroll_update);
WebGestureEvent gesture_scroll_end{
- WebInputEvent::kGestureScrollEnd, WebInputEvent::kNoModifiers,
+ WebInputEvent::Type::kGestureScrollEnd, WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests()};
gesture_scroll_end.SetFrameScale(1);
GetDocument().GetFrame()->GetEventHandler().HandleGestureEvent(
@@ -2698,7 +2705,7 @@ TEST_F(EventHandlerSimTest, SelecteTransformedTextWhenCapturing) {
)HTML");
Compositor().BeginFrame();
- WebMouseEvent mouse_down_event(WebInputEvent::kMouseDown,
+ WebMouseEvent mouse_down_event(WebInputEvent::Type::kMouseDown,
gfx::PointF(100, 20), gfx::PointF(0, 0),
WebPointerProperties::Button::kLeft, 1,
WebInputEvent::Modifiers::kLeftButtonDown,
@@ -2717,7 +2724,7 @@ TEST_F(EventHandlerSimTest, SelecteTransformedTextWhenCapturing) {
GetDocument().GetFrame()->GetEventHandler().SetPointerCapture(
PointerEventFactory::kMouseId, target);
- WebMouseEvent mouse_move_event(WebInputEvent::kMouseMove,
+ WebMouseEvent mouse_move_event(WebInputEvent::Type::kMouseMove,
gfx::PointF(258, 20), gfx::PointF(0, 0),
WebPointerProperties::Button::kLeft, 1,
WebInputEvent::Modifiers::kLeftButtonDown,
@@ -2727,7 +2734,7 @@ TEST_F(EventHandlerSimTest, SelecteTransformedTextWhenCapturing) {
mouse_move_event, Vector<WebMouseEvent>(), Vector<WebMouseEvent>());
WebMouseEvent mouse_up_event(
- WebMouseEvent::kMouseUp, gfx::PointF(258, 20), gfx::PointF(0, 0),
+ WebMouseEvent::Type::kMouseUp, gfx::PointF(258, 20), gfx::PointF(0, 0),
WebPointerProperties::Button::kLeft, 1, WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests());
mouse_up_event.SetFrameScale(1);
@@ -2787,22 +2794,22 @@ TEST_F(EventHandlerSimTest, MouseDragWithNoSubframeImplicitCapture) {
Compositor().BeginFrame();
WebMouseEvent mouse_down_inside_event(
- WebMouseEvent::kMouseDown, gfx::PointF(50, 50), gfx::PointF(50, 50),
+ WebMouseEvent::Type::kMouseDown, gfx::PointF(50, 50), gfx::PointF(50, 50),
WebPointerProperties::Button::kLeft, 0,
WebInputEvent::Modifiers::kLeftButtonDown,
WebInputEvent::GetStaticTimeStampForTests());
mouse_down_inside_event.SetFrameScale(1);
WebView().MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(mouse_down_inside_event));
+ WebCoalescedInputEvent(mouse_down_inside_event, ui::LatencyInfo()));
WebMouseEvent mouse_move_inside_event(
- WebInputEvent::kMouseMove, gfx::PointF(100, 100), gfx::PointF(100, 100),
- WebPointerProperties::Button::kLeft, 1,
+ WebInputEvent::Type::kMouseMove, gfx::PointF(100, 100),
+ gfx::PointF(100, 100), WebPointerProperties::Button::kLeft, 1,
WebInputEvent::Modifiers::kLeftButtonDown,
WebInputEvent::GetStaticTimeStampForTests());
mouse_move_inside_event.SetFrameScale(1);
WebView().MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(mouse_move_inside_event));
+ WebCoalescedInputEvent(mouse_move_inside_event, ui::LatencyInfo()));
auto* iframe_element =
To<HTMLIFrameElement>(GetDocument().getElementById("frame"));
Document* iframe_doc = iframe_element->contentDocument();
@@ -2817,13 +2824,13 @@ TEST_F(EventHandlerSimTest, MouseDragWithNoSubframeImplicitCapture) {
// Without capturing, next mouse move will be send to outer frame.
WebMouseEvent mouse_move_outside_event(
- WebInputEvent::kMouseMove, gfx::PointF(100, 300), gfx::PointF(100, 300),
- WebPointerProperties::Button::kLeft, 1,
+ WebInputEvent::Type::kMouseMove, gfx::PointF(100, 300),
+ gfx::PointF(100, 300), WebPointerProperties::Button::kLeft, 1,
WebInputEvent::Modifiers::kLeftButtonDown,
WebInputEvent::GetStaticTimeStampForTests());
mouse_move_outside_event.SetFrameScale(1);
WebView().MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(mouse_move_outside_event));
+ WebCoalescedInputEvent(mouse_move_outside_event, ui::LatencyInfo()));
// Mouse is hovering the element in outer frame.
EXPECT_FALSE(iframe_doc->HoverElement());
@@ -2879,13 +2886,13 @@ TEST_F(EventHandlerSimTest,
Compositor().BeginFrame();
WebMouseEvent mouse_down_inside_event(
- WebMouseEvent::kMouseDown, gfx::PointF(50, 50), gfx::PointF(50, 50),
+ WebMouseEvent::Type::kMouseDown, gfx::PointF(50, 50), gfx::PointF(50, 50),
WebPointerProperties::Button::kLeft, 0,
WebInputEvent::Modifiers::kLeftButtonDown,
WebInputEvent::GetStaticTimeStampForTests());
mouse_down_inside_event.SetFrameScale(1);
WebView().MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(mouse_down_inside_event));
+ WebCoalescedInputEvent(mouse_down_inside_event, ui::LatencyInfo()));
auto* iframe_element =
To<HTMLIFrameElement>(GetDocument().getElementById("frame"));
@@ -2898,14 +2905,14 @@ TEST_F(EventHandlerSimTest,
EXPECT_TRUE(target->hasPointerCapture(PointerEventFactory::kMouseId));
// With pointercapture, next mouse move will be send to inner frame.
- WebMouseEvent mouse_move_event(WebInputEvent::kMouseMove,
+ WebMouseEvent mouse_move_event(WebInputEvent::Type::kMouseMove,
gfx::PointF(100, 300), gfx::PointF(100, 300),
WebPointerProperties::Button::kLeft, 1,
WebInputEvent::Modifiers::kLeftButtonDown,
WebInputEvent::GetStaticTimeStampForTests());
mouse_move_event.SetFrameScale(1);
WebView().MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(mouse_move_event));
+ WebCoalescedInputEvent(mouse_move_event, ui::LatencyInfo()));
EXPECT_EQ(iframe_doc->GetFrame()
->GetEventHandler()
@@ -2916,7 +2923,7 @@ TEST_F(EventHandlerSimTest,
// Release capture and move event will be send to outer frame.
target->releasePointerCapture(PointerEventFactory::kMouseId, exception);
WebView().MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(mouse_move_event));
+ WebCoalescedInputEvent(mouse_move_event, ui::LatencyInfo()));
// iframe no longer gets mouse move events.
EXPECT_FALSE(iframe_doc->HoverElement());
@@ -2956,31 +2963,31 @@ TEST_F(EventHandlerSimTest, MouseRightButtonDownMoveToIFrame) {
frame_resource.Complete("<!DOCTYPE html>");
Compositor().BeginFrame();
WebMouseEvent mouse_down_outside_event(
- WebMouseEvent::kMouseDown, gfx::PointF(300, 29), gfx::PointF(300, 29),
- WebPointerProperties::Button::kRight, 0,
+ WebMouseEvent::Type::kMouseDown, gfx::PointF(300, 29),
+ gfx::PointF(300, 29), WebPointerProperties::Button::kRight, 0,
WebInputEvent::Modifiers::kRightButtonDown,
WebInputEvent::GetStaticTimeStampForTests());
mouse_down_outside_event.SetFrameScale(1);
WebView().MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(mouse_down_outside_event));
+ WebCoalescedInputEvent(mouse_down_outside_event, ui::LatencyInfo()));
WebMouseEvent mouse_move_outside_event(
- WebMouseEvent::kMouseMove, gfx::PointF(300, 29), gfx::PointF(300, 29),
- WebPointerProperties::Button::kRight, 0,
+ WebMouseEvent::Type::kMouseMove, gfx::PointF(300, 29),
+ gfx::PointF(300, 29), WebPointerProperties::Button::kRight, 0,
WebInputEvent::Modifiers::kRightButtonDown,
WebInputEvent::GetStaticTimeStampForTests());
mouse_move_outside_event.SetFrameScale(1);
WebView().MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(mouse_move_outside_event));
+ WebCoalescedInputEvent(mouse_move_outside_event, ui::LatencyInfo()));
WebMouseEvent mouse_move_inside_event(
- WebMouseEvent::kMouseMove, gfx::PointF(100, 229), gfx::PointF(100, 229),
- WebPointerProperties::Button::kRight, 0,
+ WebMouseEvent::Type::kMouseMove, gfx::PointF(100, 229),
+ gfx::PointF(100, 229), WebPointerProperties::Button::kRight, 0,
WebInputEvent::Modifiers::kRightButtonDown,
WebInputEvent::GetStaticTimeStampForTests());
mouse_move_inside_event.SetFrameScale(1);
WebView().MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(mouse_move_inside_event));
+ WebCoalescedInputEvent(mouse_move_inside_event, ui::LatencyInfo()));
EXPECT_FALSE(
GetDocument().GetFrame()->GetEventHandler().IsMousePositionUnknown());
EXPECT_FALSE(To<LocalFrame>(GetDocument().GetFrame()->Tree().FirstChild())
@@ -3007,7 +3014,7 @@ TEST_F(EventHandlerSimTest, PenDraggingOnElementActive) {
)HTML");
Compositor().BeginFrame();
- WebMouseEvent pen_down(WebMouseEvent::kMouseDown, gfx::PointF(100, 100),
+ WebMouseEvent pen_down(WebMouseEvent::Type::kMouseDown, gfx::PointF(100, 100),
gfx::PointF(100, 100),
WebPointerProperties::Button::kLeft, 0,
WebInputEvent::Modifiers::kLeftButtonDown,
@@ -3015,9 +3022,9 @@ TEST_F(EventHandlerSimTest, PenDraggingOnElementActive) {
pen_down.pointer_type = blink::WebPointerProperties::PointerType::kPen;
pen_down.SetFrameScale(1);
WebView().MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(pen_down));
+ WebCoalescedInputEvent(pen_down, ui::LatencyInfo()));
- WebMouseEvent pen_move(WebMouseEvent::kMouseMove, gfx::PointF(100, 100),
+ WebMouseEvent pen_move(WebMouseEvent::Type::kMouseMove, gfx::PointF(100, 100),
gfx::PointF(100, 100),
WebPointerProperties::Button::kLeft, 0,
WebInputEvent::Modifiers::kLeftButtonDown,
@@ -3026,15 +3033,57 @@ TEST_F(EventHandlerSimTest, PenDraggingOnElementActive) {
pen_move.SetFrameScale(1);
// Send first mouse move to update mouse event sates.
WebView().MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(pen_move));
+ WebCoalescedInputEvent(pen_move, ui::LatencyInfo()));
// Send another mouse move again to update active element to verify mouse
// event states.
WebView().MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(pen_move));
+ WebCoalescedInputEvent(pen_move, ui::LatencyInfo()));
EXPECT_EQ(GetDocument().GetActiveElement(),
GetDocument().getElementById("target"));
}
+TEST_F(EventHandlerSimTest, TestNoCrashOnMouseWheelZeroDelta) {
+ WebView().MainFrameWidget()->Resize(WebSize(800, 600));
+ SimRequest request("https://example.com/test.html", "text/html");
+ LoadURL("https://example.com/test.html");
+ request.Complete(R"HTML(
+ <!DOCTYPE html>
+ <body>
+ <div id="area" style="width:100px;height:100px">
+ </div>
+ <p id='log'>no wheel event</p>
+ </body>
+ <script>
+ document.addEventListener('wheel', (e) => {
+ let log = document.getElementById('log');
+ log.innerText = 'received wheel event, deltaX: ' + e.deltaX + ' deltaY: ' + e.deltaY;
+ });
+ </script>
+ )HTML");
+ Compositor().BeginFrame();
+
+ // Set mouse position and active web view.
+ InitializeMousePositionAndActivateView(50, 50);
+ Compositor().BeginFrame();
+
+ WebElement element = GetDocument().getElementById("log");
+ WebMouseWheelEvent wheel_event(
+ blink::WebInputEvent::Type::kMouseWheel,
+ blink::WebInputEvent::kNoModifiers,
+ blink::WebInputEvent::GetStaticTimeStampForTests());
+ wheel_event.SetPositionInScreen(50, 50);
+ wheel_event.delta_x = 0;
+ wheel_event.delta_y = 0;
+ wheel_event.phase = WebMouseWheelEvent::kPhaseBegan;
+ GetDocument().GetFrame()->GetEventHandler().HandleWheelEvent(wheel_event);
+ EXPECT_EQ("received wheel event, deltaX: 0 deltaY: 0",
+ element.InnerHTML().Utf8());
+ ASSERT_EQ(0,
+ GetDocument().View()->LayoutViewport()->GetScrollOffset().Height());
+ ASSERT_EQ(0,
+ GetDocument().View()->LayoutViewport()->GetScrollOffset().Width());
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/input/fallback_cursor_event_manager.cc b/chromium/third_party/blink/renderer/core/input/fallback_cursor_event_manager.cc
deleted file mode 100644
index 3008ec61847..00000000000
--- a/chromium/third_party/blink/renderer/core/input/fallback_cursor_event_manager.cc
+++ /dev/null
@@ -1,466 +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/core/input/fallback_cursor_event_manager.h"
-
-#include "third_party/blink/public/common/input/web_mouse_event.h"
-#include "third_party/blink/renderer/core/dom/document.h"
-#include "third_party/blink/renderer/core/dom/node.h"
-#include "third_party/blink/renderer/core/editing/editing_utilities.h"
-#include "third_party/blink/renderer/core/events/web_input_event_conversion.h"
-#include "third_party/blink/renderer/core/frame/local_frame.h"
-#include "third_party/blink/renderer/core/frame/local_frame_client.h"
-#include "third_party/blink/renderer/core/frame/settings.h"
-#include "third_party/blink/renderer/core/frame/visual_viewport.h"
-#include "third_party/blink/renderer/core/geometry/dom_rect.h"
-#include "third_party/blink/renderer/core/html/html_frame_owner_element.h"
-#include "third_party/blink/renderer/core/input/event_handler.h"
-#include "third_party/blink/renderer/core/input/scroll_manager.h"
-#include "third_party/blink/renderer/core/layout/hit_test_location.h"
-#include "third_party/blink/renderer/core/layout/hit_test_request.h"
-#include "third_party/blink/renderer/core/layout/hit_test_result.h"
-#include "third_party/blink/renderer/core/layout/layout_box.h"
-#include "third_party/blink/renderer/core/layout/layout_object.h"
-#include "third_party/blink/renderer/core/layout/layout_view.h"
-#include "third_party/blink/renderer/core/page/chrome_client.h"
-#include "third_party/blink/renderer/core/page/focus_controller.h"
-#include "third_party/blink/renderer/core/page/page.h"
-#include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
-#include "third_party/blink/renderer/platform/geometry/int_point.h"
-#include "third_party/blink/renderer/platform/geometry/int_size.h"
-#include "third_party/blink/renderer/platform/keyboard_codes.h"
-#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
-#include "third_party/blink/renderer/platform/wtf/casting.h"
-
-namespace blink {
-
-namespace {
-
-const float kScrollAreaRatio = 0.3f;
-
-LocalFrame* FrameOfNode(const Node& node) {
- return node.GetDocument().GetFrame();
-}
-
-Node* ParentNode(const Node& node) {
- if (node.IsDocumentNode()) {
- FrameOwner* frame_owner = FrameOfNode(node)->Owner();
- DCHECK(frame_owner->IsLocal());
- return DynamicTo<HTMLFrameOwnerElement>(frame_owner);
- }
-
- return node.parentNode();
-}
-
-HitTestResult HitTest(LayoutView* layout_view, const IntPoint& point_in_root) {
- HitTestRequest request(HitTestRequest::kReadOnly |
- HitTestRequest::kAllowChildFrameContent |
- HitTestRequest::kRetargetForInert);
- HitTestLocation location(point_in_root);
- HitTestResult result(request, location);
- layout_view->HitTest(location, result);
-
- return result;
-}
-
-bool CanScrollAnyDirection(const ScrollableArea& scrollable) {
- IntSize scroll_dimensions =
- scrollable.MaximumScrollOffsetInt() - scrollable.MinimumScrollOffsetInt();
- return !scroll_dimensions.IsZero();
-}
-
-IntSize ScrollableAreaClipSizeInRootFrame(const ScrollableArea& scrollable) {
- LayoutBox* box = scrollable.GetLayoutBox();
- DCHECK(box);
- LocalFrameView* view = box->GetFrameView();
- DCHECK(view);
-
- PhysicalRect rect(scrollable.VisibleContentRect(blink::kIncludeScrollbars));
- rect = view->DocumentToFrame(rect);
- return view->ConvertToRootFrame(EnclosedIntRect(FloatRect(rect))).Size();
-}
-
-IntPoint RootFrameLocationToScrollable(const IntPoint& location_in_root_frame,
- const ScrollableArea& scrollable) {
- LayoutBox* box = scrollable.GetLayoutBox();
- DCHECK(box);
- LocalFrameView* view = box->GetFrameView();
-
- DCHECK(view);
-
- IntPoint location_in_frame =
- view->ConvertFromRootFrame(location_in_root_frame);
-
- if (&scrollable == view->GetScrollableArea()) {
- LocalFrame& frame = view->GetFrame();
- if (frame.IsMainFrame() && frame.GetPage()) {
- // For the main frame, the scroller whose location we want to be relative
- // to is the visual viewport so that the cursor works under pinch zoom
- // scenarios.
- VisualViewport& viewport = frame.GetPage()->GetVisualViewport();
- IntPoint point_in_viewport =
- viewport.RootFrameToViewport(location_in_frame);
-
- // Scale since we're in visual viewport coordinates, and want the offset
- // relative to the visual viewport, but all the comparisons related to
- // scroller size are done in the root frame.
- float scale = 1.f / viewport.Scale();
- point_in_viewport.Scale(scale, scale);
- return point_in_viewport;
- }
-
- return location_in_frame;
- }
-
- DCHECK(scrollable.IsPaintLayerScrollableArea());
-
- IntPoint location_in_box =
- view->ConvertToLayoutObject(*box, location_in_frame);
- location_in_box.Move(-box->BorderLeft().ToInt(), -box->BorderTop().ToInt());
- return location_in_box;
-}
-
-} // namespace
-
-FallbackCursorEventManager::FallbackCursorEventManager(LocalFrame& root_frame)
- : root_frame_(root_frame) {
- DCHECK(root_frame.IsMainFrame());
- ResetCurrentScrollable();
-}
-
-void FallbackCursorEventManager::Trace(Visitor* visitor) {
- visitor->Trace(root_frame_);
- visitor->Trace(current_node_);
-}
-
-void FallbackCursorEventManager::ResetCurrentScrollable() {
- current_node_.Clear();
-}
-
-// Check if current scrolling ScrollableArea is still valid and reset it if not.
-void FallbackCursorEventManager::InvalidateCurrentScrollableIfNeeded() {
- if (!current_node_)
- return;
-
- if (!current_node_->isConnected() ||
- !current_node_->GetDocument().GetFrame()) {
- ResetCurrentScrollable();
- }
- ScrollableArea* current_scrollable = CurrentScrollingScrollableArea();
- if (!current_scrollable || !CanScrollAnyDirection(*current_scrollable))
- ResetCurrentScrollable();
-}
-
-ScrollableArea* FallbackCursorEventManager::CurrentScrollingScrollableArea() {
- LocalFrame* current_frame = CurrentScrollingFrame();
- Node* current_node = CurrentScrollingNode();
-
- if (current_node->IsDocumentNode())
- return current_frame->View()->GetScrollableArea();
-
- auto* layout_object = current_node->GetLayoutObject();
- if (!layout_object || !layout_object->IsBox())
- return nullptr;
-
- return ToLayoutBox(current_node->GetLayoutObject())->GetScrollableArea();
-}
-
-Node* FallbackCursorEventManager::CurrentScrollingNode() {
- if (!current_node_)
- return root_frame_->GetDocument();
-
- return current_node_.Get();
-}
-
-LocalFrame* FallbackCursorEventManager::CurrentScrollingFrame() {
- if (!current_node_)
- return root_frame_;
-
- return FrameOfNode(*current_node_.Get());
-}
-
-bool FallbackCursorEventManager::ShouldLock(
- Direction d,
- const ScrollableArea& scrollable,
- const IntSize& node_size,
- const IntPoint& cursor_location_in_node) {
- // This method won't work correctly on RootFrameViewport because of how
- // UserInputScrollable works.
- DCHECK(!scrollable.IsRootFrameViewport());
-
- // Check can scroll in direction, if not should not lock this direction.
- IntSize current_offset = scrollable.ScrollOffsetInt();
- IntSize min_offset = scrollable.MinimumScrollOffsetInt();
- IntSize max_offset = scrollable.MaximumScrollOffsetInt();
-
- // If a direction isn't scrollable (e.g. overflow:hidden), we should restrict
- // the min/max in that axis so that the code below realizes we can't scroll
- // in that direction. That'll ensure we don't lock the cursor in that
- // direction and allow it to be moved rather than fruitlessly trying to
- // scroll.
- if (!scrollable.UserInputScrollable(kHorizontalScrollbar)) {
- min_offset.SetWidth(current_offset.Width());
- max_offset.SetWidth(current_offset.Width());
- }
- if (!scrollable.UserInputScrollable(kVerticalScrollbar)) {
- min_offset.SetHeight(current_offset.Height());
- max_offset.SetHeight(current_offset.Height());
- }
-
- switch (d) {
- case Direction::kLeft:
- if (current_offset.Width() <= min_offset.Width())
- return false;
- break;
- case Direction::kRight:
- if (current_offset.Width() >= max_offset.Width())
- return false;
- break;
- case Direction::kUp:
- if (current_offset.Height() <= min_offset.Height())
- return false;
- break;
- case Direction::kDown:
- if (current_offset.Height() >= max_offset.Height())
- return false;
- break;
- default:
- NOTREACHED();
- }
-
- // Check if cursor located in scroll area.
- switch (d) {
- case Direction::kLeft:
- if (cursor_location_in_node.X() < node_size.Width() * kScrollAreaRatio) {
- return true;
- }
- break;
- case Direction::kRight:
- if (cursor_location_in_node.X() >
- node_size.Width() * (1 - kScrollAreaRatio)) {
- return true;
- }
- break;
- case Direction::kUp:
- if (cursor_location_in_node.Y() < node_size.Height() * kScrollAreaRatio) {
- return true;
- }
- break;
- case Direction::kDown:
- if (cursor_location_in_node.Y() >
- node_size.Height() * (1 - kScrollAreaRatio)) {
- return true;
- }
- break;
- default:
- NOTREACHED();
- }
-
- return false;
-}
-
-void FallbackCursorEventManager::LockCursor(bool left,
- bool right,
- bool up,
- bool down) {
- root_frame_->GetChromeClient().FallbackCursorModeLockCursor(
- root_frame_.Get(), left, right, up, down);
-}
-
-void FallbackCursorEventManager::SetCursorVisibility(bool visible) {
- root_frame_->GetChromeClient().FallbackCursorModeSetCursorVisibility(
- root_frame_.Get(), visible);
-}
-
-void FallbackCursorEventManager::ComputeLockCursor(
- const IntPoint& location_in_root_frame) {
- DCHECK(root_frame_->GetDocument());
- DCHECK(root_frame_->GetDocument()->View());
- // TODO(bokan): Overly-defensive since we'll be merging, remove from ToT.
- if (!root_frame_->GetDocument() || !root_frame_->GetDocument()->View())
- return;
-
- ScrollableArea* scrollable = CurrentScrollingScrollableArea();
-
- DCHECK(scrollable);
- IntSize scrollable_clip_size_in_root_frame =
- ScrollableAreaClipSizeInRootFrame(*scrollable);
- VisualViewport& visual_viewport = root_frame_->GetPage()->GetVisualViewport();
- IntPoint location_in_scrollable =
- RootFrameLocationToScrollable(location_in_root_frame, *scrollable);
-
- // The RootFrameViewport is special because it's really two scrollers in one.
- // We need to check each of the visual and layout viewports independently
- // since we need to account for whether the scroller with extent
- // (current_offset < MaxScrollOffset()) is UserInputScrollable, however,
- // RootFrameViewport::UserInputScrollable will return whether either
- // sub-viewport is UserInputScrollable.
- // TODO(bokan): The below is awkward because we need a minimal change for
- // merge. It relies on the fact that ShouldLock doesn't use the the passed in
- // scroller to determine the mouse location relative to the scroll region,
- // the geometry is calculated here the same is passed in both cases. We
- // should refactor ShouldLock into InScrollRegion and CanScroll.
- ScrollableArea* scroller_for_lock =
- scrollable->IsRootFrameViewport()
- ? root_frame_->GetDocument()->View()->LayoutViewport()
- : scrollable;
-
- bool left =
- ShouldLock(Direction::kLeft, *scroller_for_lock,
- scrollable_clip_size_in_root_frame, location_in_scrollable);
- bool right =
- ShouldLock(Direction::kRight, *scroller_for_lock,
- scrollable_clip_size_in_root_frame, location_in_scrollable);
- bool up =
- ShouldLock(Direction::kUp, *scroller_for_lock,
- scrollable_clip_size_in_root_frame, location_in_scrollable);
- bool down =
- ShouldLock(Direction::kDown, *scroller_for_lock,
- scrollable_clip_size_in_root_frame, location_in_scrollable);
-
- // If we can't scroll the layout viewport, we should still check whether we
- // might be able to scroll the visual viewport.
- if (scrollable->IsRootFrameViewport()) {
- left |=
- ShouldLock(Direction::kLeft, visual_viewport,
- scrollable_clip_size_in_root_frame, location_in_scrollable);
- right |=
- ShouldLock(Direction::kRight, visual_viewport,
- scrollable_clip_size_in_root_frame, location_in_scrollable);
- up |=
- ShouldLock(Direction::kUp, visual_viewport,
- scrollable_clip_size_in_root_frame, location_in_scrollable);
- down |=
- ShouldLock(Direction::kDown, visual_viewport,
- scrollable_clip_size_in_root_frame, location_in_scrollable);
- }
-
- LockCursor(left, right, up, down);
-}
-
-void FallbackCursorEventManager::HandleMouseMoveEvent(const WebMouseEvent& e) {
- DCHECK(RuntimeEnabledFeatures::FallbackCursorModeEnabled());
- // TODO(crbug.com/953393): reenable after bug is fixed.
- // DCHECK(is_fallback_cursor_mode_on_);
-
- InvalidateCurrentScrollableIfNeeded();
- ScrollableArea* scrollable = CurrentScrollingScrollableArea();
-
- DCHECK(scrollable);
-
- DCHECK(root_frame_->GetDocument());
- DCHECK(root_frame_->GetDocument()->View());
- // TODO(bokan): Overly-defensive since we'll be merging, remove from ToT.
- if (!root_frame_->GetDocument() || !root_frame_->GetDocument()->View())
- return;
-
- IntPoint location_in_root_frame{e.PositionInRootFrame().x(),
- e.PositionInRootFrame().y()};
-
- // Make sure we unlock all movement if the cursor is outside our bounds. This
- // can happen when the cursor is enabled/disabled (e.g. position: -1,-1).
- IntRect root_frame_rect = root_frame_->GetDocument()->View()->FrameRect();
- if (!root_frame_rect.Contains(location_in_root_frame)) {
- ResetCurrentScrollable();
- LockCursor(false, false, false, false);
- return;
- }
-
- IntSize scrollable_clip_size_in_root_frame =
- ScrollableAreaClipSizeInRootFrame(*scrollable);
- IntPoint location_in_scrollable =
- RootFrameLocationToScrollable(location_in_root_frame, *scrollable);
-
- // Check if mouse out of current node.
- IntRect rect = IntRect(IntPoint(), scrollable_clip_size_in_root_frame);
- if (!rect.Contains(location_in_scrollable))
- ResetCurrentScrollable();
-
- ComputeLockCursor(location_in_root_frame);
-}
-
-void FallbackCursorEventManager::HandleMousePressEvent(const WebMouseEvent& e) {
- DCHECK(RuntimeEnabledFeatures::FallbackCursorModeEnabled());
- // TODO(crbug.com/953393): reenable after bug is fixed.
- // DCHECK(is_fallback_cursor_mode_on_);
-
- ResetCurrentScrollable();
-
- // Re hit test since we need a hit test with child frame.
- IntPoint location{e.PositionInRootFrame().x(), e.PositionInRootFrame().y()};
- HitTestResult hit_test_result =
- HitTest(root_frame_->GetDocument()->GetLayoutView(), location);
- Node* node = hit_test_result.InnerNode();
- if (!node)
- return;
-
- // Click on input boxes or media node should hide the cursor.
- if (HasEditableStyle(*node) || node->IsMediaElement()) {
- SetCursorVisibility(false);
- return;
- }
-
- for (; node; node = ParentNode(*node)) {
- ScrollableArea* scrollable = nullptr;
- if (node->IsDocumentNode()) {
- LocalFrame* current_frame = FrameOfNode(*node);
- DCHECK(current_frame);
- scrollable = current_frame->View()->GetScrollableArea();
- } else {
- auto* layout_object = node->GetLayoutObject();
- if (!layout_object || !layout_object->IsBox()) {
- continue;
- }
-
- LayoutBox* box = ToLayoutBox(layout_object);
- if (!box->CanBeScrolledAndHasScrollableArea()) {
- continue;
- }
- scrollable = box->GetScrollableArea();
- }
-
- DCHECK(scrollable);
- if (!CanScrollAnyDirection(*scrollable))
- continue;
-
- // Found scrollable
- break;
- }
-
- current_node_ = node;
-}
-
-Element* FallbackCursorEventManager::GetFocusedElement() const {
- DCHECK(root_frame_->GetPage());
- LocalFrame* frame =
- root_frame_->GetPage()->GetFocusController().FocusedFrame();
- if (!frame || !frame->GetDocument())
- return nullptr;
-
- return frame->GetDocument()->FocusedElement();
-}
-
-bool FallbackCursorEventManager::HandleKeyBackEvent() {
- DCHECK(RuntimeEnabledFeatures::FallbackCursorModeEnabled());
-
- if (!is_fallback_cursor_mode_on_)
- return false;
-
- SetCursorVisibility(true);
- if (Element* focused_element = GetFocusedElement()) {
- focused_element->blur();
- return true;
- }
-
- ResetCurrentScrollable();
- return true;
-}
-
-void FallbackCursorEventManager::SetIsFallbackCursorModeOn(bool is_on) {
- is_fallback_cursor_mode_on_ = is_on;
- DCHECK(root_frame_->GetPage());
- root_frame_->GetPage()->GetSettings().SetSpatialNavigationEnabled(!is_on);
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/input/fallback_cursor_event_manager.h b/chromium/third_party/blink/renderer/core/input/fallback_cursor_event_manager.h
deleted file mode 100644
index 7c0bc7a7428..00000000000
--- a/chromium/third_party/blink/renderer/core/input/fallback_cursor_event_manager.h
+++ /dev/null
@@ -1,77 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_INPUT_FALLBACK_CURSOR_EVENT_MANAGER_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_INPUT_FALLBACK_CURSOR_EVENT_MANAGER_H_
-
-#include "base/gtest_prod_util.h"
-#include "base/macros.h"
-#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/platform/heap/handle.h"
-#include "third_party/blink/renderer/platform/heap/visitor.h"
-#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
-
-namespace blink {
-
-class Element;
-class Node;
-class IntPoint;
-class IntSize;
-class LocalFrame;
-class ScrollableArea;
-class WebMouseEvent;
-
-class CORE_EXPORT FallbackCursorEventManager
- : public GarbageCollected<FallbackCursorEventManager> {
- public:
- FallbackCursorEventManager(LocalFrame&);
- void Trace(Visitor*);
-
- void SetIsFallbackCursorModeOn(bool is_on);
-
- void HandleMouseMoveEvent(const WebMouseEvent&);
- void HandleMousePressEvent(const WebMouseEvent&);
- bool HandleKeyBackEvent();
-
- private:
- FRIEND_TEST_ALL_PREFIXES(FallbackCursorEventManagerTest,
- MouseMoveCursorLockOnDiv);
- FRIEND_TEST_ALL_PREFIXES(FallbackCursorEventManagerTest,
- MouseMoveCursorLockOnIFrame);
- FRIEND_TEST_ALL_PREFIXES(FallbackCursorEventManagerTest, KeyBackAndMouseMove);
- FRIEND_TEST_ALL_PREFIXES(FallbackCursorEventManagerTest, MouseDownOnEditor);
-
- enum class Direction {
- kLeft,
- kRight,
- kUp,
- kDown,
- };
-
- void ResetCurrentScrollable();
- void InvalidateCurrentScrollableIfNeeded();
- LocalFrame* CurrentScrollingFrame();
- Node* CurrentScrollingNode();
- ScrollableArea* CurrentScrollingScrollableArea();
-
- bool ShouldLock(Direction d,
- const ScrollableArea& scrollable,
- const IntSize& node_size,
- const IntPoint& cursor_location_in_node);
- void ComputeLockCursor(const IntPoint& location_in_root_frame);
- void LockCursor(bool left, bool right, bool up, bool down);
- void SetCursorVisibility(bool visible);
-
- Element* GetFocusedElement() const;
-
- const Member<LocalFrame> root_frame_;
- Member<Node> current_node_;
- bool is_fallback_cursor_mode_on_;
-
- DISALLOW_COPY_AND_ASSIGN(FallbackCursorEventManager);
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_CORE_INPUT_FALLBACK_CURSOR_EVENT_MANAGER_H_
diff --git a/chromium/third_party/blink/renderer/core/input/fallback_cursor_event_manager_test.cc b/chromium/third_party/blink/renderer/core/input/fallback_cursor_event_manager_test.cc
deleted file mode 100644
index ba05ed43673..00000000000
--- a/chromium/third_party/blink/renderer/core/input/fallback_cursor_event_manager_test.cc
+++ /dev/null
@@ -1,597 +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/core/input/fallback_cursor_event_manager.h"
-
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/common/input/web_mouse_event.h"
-#include "third_party/blink/renderer/core/dom/document.h"
-#include "third_party/blink/renderer/core/frame/local_frame.h"
-#include "third_party/blink/renderer/core/frame/visual_viewport.h"
-#include "third_party/blink/renderer/core/input/event_handler.h"
-#include "third_party/blink/renderer/core/loader/empty_clients.h"
-#include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
-#include "third_party/blink/renderer/core/testing/core_unit_test_helper.h"
-#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
-
-namespace {
-
-constexpr size_t kLeft = 0;
-constexpr size_t kRight = 1;
-constexpr size_t kUp = 2;
-constexpr size_t kDown = 3;
-
-} // namespace
-
-#define ExpectLock(l, r, u, d) \
- EXPECT_EQ(GetFallbackCursorChromeClient().cursor_lock_[kLeft], l); \
- EXPECT_EQ(GetFallbackCursorChromeClient().cursor_lock_[kRight], r); \
- EXPECT_EQ(GetFallbackCursorChromeClient().cursor_lock_[kUp], u); \
- EXPECT_EQ(GetFallbackCursorChromeClient().cursor_lock_[kDown], d);
-
-namespace blink {
-
-class FallbackCursorChromeClient : public RenderingTestChromeClient {
- public:
- FallbackCursorChromeClient() {}
-
- void FallbackCursorModeLockCursor(LocalFrame* frame,
- bool left,
- bool right,
- bool up,
- bool down) override {
- cursor_lock_[0] = left;
- cursor_lock_[1] = right;
- cursor_lock_[2] = up;
- cursor_lock_[3] = down;
- }
-
- void FallbackCursorModeSetCursorVisibility(LocalFrame* frame,
- bool visible) override {
- cursor_visible_ = visible;
- }
-
- bool cursor_lock_[4] = {0};
- bool cursor_visible_ = true;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(FallbackCursorChromeClient);
-};
-
-class FallbackCursorEventManagerTest : public RenderingTest,
- private ScopedFallbackCursorModeForTest {
- protected:
- FallbackCursorEventManagerTest()
- : RenderingTest(MakeGarbageCollected<SingleChildLocalFrameClient>()),
- ScopedFallbackCursorModeForTest(true),
- chrome_client_(MakeGarbageCollected<FallbackCursorChromeClient>()) {}
-
- ~FallbackCursorEventManagerTest() override {}
-
- RenderingTestChromeClient& GetChromeClient() const override {
- return *chrome_client_;
- }
-
- FallbackCursorChromeClient& GetFallbackCursorChromeClient() const {
- return *chrome_client_;
- }
-
- void TurnOnFallbackCursorMode() {
- GetDocument().GetFrame()->GetEventHandler().SetIsFallbackCursorModeOn(true);
- }
-
- void MouseMove(int x, int y, float scale = 1.0f) {
- WebMouseEvent event(WebInputEvent::kMouseMove, gfx::PointF(x, y),
- gfx::PointF(x, y),
- WebPointerProperties::Button::kNoButton, 0,
- WebInputEvent::kNoModifiers, base::TimeTicks::Now());
- event.SetFrameScale(scale);
- GetDocument().GetFrame()->GetEventHandler().HandleMouseMoveEvent(
- event, Vector<WebMouseEvent>(), Vector<WebMouseEvent>());
- }
-
- // Simulates a mouse move at the given point in the visual viewport (i.e. the
- // coordinates relative to the Chrome window).
- // TODO(bokan): Replace all above uses with this method.
- void MouseMoveViewport(IntPoint point) {
- VisualViewport& visual_viewport =
- GetDocument().GetPage()->GetVisualViewport();
- FloatPoint root_frame_point =
- visual_viewport.ViewportToRootFrame(FloatPoint(point));
-
- WebMouseEvent event(WebInputEvent::kMouseMove, root_frame_point,
- root_frame_point,
- WebPointerProperties::Button::kNoButton, 0,
- WebInputEvent::kNoModifiers, base::TimeTicks::Now());
- event.SetFrameScale(1.0f);
- GetDocument().GetFrame()->GetEventHandler().HandleMouseMoveEvent(
- event, Vector<WebMouseEvent>(), Vector<WebMouseEvent>());
- }
-
- void MouseDown(int x, int y) {
- WebMouseEvent event(WebInputEvent::kMouseDown, gfx::PointF(x, y),
- gfx::PointF(x, y), WebPointerProperties::Button::kLeft,
- 0, WebInputEvent::Modifiers::kLeftButtonDown,
- base::TimeTicks::Now());
- event.SetFrameScale(1);
- GetDocument().GetFrame()->GetEventHandler().HandleMousePressEvent(event);
- }
-
- bool KeyBack() {
- return GetDocument()
- .GetFrame()
- ->GetEventHandler()
- .HandleFallbackCursorModeBackEvent();
- }
-
- private:
- Persistent<FallbackCursorChromeClient> chrome_client_;
-
- DISALLOW_COPY_AND_ASSIGN(FallbackCursorEventManagerTest);
-};
-
-TEST_F(FallbackCursorEventManagerTest, RootFrameNotScrollable) {
- SetBodyInnerHTML("A");
- TurnOnFallbackCursorMode();
-
- // Mouse move to edge.
- MouseMove(0, 0);
- ExpectLock(false, false, false, false);
-
- MouseMove(0, 600);
- ExpectLock(false, false, false, false);
-
- MouseMove(800, 0);
- ExpectLock(false, false, false, false);
-
- MouseMove(800, 600);
- ExpectLock(false, false, false, false);
-}
-
-TEST_F(FallbackCursorEventManagerTest, ResetOnOutOfFrame) {
- SetBodyInnerHTML(R"HTML(
- <style>
- html, body {
- margin: 0px;
- }
- .big {
- height: 10000px;
- width: 10000px;
- }
- </style>
- <div class='big'></div>
- )HTML");
- TurnOnFallbackCursorMode();
-
- // Move below the scroll down line.
- MouseMove(100, 500);
- ExpectLock(false, false, false, true);
-
- // Ensure an invalid or out-of-bounds mouse move will reset the lock.
- MouseMove(-1, -1);
- ExpectLock(false, false, false, false);
-
- // Ensure an invalid or out-of-bounds mouse move will reset the lock.
- MouseMove(790, 590);
- ExpectLock(false, true, false, true);
-
- // Ensure an invalid or out-of-bounds mouse move will reset the lock.
- MouseMove(800, 600);
- ExpectLock(false, false, false, false);
-}
-
-TEST_F(FallbackCursorEventManagerTest, MouseMoveCursorLockOnRootFrame) {
- SetBodyInnerHTML(R"HTML(
- <style>
- html, body {
- margin: 0px;
- }
- .big {
- height: 10000px;
- width: 10000px;
- }
- </style>
- <div class='big'></div>
- )HTML");
- TurnOnFallbackCursorMode();
-
- // Move below the scroll down line.
- MouseMove(100, 500);
- ExpectLock(false, false, false, true);
-
- // Move above the scroll down line.
- MouseMove(100, 400);
- ExpectLock(false, false, false, false);
-
- // Move to the right of scroll right line.
- MouseMove(600, 400);
- ExpectLock(false, true, false, false);
-}
-
-TEST_F(FallbackCursorEventManagerTest,
- MouseMoveCursorLockOnRootFrameWithScale) {
- const float SCALE = 0.5f;
- SetBodyInnerHTML(R"HTML(
- <style>
- html, body {
- margin: 0px;
- }
- .big {
- height: 10000px;
- width: 10000px;
- }
- </style>
- <div class='big'></div>
- )HTML");
- TurnOnFallbackCursorMode();
-
- // Move below the scroll down line.
- MouseMove(50, 250, SCALE);
- ExpectLock(false, false, false, true);
-
- // Move above the scroll down line.
- MouseMove(50, 200, SCALE);
- ExpectLock(false, false, false, false);
-
- // Move to the right of scroll right line.
- MouseMove(300, 200, SCALE);
- ExpectLock(false, true, false, false);
-}
-
-TEST_F(FallbackCursorEventManagerTest, MouseMoveCursorLockOnDiv) {
- SetBodyInnerHTML(R"HTML(
- <style>
- html, body {
- margin: 0px;
- }
- .big {
- height: 10000px;
- width: 10000px;
- }
- #d1 {
- height: 100px;
- width: 100px;
- overflow: auto;
- }
- </style>
- <div id='d1'>
- <div class='big'></div>
- </div>
- )HTML");
- TurnOnFallbackCursorMode();
-
- // Move below the scroll down line but before mouse down.
- MouseMove(50, 80);
- ExpectLock(false, false, false, false);
- EXPECT_FALSE(GetDocument()
- .GetFrame()
- ->GetEventHandler()
- .fallback_cursor_event_manager_->current_node_);
-
- // Mouse down and move lock on down.
- MouseDown(50, 80);
- Element* d1 = GetDocument().getElementById("d1");
- EXPECT_EQ(GetDocument()
- .GetFrame()
- ->GetEventHandler()
- .fallback_cursor_event_manager_->current_node_.Get(),
- d1);
- MouseMove(50, 80);
- ExpectLock(false, false, false, true);
-
- // Mouse move out of div.
- MouseMove(200, 200);
- ExpectLock(false, false, false, false);
- EXPECT_FALSE(GetDocument()
- .GetFrame()
- ->GetEventHandler()
- .fallback_cursor_event_manager_->current_node_);
-
- // key back.
- MouseMove(50, 80);
- MouseDown(50, 80);
- EXPECT_EQ(GetDocument()
- .GetFrame()
- ->GetEventHandler()
- .fallback_cursor_event_manager_->current_node_.Get(),
- d1);
- EXPECT_TRUE(KeyBack());
- EXPECT_FALSE(GetDocument()
- .GetFrame()
- ->GetEventHandler()
- .fallback_cursor_event_manager_->current_node_);
-}
-
-TEST_F(FallbackCursorEventManagerTest, MouseMoveCursorLockOnIFrame) {
- SetBodyInnerHTML(R"HTML(
- <style>
- html, body {
- margin: 0px;
- }
- #ifr {
- height: 100px;
- width: 100px;
- }
- </style>
- <iframe id='ifr'></iframe>
- )HTML");
-
- SetChildFrameHTML(R"HTML(
- <style>
- html, body {
- margin: 0px;
- }
- .big {
- height: 10000px;
- width: 10000px;
- }
- </style>
- <div class='big'></div>
- )HTML");
- TurnOnFallbackCursorMode();
-
- // Move below the scroll down line but before mouse down.
- MouseMove(50, 80);
- ExpectLock(false, false, false, false);
- EXPECT_FALSE(GetDocument()
- .GetFrame()
- ->GetEventHandler()
- .fallback_cursor_event_manager_->current_node_);
-
- // Mouse down and move lock on down.
- MouseDown(50, 80);
- MouseMove(50, 80);
- ExpectLock(false, false, false, true);
- Node* child_frame_doc = ChildFrame().GetDocument();
- EXPECT_EQ(GetDocument()
- .GetFrame()
- ->GetEventHandler()
- .fallback_cursor_event_manager_->current_node_.Get(),
- child_frame_doc);
-
- // Mouse move out of iframe.
- MouseMove(200, 200);
- ExpectLock(false, false, false, false);
- EXPECT_FALSE(GetDocument()
- .GetFrame()
- ->GetEventHandler()
- .fallback_cursor_event_manager_->current_node_);
-
- // key back.
- MouseMove(50, 80);
- MouseDown(50, 80);
- EXPECT_EQ(GetDocument()
- .GetFrame()
- ->GetEventHandler()
- .fallback_cursor_event_manager_->current_node_.Get(),
- child_frame_doc);
- EXPECT_TRUE(KeyBack());
- EXPECT_FALSE(GetDocument()
- .GetFrame()
- ->GetEventHandler()
- .fallback_cursor_event_manager_->current_node_);
-}
-
-TEST_F(FallbackCursorEventManagerTest, KeyBackAndMouseMove) {
- SetBodyInnerHTML(R"HTML(
- <style>
- html, body {
- margin: 0px;
- }
- #ifr {
- height: 100px;
- width: 100px;
- }
- div {
- height: 10000px;
- width: 10000px;
- }
- </style>
- <iframe id='ifr'></iframe>
- <div></div>
- )HTML");
-
- SetChildFrameHTML(R"HTML(
- <style>
- html, body {
- margin: 0px;
- }
- .big {
- height: 10000px;
- width: 10000px;
- }
- </style>
- <div class='big'></div>
- )HTML");
- TurnOnFallbackCursorMode();
-
- // Move below the scroll down line but before mouse down.
- MouseMove(50, 80);
- ExpectLock(false, false, false, false);
- EXPECT_FALSE(GetDocument()
- .GetFrame()
- ->GetEventHandler()
- .fallback_cursor_event_manager_->current_node_);
-
- // Mouse down and move lock on down.
- MouseDown(50, 80);
- MouseMove(50, 80);
- ExpectLock(false, false, false, true);
- Node* child_frame_doc = ChildFrame().GetDocument();
- EXPECT_EQ(GetDocument()
- .GetFrame()
- ->GetEventHandler()
- .fallback_cursor_event_manager_->current_node_.Get(),
- child_frame_doc);
-
- // key back.
- EXPECT_TRUE(KeyBack());
- EXPECT_FALSE(GetDocument()
- .GetFrame()
- ->GetEventHandler()
- .fallback_cursor_event_manager_->current_node_);
-
- // Move below the scroll down line of page.
- MouseMove(100, 500);
- ExpectLock(false, false, false, true);
-}
-
-TEST_F(FallbackCursorEventManagerTest, MouseDownOnEditor) {
- SetBodyInnerHTML(R"HTML(
- <style>
- html, body {
- margin: 0px;
- }
- #editor {
- height: 100px;
- width: 100px;
- }
- </style>
- <div id='editor' contenteditable='true'>
- </div>
- )HTML");
- TurnOnFallbackCursorMode();
-
- MouseMove(50, 80);
- MouseDown(50, 80);
-
- EXPECT_EQ(GetFallbackCursorChromeClient().cursor_visible_, false);
-
- Element* editor = GetDocument().getElementById("editor");
- EXPECT_EQ(GetDocument().FocusedElement(), editor);
-
- EXPECT_TRUE(KeyBack());
-
- EXPECT_EQ(GetFallbackCursorChromeClient().cursor_visible_, true);
- EXPECT_FALSE(GetDocument().FocusedElement());
-}
-
-// Ensure the cursor causes correct locking and scrolling when the web page is
-// zoomed in and the visual viewport is offset.
-TEST_F(FallbackCursorEventManagerTest, ZoomedIn) {
- SetBodyInnerHTML(R"HTML(
- <style>
- html, body {
- margin: 0px;
- }
- .big {
- height: 10000px;
- width: 10000px;
- }
- </style>
- <div class='big'></div>
- )HTML");
- TurnOnFallbackCursorMode();
- VisualViewport& visual_viewport =
- GetDocument().GetPage()->GetVisualViewport();
- visual_viewport.SetScaleAndLocation(4, /*is_pinch_gesture_active=*/false,
- FloatPoint(400, 300));
-
- ASSERT_EQ(IntSize(800, 600), GetDocument().View()->Size());
- ASSERT_EQ(FloatSize(200, 150), visual_viewport.VisibleRect().Size());
-
- // Move to the center of the viewport.
- MouseMoveViewport(IntPoint(400, 300));
- ExpectLock(false, false, false, false);
-
- // Move below the scroll down line.
- MouseMoveViewport(IntPoint(400, 550));
- ExpectLock(false, false, false, true);
-
- // Move to the left of scroll left line.
- MouseMoveViewport(IntPoint(50, 300));
- ExpectLock(true, false, false, false);
-}
-
-// Ensure the cursor causes correct locking in the presence of overflow:hidden.
-TEST_F(FallbackCursorEventManagerTest, AccountsForOverflowHidden) {
- SetBodyInnerHTML(R"HTML(
- <style>
- html, body {
- margin: 0px;
- }
- html {
- overflow-x: hidden;
- }
- .big {
- height: 10000px;
- width: 10000px;
- }
- </style>
- <div class='big'></div>
- )HTML");
- TurnOnFallbackCursorMode();
- VisualViewport& visual_viewport =
- GetDocument().GetPage()->GetVisualViewport();
-
- // Start fully zoomed out.
- ASSERT_EQ(IntSize(800, 600), GetDocument().View()->Size());
- ASSERT_EQ(FloatSize(800, 600), visual_viewport.VisibleRect().Size());
-
- // Move to the center of the viewport.
- MouseMoveViewport(IntPoint(400, 300));
- ExpectLock(false, false, false, false);
-
- // Move to the right scroll region. We don't expect to lock because the visual
- // viewport has no scroll extent. The layout viewport has scroll extent but
- // is limited by overflow-x:hidden.
- MouseMoveViewport(IntPoint(750, 300));
- ExpectLock(false, false, false, false);
-
- // Move to the bottom scroll region. Since only overflow-x is hidden, this
- // should cause locking in the down direction.
- MouseMoveViewport(IntPoint(400, 550));
- ExpectLock(false, false, false, true);
-
- // Now zoom in. Make sure we can still scroll the visual viewport but not the
- // layout.
- visual_viewport.SetScaleAndLocation(4, /*is_pinch_gesture_active=*/false,
- FloatPoint(0, 0));
- ASSERT_EQ(IntSize(800, 600), GetDocument().View()->Size());
- ASSERT_EQ(FloatSize(200, 150), visual_viewport.VisibleRect().Size());
-
- // Move to the right scroll region; since the visual viewport can scroll, we
- // should expect to lock to the right.
- MouseMoveViewport(IntPoint(750, 300));
- ExpectLock(false, true, false, false);
-
- // Now move the visual viewport to the bottom right corner of the layout
- // viewport.
- visual_viewport.SetScaleAndLocation(4, /*is_pinch_gesture_active=*/false,
- FloatPoint(600, 450));
-
- // Move mouse to the right scroll region. Since the visual viewport is at the
- // extent, and the layout viewport isn't user scrollable, we shouldn't cause
- // locking.
- MouseMoveViewport(IntPoint(750, 350));
- ExpectLock(false, false, false, false);
-
- // Move the mouse to the bottom scroll region, we should expect to lock
- // because the layout viewport can scroll vertically, even though the visual
- // viewport is at the extent.
- MouseMoveViewport(IntPoint(750, 550));
- ExpectLock(false, false, false, true);
-
- // Move the mouse to the bottom scroll region, we should expect to lock
- // because the layout viewport can scroll vertically, even though the visual
- // viewport is at the extent.
- MouseMoveViewport(IntPoint(745, 550));
- ExpectLock(false, false, false, true);
-
- // Fully scroll the layout viewport to the bottom.
- GetDocument().View()->LayoutViewport()->SetScrollOffset(
- ScrollOffset(0, 100000), mojom::blink::ScrollType::kProgrammatic);
-
- // Move the mouse to the bottom of the viewport, we shouldn't lock because
- // both layout and visual are at the extent.
- MouseMoveViewport(IntPoint(740, 550));
- ExpectLock(false, false, false, false);
-}
-
-TEST_F(FallbackCursorEventManagerTest, NotInCursorMode) {
- GetPage().SetIsCursorVisible(false);
- EXPECT_FALSE(KeyBack());
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/input/gesture_manager.cc b/chromium/third_party/blink/renderer/core/input/gesture_manager.cc
index d28ddfd464f..e07a04bad9e 100644
--- a/chromium/third_party/blink/renderer/core/input/gesture_manager.cc
+++ b/chromium/third_party/blink/renderer/core/input/gesture_manager.cc
@@ -68,21 +68,21 @@ HitTestRequest::HitTestRequestType GestureManager::GetHitTypeForGestureType(
HitTestRequest::HitTestRequestType hit_type =
HitTestRequest::kTouchEvent | HitTestRequest::kRetargetForInert;
switch (type) {
- case WebInputEvent::kGestureShowPress:
- case WebInputEvent::kGestureTapUnconfirmed:
+ case WebInputEvent::Type::kGestureShowPress:
+ case WebInputEvent::Type::kGestureTapUnconfirmed:
return hit_type | HitTestRequest::kActive;
- case WebInputEvent::kGestureTapCancel:
+ case WebInputEvent::Type::kGestureTapCancel:
// A TapDownCancel received when no element is active shouldn't really be
// changing hover state.
if (!frame_->GetDocument()->GetActiveElement())
hit_type |= HitTestRequest::kReadOnly;
return hit_type | HitTestRequest::kRelease;
- case WebInputEvent::kGestureTap:
+ case WebInputEvent::Type::kGestureTap:
return hit_type | HitTestRequest::kRelease;
- case WebInputEvent::kGestureTapDown:
- case WebInputEvent::kGestureLongPress:
- case WebInputEvent::kGestureLongTap:
- case WebInputEvent::kGestureTwoFingerTap:
+ case WebInputEvent::Type::kGestureTapDown:
+ case WebInputEvent::Type::kGestureLongPress:
+ case WebInputEvent::Type::kGestureLongTap:
+ case WebInputEvent::Type::kGestureTwoFingerTap:
// FIXME: Shouldn't LongTap and TwoFingerTap clear the Active state?
return hit_type | HitTestRequest::kActive | HitTestRequest::kReadOnly;
default:
@@ -117,20 +117,20 @@ WebInputEventResult GestureManager::HandleGestureEventInFrame(
}
switch (gesture_event.GetType()) {
- case WebInputEvent::kGestureTapDown:
+ case WebInputEvent::Type::kGestureTapDown:
return HandleGestureTapDown(targeted_event);
- case WebInputEvent::kGestureTap:
+ case WebInputEvent::Type::kGestureTap:
return HandleGestureTap(targeted_event);
- case WebInputEvent::kGestureShowPress:
+ case WebInputEvent::Type::kGestureShowPress:
return HandleGestureShowPress();
- case WebInputEvent::kGestureLongPress:
+ case WebInputEvent::Type::kGestureLongPress:
return HandleGestureLongPress(targeted_event);
- case WebInputEvent::kGestureLongTap:
+ case WebInputEvent::Type::kGestureLongTap:
return HandleGestureLongTap(targeted_event);
- case WebInputEvent::kGestureTwoFingerTap:
+ case WebInputEvent::Type::kGestureTwoFingerTap:
return HandleGestureTwoFingerTap(targeted_event);
- case WebInputEvent::kGestureTapCancel:
- case WebInputEvent::kGestureTapUnconfirmed:
+ case WebInputEvent::Type::kGestureTapCancel:
+ case WebInputEvent::Type::kGestureTapUnconfirmed:
break;
default:
NOTREACHED();
@@ -174,7 +174,7 @@ WebInputEventResult GestureManager::HandleGestureTap(
if (!suppress_mouse_events_from_gestures_) {
WebMouseEvent fake_mouse_move(
- WebInputEvent::kMouseMove, gesture_event,
+ WebInputEvent::Type::kMouseMove, gesture_event,
WebPointerProperties::Button::kNoButton,
/* clickCount */ 0,
static_cast<WebInputEvent::Modifiers>(
@@ -216,7 +216,7 @@ WebInputEventResult GestureManager::HandleGestureTap(
mouse_event_manager_->SetClickElement(tapped_element);
WebMouseEvent fake_mouse_down(
- WebInputEvent::kMouseDown, gesture_event,
+ WebInputEvent::Type::kMouseDown, gesture_event,
WebPointerProperties::Button::kLeft, gesture_event.TapCount(),
static_cast<WebInputEvent::Modifiers>(
modifiers | WebInputEvent::Modifiers::kLeftButtonDown |
@@ -250,7 +250,7 @@ WebInputEventResult GestureManager::HandleGestureTap(
}
if (current_hit_test.InnerNode()) {
- DCHECK(gesture_event.GetType() == WebInputEvent::kGestureTap);
+ DCHECK(gesture_event.GetType() == WebInputEvent::Type::kGestureTap);
HitTestResult result = current_hit_test;
result.SetToShadowHostIfInRestrictedShadowRoot();
frame_->GetChromeClient().OnMouseDown(*result.InnerNode());
@@ -268,7 +268,7 @@ WebInputEventResult GestureManager::HandleGestureTap(
}
WebMouseEvent fake_mouse_up(
- WebInputEvent::kMouseUp, gesture_event,
+ WebInputEvent::Type::kMouseUp, gesture_event,
WebPointerProperties::Button::kLeft, gesture_event.TapCount(),
static_cast<WebInputEvent::Modifiers>(
modifiers | WebInputEvent::Modifiers::kIsCompatibilityEventForTouch),
@@ -397,7 +397,7 @@ WebInputEventResult GestureManager::SendContextMenuEventForGesture(
if (!suppress_mouse_events_from_gestures_) {
// Send MouseMove event prior to handling (https://crbug.com/485290).
WebMouseEvent fake_mouse_move(
- WebInputEvent::kMouseMove, gesture_event,
+ WebInputEvent::Type::kMouseMove, gesture_event,
WebPointerProperties::Button::kNoButton,
/* clickCount */ 0,
static_cast<WebInputEvent::Modifiers>(
@@ -409,10 +409,10 @@ WebInputEventResult GestureManager::SendContextMenuEventForGesture(
fake_mouse_move);
}
- WebInputEvent::Type event_type = WebInputEvent::kMouseDown;
+ WebInputEvent::Type event_type = WebInputEvent::Type::kMouseDown;
if (frame_->GetSettings() &&
frame_->GetSettings()->GetShowContextMenuOnMouseUp())
- event_type = WebInputEvent::kMouseUp;
+ event_type = WebInputEvent::Type::kMouseUp;
WebMouseEvent mouse_event(
event_type, gesture_event, WebPointerProperties::Button::kNoButton,
diff --git a/chromium/third_party/blink/renderer/core/input/ime_on_focus_test.cc b/chromium/third_party/blink/renderer/core/input/ime_on_focus_test.cc
index 5f3bfe5bba5..7f1b17bd74f 100644
--- a/chromium/third_party/blink/renderer/core/input/ime_on_focus_test.cc
+++ b/chromium/third_party/blink/renderer/core/input/ime_on_focus_test.cc
@@ -3,7 +3,7 @@
// found in the LICENSE file.
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/platform/web_coalesced_input_event.h"
+#include "third_party/blink/public/common/input/web_coalesced_input_event.h"
#include "third_party/blink/public/platform/web_url_loader_mock_factory.h"
#include "third_party/blink/public/web/web_document.h"
#include "third_party/blink/renderer/core/dom/document.h"
@@ -63,7 +63,7 @@ class ImeOnFocusTest : public testing::Test {
};
void ImeOnFocusTest::SendGestureTap(WebView* web_view, IntPoint client_point) {
- WebGestureEvent web_gesture_event(WebInputEvent::kGestureTap,
+ WebGestureEvent web_gesture_event(WebInputEvent::Type::kGestureTap,
WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests(),
WebGestureDevice::kTouchscreen);
@@ -75,7 +75,7 @@ void ImeOnFocusTest::SendGestureTap(WebView* web_view, IntPoint client_point) {
web_gesture_event.data.tap.height = 10;
web_view->MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(web_gesture_event));
+ WebCoalescedInputEvent(web_gesture_event, ui::LatencyInfo()));
RunPendingTasks();
}
diff --git a/chromium/third_party/blink/renderer/core/input/input_device_capabilities.idl b/chromium/third_party/blink/renderer/core/input/input_device_capabilities.idl
index 341f71ebb80..e7f2fb4ee25 100644
--- a/chromium/third_party/blink/renderer/core/input/input_device_capabilities.idl
+++ b/chromium/third_party/blink/renderer/core/input/input_device_capabilities.idl
@@ -11,7 +11,9 @@
// https://wicg.github.io/InputDeviceCapabilities/#the-inputdevicecapabilities-interface
-interface InputDeviceCapabilities {
+[
+ Exposed=Window
+] interface InputDeviceCapabilities {
constructor(optional InputDeviceCapabilitiesInit deviceInitDict = {});
// Whether this device dispatches touch events for movement. This is used to detect
diff --git a/chromium/third_party/blink/renderer/core/input/keyboard_event_manager.cc b/chromium/third_party/blink/renderer/core/input/keyboard_event_manager.cc
index 8589587194d..67f5c368ab5 100644
--- a/chromium/third_party/blink/renderer/core/input/keyboard_event_manager.cc
+++ b/chromium/third_party/blink/renderer/core/input/keyboard_event_manager.cc
@@ -30,6 +30,7 @@
#include "third_party/blink/renderer/core/page/spatial_navigation.h"
#include "third_party/blink/renderer/core/page/spatial_navigation_controller.h"
#include "third_party/blink/renderer/platform/keyboard_codes.h"
+#include "third_party/blink/renderer/platform/widget/frame_widget.h"
#include "third_party/blink/renderer/platform/windows_keyboard_codes.h"
#include "ui/events/keycodes/dom/keycode_converter.h"
@@ -44,7 +45,6 @@ namespace blink {
namespace {
const int kVKeyProcessKey = 229;
-const int kVKeySpatNavBack = 233;
bool MapKeyCodeForScroll(int key_code,
WebInputEvent::Modifiers modifiers,
@@ -184,8 +184,8 @@ WebInputEventResult KeyboardEventManager::KeyEvent(
DCHECK(RuntimeEnabledFeatures::MiddleClickAutoscrollEnabled());
// If a key is pressed while the middleClickAutoscroll is in progress then
// we want to stop.
- if (initial_key_event.GetType() == WebInputEvent::kKeyDown ||
- initial_key_event.GetType() == WebInputEvent::kRawKeyDown)
+ if (initial_key_event.GetType() == WebInputEvent::Type::kKeyDown ||
+ initial_key_event.GetType() == WebInputEvent::Type::kRawKeyDown)
scroll_manager_->StopMiddleClickAutoscroll();
// If we were in panscroll mode, we swallow the key event
@@ -205,8 +205,8 @@ WebInputEventResult KeyboardEventManager::KeyEvent(
static_cast<ui::DomKey>(initial_key_event.dom_key));
if (!is_modifier && initial_key_event.dom_key != ui::DomKey::ESCAPE &&
- (initial_key_event.GetType() == WebInputEvent::kKeyDown ||
- initial_key_event.GetType() == WebInputEvent::kRawKeyDown)) {
+ (initial_key_event.GetType() == WebInputEvent::Type::kKeyDown ||
+ initial_key_event.GetType() == WebInputEvent::Type::kRawKeyDown)) {
LocalFrame::NotifyUserActivation(
frame_,
RuntimeEnabledFeatures::BrowserVerifiedUserActivationKeyboardEnabled());
@@ -222,7 +222,7 @@ WebInputEventResult KeyboardEventManager::KeyEvent(
// currently match either Mac or Windows behavior, depending on whether they
// send combined KeyDown events.
bool matched_an_access_key = false;
- if (initial_key_event.GetType() == WebInputEvent::kKeyDown)
+ if (initial_key_event.GetType() == WebInputEvent::Type::kKeyDown)
matched_an_access_key = HandleAccessKey(initial_key_event);
// Don't expose key events to pages while browsing on the drive-by web. This
@@ -236,8 +236,8 @@ WebInputEventResult KeyboardEventManager::KeyEvent(
if (!should_send_key_events_to_js &&
frame_->GetDocument()->IsInWebAppScope()) {
- DCHECK(frame_->View());
- blink::mojom::DisplayMode display_mode = frame_->View()->DisplayMode();
+ mojom::blink::DisplayMode display_mode =
+ frame_->GetWidgetForLocalRoot()->DisplayMode();
should_send_key_events_to_js =
display_mode == blink::mojom::DisplayMode::kMinimalUi ||
display_mode == blink::mojom::DisplayMode::kStandalone ||
@@ -271,8 +271,8 @@ WebInputEventResult KeyboardEventManager::KeyEvent(
// TODO: it would be fair to let an input method handle KeyUp events
// before DOM dispatch.
- if (initial_key_event.GetType() == WebInputEvent::kKeyUp ||
- initial_key_event.GetType() == WebInputEvent::kChar) {
+ if (initial_key_event.GetType() == WebInputEvent::Type::kKeyUp ||
+ initial_key_event.GetType() == WebInputEvent::Type::kChar) {
KeyboardEvent* dom_event = KeyboardEvent::Create(
initial_key_event, frame_->GetDocument()->domWindow(),
event_cancellable);
@@ -284,8 +284,8 @@ WebInputEventResult KeyboardEventManager::KeyEvent(
}
WebKeyboardEvent key_down_event = initial_key_event;
- if (key_down_event.GetType() != WebInputEvent::kRawKeyDown)
- key_down_event.SetType(WebInputEvent::kRawKeyDown);
+ if (key_down_event.GetType() != WebInputEvent::Type::kRawKeyDown)
+ key_down_event.SetType(WebInputEvent::Type::kRawKeyDown);
KeyboardEvent* keydown = KeyboardEvent::Create(
key_down_event, frame_->GetDocument()->domWindow(), event_cancellable);
if (matched_an_access_key)
@@ -311,7 +311,7 @@ WebInputEventResult KeyboardEventManager::KeyEvent(
if (changed_focused_frame)
return WebInputEventResult::kHandledSystem;
- if (initial_key_event.GetType() == WebInputEvent::kRawKeyDown)
+ if (initial_key_event.GetType() == WebInputEvent::Type::kRawKeyDown)
return WebInputEventResult::kNotHandled;
// Focus may have changed during keydown handling, so refetch node.
@@ -333,7 +333,7 @@ WebInputEventResult KeyboardEventManager::KeyEvent(
#endif
WebKeyboardEvent key_press_event = initial_key_event;
- key_press_event.SetType(WebInputEvent::kChar);
+ key_press_event.SetType(WebInputEvent::Type::kChar);
if (key_press_event.text[0] == 0)
return WebInputEventResult::kNotHandled;
KeyboardEvent* keypress = KeyboardEvent::Create(
@@ -396,8 +396,6 @@ void KeyboardEventManager::DefaultKeyboardEventHandler(
return;
if (event->key() == "Enter") {
DefaultEnterEventHandler(event);
- } else if (event->keyCode() == kVKeySpatNavBack) {
- DefaultSpatNavBackEventHandler(event);
}
}
}
@@ -465,40 +463,80 @@ void KeyboardEventManager::DefaultArrowEventHandler(
}
void KeyboardEventManager::DefaultTabEventHandler(KeyboardEvent* event) {
+ // TODO (liviutinta) remove TRACE after fixing crbug.com/1063548
+ TRACE_EVENT0("input", "KeyboardEventManager::DefaultTabEventHandler");
DCHECK_EQ(event->type(), event_type_names::kKeydown);
-
// We should only advance focus on tabs if no special modifier keys are held
// down.
- if (event->ctrlKey() || event->metaKey())
+ if (event->ctrlKey() || event->metaKey()) {
+ // TODO (liviutinta) remove TRACE after fixing crbug.com/1063548
+ TRACE_EVENT_INSTANT1(
+ "input", "KeyboardEventManager::DefaultTabEventHandler",
+ TRACE_EVENT_SCOPE_THREAD, "reason_tab_does_not_advance_focus",
+ (event->ctrlKey() ? (event->metaKey() ? "Ctrl+MetaKey+Tab" : "Ctrl+Tab")
+ : "MetaKey+Tab"));
return;
+ }
#if !defined(OS_MACOSX)
// Option-Tab is a shortcut based on a system-wide preference on Mac but
// should be ignored on all other platforms.
- if (event->altKey())
+ if (event->altKey()) {
+ // TODO (liviutinta) remove TRACE after fixing crbug.com/1063548
+ TRACE_EVENT_INSTANT1("input",
+ "KeyboardEventManager::DefaultTabEventHandler",
+ TRACE_EVENT_SCOPE_THREAD,
+ "reason_tab_does_not_advance_focus", "Alt+Tab");
return;
+ }
#endif
Page* page = frame_->GetPage();
- if (!page)
+ if (!page) {
+ // TODO (liviutinta) remove TRACE after fixing crbug.com/1063548
+ TRACE_EVENT_INSTANT1("input",
+ "KeyboardEventManager::DefaultTabEventHandler",
+ TRACE_EVENT_SCOPE_THREAD,
+ "reason_tab_does_not_advance_focus", "Page is null");
return;
- if (!page->TabKeyCyclesThroughElements())
+ }
+ if (!page->TabKeyCyclesThroughElements()) {
+ // TODO (liviutinta) remove TRACE after fixing crbug.com/1063548
+ TRACE_EVENT_INSTANT1(
+ "input", "KeyboardEventManager::DefaultTabEventHandler",
+ TRACE_EVENT_SCOPE_THREAD, "reason_tab_does_not_advance_focus",
+ "TabKeyCyclesThroughElements is false");
return;
+ }
mojom::blink::FocusType focus_type = event->shiftKey()
? mojom::blink::FocusType::kBackward
: mojom::blink::FocusType::kForward;
// Tabs can be used in design mode editing.
- if (frame_->GetDocument()->InDesignMode())
+ if (frame_->GetDocument()->InDesignMode()) {
+ // TODO (liviutinta) remove TRACE after fixing crbug.com/1063548
+ TRACE_EVENT_INSTANT1(
+ "input", "KeyboardEventManager::DefaultTabEventHandler",
+ TRACE_EVENT_SCOPE_THREAD, "reason_tab_does_not_advance_focus",
+ "DesignMode is true");
return;
+ }
if (page->GetFocusController().AdvanceFocus(focus_type,
frame_->GetDocument()
->domWindow()
->GetInputDeviceCapabilities()
- ->FiresTouchEvents(false)))
+ ->FiresTouchEvents(false))) {
event->SetDefaultHandled();
+ } else {
+ // TODO (liviutinta) remove TRACE after fixing crbug.com/1063548
+ TRACE_EVENT_INSTANT1(
+ "input", "KeyboardEventManager::DefaultTabEventHandler",
+ TRACE_EVENT_SCOPE_THREAD, "reason_tab_does_not_advance_focus",
+ "AdvanceFocus returned false");
+ return;
+ }
}
void KeyboardEventManager::DefaultEscapeEventHandler(KeyboardEvent* event) {
@@ -515,34 +553,6 @@ void KeyboardEventManager::DefaultEscapeEventHandler(KeyboardEvent* event) {
dialog->DispatchEvent(*Event::CreateCancelable(event_type_names::kCancel));
}
-bool KeyboardEventManager::DefaultSpatNavBackEventHandler(
- KeyboardEvent* event) {
- if (RuntimeEnabledFeatures::FallbackCursorModeEnabled()) {
- bool handled = frame_->LocalFrameRoot()
- .GetEventHandler()
- .HandleFallbackCursorModeBackEvent();
- if (handled) {
- event->SetDefaultHandled();
- return true;
- }
- }
-
- if (IsSpatialNavigationEnabled(frame_) &&
- !frame_->GetDocument()->InDesignMode()) {
- Page* page = frame_->GetPage();
- if (!page)
- return false;
- bool handled =
- page->GetSpatialNavigationController().HandleEscapeKeyboardEvent(event);
- if (handled) {
- event->SetDefaultHandled();
- return true;
- }
- }
-
- return false;
-}
-
void KeyboardEventManager::DefaultEnterEventHandler(KeyboardEvent* event) {
Page* page = frame_->GetPage();
if (!page)
diff --git a/chromium/third_party/blink/renderer/core/input/keyboard_event_manager.h b/chromium/third_party/blink/renderer/core/input/keyboard_event_manager.h
index c1d28376037..7ffe289af7c 100644
--- a/chromium/third_party/blink/renderer/core/input/keyboard_event_manager.h
+++ b/chromium/third_party/blink/renderer/core/input/keyboard_event_manager.h
@@ -57,7 +57,6 @@ class CORE_EXPORT KeyboardEventManager final
void DefaultEnterEventHandler(KeyboardEvent*);
void DefaultImeSubmitHandler(KeyboardEvent*);
void DefaultArrowEventHandler(KeyboardEvent*, Node*);
- bool DefaultSpatNavBackEventHandler(KeyboardEvent*);
const Member<LocalFrame> frame_;
diff --git a/chromium/third_party/blink/renderer/core/input/mouse_event_manager.cc b/chromium/third_party/blink/renderer/core/input/mouse_event_manager.cc
index b77c990e74f..33b4179ed74 100644
--- a/chromium/third_party/blink/renderer/core/input/mouse_event_manager.cc
+++ b/chromium/third_party/blink/renderer/core/input/mouse_event_manager.cc
@@ -74,7 +74,8 @@ void UpdateMouseMovementXY(const WebMouseEvent& mouse_event,
MouseEventInit* initializer) {
if (RuntimeEnabledFeatures::ConsolidatedMovementXYEnabled() &&
!mouse_event.is_raw_movement_event &&
- mouse_event.GetType() == WebInputEvent::kMouseMove && last_position) {
+ mouse_event.GetType() == WebInputEvent::Type::kMouseMove &&
+ last_position) {
// TODO(crbug.com/907309): Current movementX/Y is in physical pixel when
// zoom-for-dsf is enabled. Here we apply the device-scale-factor to align
// with the current behavior. We need to figure out what is the best
@@ -462,7 +463,7 @@ void MouseEventManager::RecomputeMouseHoverState() {
button = WebPointerProperties::Button::kLeft;
modifiers |= WebInputEvent::kLeftButtonDown;
}
- WebMouseEvent fake_mouse_move_event(WebInputEvent::kMouseMove,
+ WebMouseEvent fake_mouse_move_event(WebInputEvent::Type::kMouseMove,
last_known_mouse_position_,
last_known_mouse_screen_position_, button,
0, modifiers, base::TimeTicks::Now());
@@ -673,7 +674,8 @@ FloatPoint MouseEventManager::LastKnownMouseScreenPosition() {
}
void MouseEventManager::SetLastKnownMousePosition(const WebMouseEvent& event) {
- is_mouse_position_unknown_ = event.GetType() == WebInputEvent::kMouseLeave;
+ is_mouse_position_unknown_ =
+ event.GetType() == WebInputEvent::Type::kMouseLeave;
last_known_mouse_position_ = FloatPoint(event.PositionInWidget());
last_known_mouse_screen_position_ = FloatPoint(event.PositionInScreen());
}
@@ -775,7 +777,7 @@ bool MouseEventManager::HandleDragDropIfPossible(
// TODO(mustaq): Suppressing long-tap MouseEvents could break
// drag-drop. Will do separately because of the risk. crbug.com/606938.
WebMouseEvent mouse_down_event(
- WebInputEvent::kMouseDown, gesture_event,
+ WebInputEvent::Type::kMouseDown, gesture_event,
WebPointerProperties::Button::kLeft, 1,
modifiers | WebInputEvent::Modifiers::kLeftButtonDown |
WebInputEvent::Modifiers::kIsCompatibilityEventForTouch,
@@ -783,7 +785,7 @@ bool MouseEventManager::HandleDragDropIfPossible(
mouse_down_ = mouse_down_event;
WebMouseEvent mouse_drag_event(
- WebInputEvent::kMouseMove, gesture_event,
+ WebInputEvent::Type::kMouseMove, gesture_event,
WebPointerProperties::Button::kLeft, 1,
modifiers | WebInputEvent::Modifiers::kLeftButtonDown |
WebInputEvent::Modifiers::kIsCompatibilityEventForTouch,
@@ -831,7 +833,8 @@ WebInputEventResult MouseEventManager::HandleMouseDraggedEvent(
// When pressing Esc key while dragging and the object is outside of the
// we get a mouse leave event here.
- if (!mouse_pressed_ || event.Event().GetType() == WebInputEvent::kMouseLeave)
+ if (!mouse_pressed_ ||
+ event.Event().GetType() == WebInputEvent::Type::kMouseLeave)
return WebInputEventResult::kNotHandled;
// We disable the drag and drop actions on pen input on windows.
@@ -891,7 +894,7 @@ WebInputEventResult MouseEventManager::HandleMouseDraggedEvent(
bool MouseEventManager::HandleDrag(const MouseEventWithHitTestResults& event,
DragInitiator initiator) {
- DCHECK(event.Event().GetType() == WebInputEvent::kMouseMove);
+ DCHECK(event.Event().GetType() == WebInputEvent::Type::kMouseMove);
// Callers must protect the reference to LocalFrameView, since this function
// may dispatch DOM events, causing page/LocalFrameView to go away.
DCHECK(frame_);
diff --git a/chromium/third_party/blink/renderer/core/input/overscroll_behavior_test.cc b/chromium/third_party/blink/renderer/core/input/overscroll_behavior_test.cc
index d054a8a497a..f38410ae7f4 100644
--- a/chromium/third_party/blink/renderer/core/input/overscroll_behavior_test.cc
+++ b/chromium/third_party/blink/renderer/core/input/overscroll_behavior_test.cc
@@ -70,7 +70,7 @@ void OverscrollBehaviorTest::SetInnerOverscrollBehavior(EOverscrollBehavior x,
}
void OverscrollBehaviorTest::ScrollBegin(double hint_x, double hint_y) {
- WebGestureEvent event(WebInputEvent::kGestureScrollBegin,
+ WebGestureEvent event(WebInputEvent::Type::kGestureScrollBegin,
WebInputEvent::kNoModifiers, base::TimeTicks::Now(),
WebGestureDevice::kTouchscreen);
event.SetPositionInWidget(gfx::PointF(20, 20));
@@ -83,7 +83,7 @@ void OverscrollBehaviorTest::ScrollBegin(double hint_x, double hint_y) {
}
void OverscrollBehaviorTest::ScrollUpdate(double delta_x, double delta_y) {
- WebGestureEvent event(WebInputEvent::kGestureScrollUpdate,
+ WebGestureEvent event(WebInputEvent::Type::kGestureScrollUpdate,
WebInputEvent::kNoModifiers, base::TimeTicks::Now(),
WebGestureDevice::kTouchscreen);
event.SetPositionInWidget(gfx::PointF(20, 20));
@@ -95,7 +95,7 @@ void OverscrollBehaviorTest::ScrollUpdate(double delta_x, double delta_y) {
}
void OverscrollBehaviorTest::ScrollEnd() {
- WebGestureEvent event(WebInputEvent::kGestureScrollEnd,
+ WebGestureEvent event(WebInputEvent::Type::kGestureScrollEnd,
WebInputEvent::kNoModifiers, base::TimeTicks::Now(),
WebGestureDevice::kTouchscreen);
event.SetPositionInWidget(gfx::PointF(20, 20));
diff --git a/chromium/third_party/blink/renderer/core/input/pointer_event_manager.cc b/chromium/third_party/blink/renderer/core/input/pointer_event_manager.cc
index 6a68b124069..6c62af01ad2 100644
--- a/chromium/third_party/blink/renderer/core/input/pointer_event_manager.cc
+++ b/chromium/third_party/blink/renderer/core/input/pointer_event_manager.cc
@@ -228,7 +228,7 @@ void PointerEventManager::SendMouseAndPointerBoundaryEvents(
// Mouse event type does not matter as this pointerevent will only be used
// to create boundary pointer events and its type will be overridden in
// |sendBoundaryEvents| function.
- const WebPointerEvent web_pointer_event(WebInputEvent::kPointerMove,
+ const WebPointerEvent web_pointer_event(WebInputEvent::Type::kPointerMove,
mouse_event);
PointerEvent* dummy_pointer_event = pointer_event_factory_.Create(
web_pointer_event, Vector<WebPointerEvent>(), Vector<WebPointerEvent>(),
@@ -345,7 +345,7 @@ bool PointerEventManager::ShouldAdjustPointerEvent(
return RuntimeEnabledFeatures::UnifiedTouchAdjustmentEnabled() &&
pointer_event.pointer_type ==
WebPointerProperties::PointerType::kTouch &&
- pointer_event.GetType() == WebInputEvent::kPointerDown &&
+ pointer_event.GetType() == WebInputEvent::Type::kPointerDown &&
pointer_event_factory_.IsPrimary(pointer_event);
}
@@ -418,7 +418,7 @@ PointerEventManager::ComputePointerEventTarget(
// that will be capturing this event. |m_pointerCaptureTarget| may not
// have this target yet since the processing of that will be done right
// before firing the event.
- if (web_pointer_event.GetType() == WebInputEvent::kPointerDown ||
+ if (web_pointer_event.GetType() == WebInputEvent::Type::kPointerDown ||
!pending_pointer_capture_target_.Contains(pointer_id)) {
HitTestRequest::HitTestRequestType hit_type =
HitTestRequest::kTouchEvent | HitTestRequest::kReadOnly |
@@ -572,6 +572,17 @@ WebInputEventResult PointerEventManager::HandlePointerEvent(
PointerEvent* pointer_event =
pointer_event_factory_.Create(event, coalesced_events, predicted_events,
frame_->GetDocument()->domWindow());
+
+ // Sometimes the Browser process tags events with kRelativeMotionEvent.
+ // For e.g. during pointer lock, it recenters cursor by warping so that
+ // cursor does not hit the screen boundary.
+ // Those fake events should not be forwarded to the DOM.
+ // The conditional return here is deliberately placed after the Create()
+ // call above because of some side-effects of Create() is still needed
+ // (in particular SetLastPosition(), see crbug.com/1066544)
+ if (event.GetModifiers() & WebInputEvent::Modifiers::kRelativeMotionEvent)
+ return WebInputEventResult::kHandledSuppressed;
+
DispatchPointerEvent(target, pointer_event);
return WebInputEventResult::kHandledSystem;
}
@@ -613,7 +624,7 @@ WebInputEventResult PointerEventManager::HandlePointerEvent(
WebPointerEvent pointer_cancel_event;
pointer_cancel_event.pointer_type = event.pointer_type;
pointer_cancel_event.SetTimeStamp(event.TimeStamp());
- pointer_cancel_event.SetType(WebInputEvent::kPointerCancel);
+ pointer_cancel_event.SetType(WebInputEvent::Type::kPointerCancel);
touch_event_manager_->HandleTouchPoint(
pointer_cancel_event, coalesced_events, pointer_event_target);
@@ -628,7 +639,7 @@ WebInputEventResult PointerEventManager::HandlePointerEvent(
// For the rare case of multi-finger scenarios spanning documents, it
// seems extremely unlikely to matter which document the gesture is
// associated with so just pick the pointer event that comes.
- if (event.GetType() == WebInputEvent::kPointerUp &&
+ if (event.GetType() == WebInputEvent::Type::kPointerUp &&
!non_hovering_pointers_canceled_ && pointer_event_target.target_frame) {
LocalFrame::NotifyUserActivation(pointer_event_target.target_frame);
}
@@ -653,11 +664,11 @@ WebInputEventResult PointerEventManager::CreateAndDispatchPointerEvent(
// TODO(crbug.com/665924): The following ifs skip the mouseover/leave cases,
// we should fixed them when further merge the code path.
if (mouse_event_name == event_type_names::kMousemove)
- event_type = WebInputEvent::kPointerMove;
+ event_type = WebInputEvent::Type::kPointerMove;
else if (mouse_event_name == event_type_names::kMousedown)
- event_type = WebInputEvent::kPointerDown;
+ event_type = WebInputEvent::Type::kPointerDown;
else if (mouse_event_name == event_type_names::kMouseup)
- event_type = WebInputEvent::kPointerUp;
+ event_type = WebInputEvent::Type::kPointerUp;
else
return WebInputEventResult::kNotHandled;
@@ -721,9 +732,9 @@ WebInputEventResult PointerEventManager::SendMousePointerEvent(
const Vector<WebMouseEvent>& coalesced_events,
const Vector<WebMouseEvent>& predicted_events,
bool skip_click_dispatch) {
- DCHECK(event_type == WebInputEvent::kPointerDown ||
- event_type == WebInputEvent::kPointerMove ||
- event_type == WebInputEvent::kPointerUp);
+ DCHECK(event_type == WebInputEvent::Type::kPointerDown ||
+ event_type == WebInputEvent::Type::kPointerMove ||
+ event_type == WebInputEvent::Type::kPointerUp);
const WebPointerEvent web_pointer_event(event_type, mouse_event);
Vector<WebPointerEvent> pointer_coalesced_events;
@@ -748,10 +759,10 @@ WebInputEventResult PointerEventManager::SendMousePointerEvent(
WebInputEvent::Modifiers::kRelativeMotionEvent);
// Fake events should only be move events.
- DCHECK(!fake_event || event_type == WebInputEvent::kPointerMove);
+ DCHECK(!fake_event || event_type == WebInputEvent::Type::kPointerMove);
// This is for when the mouse is released outside of the page.
- if (!fake_event && event_type == WebInputEvent::kPointerMove &&
+ if (!fake_event && event_type == WebInputEvent::Type::kPointerMove &&
!pointer_event->buttons()) {
ReleasePointerCapture(pointer_event->pointerId());
// Send got/lostpointercapture rightaway if necessary.
@@ -773,8 +784,8 @@ WebInputEventResult PointerEventManager::SendMousePointerEvent(
Element* effective_target = GetEffectiveTargetForPointerEvent(
pointer_event_target, pointer_event->pointerId());
- if ((event_type == WebInputEvent::kPointerDown ||
- event_type == WebInputEvent::kPointerUp) &&
+ if ((event_type == WebInputEvent::Type::kPointerDown ||
+ event_type == WebInputEvent::Type::kPointerUp) &&
pointer_event->type() == event_type_names::kPointermove &&
RuntimeEnabledFeatures::PointerRawUpdateEnabled() &&
frame_->GetEventHandlerRegistry().HasEventHandlers(
@@ -800,7 +811,8 @@ WebInputEventResult PointerEventManager::SendMousePointerEvent(
if (pointer_event->isPrimary() &&
(!prevent_mouse_event_for_pointer_type_[ToPointerTypeIndex(
mouse_event.pointer_type)] ||
- (!skip_click_dispatch && event_type == WebInputEvent::kPointerUp))) {
+ (!skip_click_dispatch &&
+ event_type == WebInputEvent::Type::kPointerUp))) {
Element* mouse_target = effective_target;
// Event path could be null if the pointer event is not dispatched.
if (!event_handling_util::IsInDocument(mouse_target) &&
@@ -823,7 +835,7 @@ WebInputEventResult PointerEventManager::SendMousePointerEvent(
mouse_event, canvas_region_id, &last_mouse_position, nullptr));
}
if (!skip_click_dispatch && mouse_target &&
- event_type == WebInputEvent::kPointerUp) {
+ event_type == WebInputEvent::Type::kPointerUp) {
mouse_event_manager_->DispatchMouseClickIfNeeded(
mouse_target, mouse_event, canvas_region_id,
pointer_event->pointerId(), pointer_event->pointerType());
@@ -866,7 +878,7 @@ WebInputEventResult PointerEventManager::SendMousePointerEvent(
}
}
- if (mouse_event.GetType() == WebInputEvent::kMouseLeave &&
+ if (mouse_event.GetType() == WebInputEvent::Type::kMouseLeave &&
mouse_event.pointer_type == WebPointerProperties::PointerType::kPen) {
pointer_event_factory_.Remove(pointer_event->pointerId());
}
diff --git a/chromium/third_party/blink/renderer/core/input/pointer_event_manager_test.cc b/chromium/third_party/blink/renderer/core/input/pointer_event_manager_test.cc
index cd7acb67c50..208c7f985c9 100644
--- a/chromium/third_party/blink/renderer/core/input/pointer_event_manager_test.cc
+++ b/chromium/third_party/blink/renderer/core/input/pointer_event_manager_test.cc
@@ -124,8 +124,8 @@ TEST_F(PointerEventManagerTest, HasPointerCapture) {
ExceptionState exception(nullptr, ExceptionState::kExecutionContext, "", "");
- GetEventHandler().HandleMousePressEvent(
- CreateTestMouseEvent(WebInputEvent::kMouseDown, gfx::PointF(100, 100)));
+ GetEventHandler().HandleMousePressEvent(CreateTestMouseEvent(
+ WebInputEvent::Type::kMouseDown, gfx::PointF(100, 100)));
ASSERT_FALSE(
GetDocument().body()->hasPointerCapture(PointerEventFactory::kMouseId));
@@ -136,7 +136,8 @@ TEST_F(PointerEventManagerTest, HasPointerCapture) {
GetDocument().body()->hasPointerCapture(PointerEventFactory::kMouseId));
GetEventHandler().HandleMouseMoveEvent(
- CreateTestMouseEvent(WebInputEvent::kMouseMove, gfx::PointF(200, 200)),
+ CreateTestMouseEvent(WebInputEvent::Type::kMouseMove,
+ gfx::PointF(200, 200)),
Vector<WebMouseEvent>(), Vector<WebMouseEvent>());
ASSERT_TRUE(
@@ -161,40 +162,45 @@ TEST_F(PointerEventManagerTest, PointerCancelsOfAllTypes) {
callback);
WebView().MainFrameWidget()->HandleInputEvent(WebCoalescedInputEvent(
- CreateTestPointerEvent(WebInputEvent::kPointerDown,
- WebPointerProperties::PointerType::kTouch),
- {}, {}));
+ CreateTestPointerEvent(WebInputEvent::Type::kPointerDown,
+ WebPointerProperties::PointerType::kTouch)
+ .Clone(),
+ {}, {}, ui::LatencyInfo()));
WebView().MainFrameWidget()->HandleInputEvent(WebCoalescedInputEvent(
- CreateTestPointerEvent(WebInputEvent::kPointerDown,
- WebPointerProperties::PointerType::kPen),
- {}, {}));
+ CreateTestPointerEvent(WebInputEvent::Type::kPointerDown,
+ WebPointerProperties::PointerType::kPen)
+ .Clone(),
+ {}, {}, ui::LatencyInfo()));
- GetEventHandler().HandleMousePressEvent(
- CreateTestMouseEvent(WebInputEvent::kMouseDown, gfx::PointF(100, 100)));
+ GetEventHandler().HandleMousePressEvent(CreateTestMouseEvent(
+ WebInputEvent::Type::kMouseDown, gfx::PointF(100, 100)));
ASSERT_EQ(callback->mouseEventCount(), 0);
ASSERT_EQ(callback->touchEventCount(), 0);
ASSERT_EQ(callback->penEventCount(), 0);
WebView().MainFrameWidget()->HandleInputEvent(WebCoalescedInputEvent(
- CreateTestPointerEvent(WebInputEvent::kPointerCausedUaAction,
- WebPointerProperties::PointerType::kPen),
- {}, {}));
+ CreateTestPointerEvent(WebInputEvent::Type::kPointerCausedUaAction,
+ WebPointerProperties::PointerType::kPen)
+ .Clone(),
+ {}, {}, ui::LatencyInfo()));
ASSERT_EQ(callback->mouseEventCount(), 0);
ASSERT_EQ(callback->touchEventCount(), 1);
ASSERT_EQ(callback->penEventCount(), 1);
WebView().MainFrameWidget()->HandleInputEvent(WebCoalescedInputEvent(
- CreateTestPointerEvent(WebInputEvent::kPointerCausedUaAction,
- WebPointerProperties::PointerType::kTouch),
- {}, {}));
+ CreateTestPointerEvent(WebInputEvent::Type::kPointerCausedUaAction,
+ WebPointerProperties::PointerType::kTouch)
+ .Clone(),
+ {}, {}, ui::LatencyInfo()));
ASSERT_EQ(callback->mouseEventCount(), 0);
ASSERT_EQ(callback->touchEventCount(), 1);
ASSERT_EQ(callback->penEventCount(), 1);
GetEventHandler().HandleMouseMoveEvent(
- CreateTestMouseEvent(WebInputEvent::kMouseMove, gfx::PointF(200, 200)),
+ CreateTestMouseEvent(WebInputEvent::Type::kMouseMove,
+ gfx::PointF(200, 200)),
Vector<WebMouseEvent>(), Vector<WebMouseEvent>());
ASSERT_EQ(callback->mouseEventCount(), 1);
@@ -216,11 +222,12 @@ TEST_F(PointerEventManagerTest, PointerEventCoordinates) {
callback);
WebView().MainFrameWidget()->HandleInputEvent(WebCoalescedInputEvent(
- CreateTestPointerEvent(WebInputEvent::kPointerDown,
+ CreateTestPointerEvent(WebInputEvent::Type::kPointerDown,
WebPointerProperties::PointerType::kTouch,
gfx::PointF(150, 200), gfx::PointF(100, 50), 10,
- 10, 16, 24),
- {}, {}));
+ 10, 16, 24)
+ .Clone(),
+ {}, {}, ui::LatencyInfo()));
ASSERT_EQ(callback->last_client_x_, 75);
ASSERT_EQ(callback->last_client_y_, 100);
@@ -251,11 +258,12 @@ TEST_F(PointerEventManagerTest, PointerEventMovements) {
ScopedConsolidatedMovementXYForTest scoped_feature(true);
WebView().MainFrameWidget()->HandleInputEvent(WebCoalescedInputEvent(
- CreateTestPointerEvent(WebInputEvent::kPointerMove,
+ CreateTestPointerEvent(WebInputEvent::Type::kPointerMove,
WebPointerProperties::PointerType::kMouse,
gfx::PointF(150, 210), gfx::PointF(100, 50), 10,
- 10),
- {}, {}));
+ 10)
+ .Clone(),
+ {}, {}, ui::LatencyInfo()));
// The first pointermove event has movement_x/y 0.
ASSERT_EQ(callback->last_screen_x_, 100);
ASSERT_EQ(callback->last_screen_y_, 50);
@@ -263,11 +271,12 @@ TEST_F(PointerEventManagerTest, PointerEventMovements) {
ASSERT_EQ(callback->last_movement_y_, 0);
WebView().MainFrameWidget()->HandleInputEvent(WebCoalescedInputEvent(
- CreateTestPointerEvent(WebInputEvent::kPointerMove,
+ CreateTestPointerEvent(WebInputEvent::Type::kPointerMove,
WebPointerProperties::PointerType::kMouse,
gfx::PointF(150, 200), gfx::PointF(132, 29), 10,
- 10),
- {}, {}));
+ 10)
+ .Clone(),
+ {}, {}, ui::LatencyInfo()));
// pointermove event movement = event.screenX/Y - last_event.screenX/Y.
ASSERT_EQ(callback->last_screen_x_, 132);
ASSERT_EQ(callback->last_screen_y_, 29);
@@ -275,11 +284,12 @@ TEST_F(PointerEventManagerTest, PointerEventMovements) {
ASSERT_EQ(callback->last_movement_y_, -21);
WebView().MainFrameWidget()->HandleInputEvent(WebCoalescedInputEvent(
- CreateTestPointerEvent(WebInputEvent::kPointerMove,
+ CreateTestPointerEvent(WebInputEvent::Type::kPointerMove,
WebPointerProperties::PointerType::kMouse,
gfx::PointF(150, 210), gfx::PointF(113.8, 32.7),
- 10, 10),
- {}, {}));
+ 10, 10)
+ .Clone(),
+ {}, {}, ui::LatencyInfo()));
// fractional screen coordinates result in fractional movement.
ASSERT_FLOAT_EQ(callback->last_screen_x_, 113.8);
ASSERT_FLOAT_EQ(callback->last_screen_y_, 32.7);
@@ -293,11 +303,12 @@ TEST_F(PointerEventManagerTest, PointerEventMovements) {
ScopedConsolidatedMovementXYForTest scoped_feature(false);
WebView().MainFrameWidget()->HandleInputEvent(WebCoalescedInputEvent(
- CreateTestPointerEvent(WebInputEvent::kPointerMove,
+ CreateTestPointerEvent(WebInputEvent::Type::kPointerMove,
WebPointerProperties::PointerType::kMouse,
gfx::PointF(150, 210), gfx::PointF(100, 16.25),
- 1024, -8765),
- {}, {}));
+ 1024, -8765)
+ .Clone(),
+ {}, {}, ui::LatencyInfo()));
ASSERT_EQ(callback->last_screen_x_, 100);
ASSERT_EQ(callback->last_screen_y_, 16.25);
ASSERT_EQ(callback->last_movement_x_, 1024);
@@ -322,28 +333,29 @@ TEST_F(PointerEventManagerTest, PointerEventSmallFractionMovements) {
ScopedConsolidatedMovementXYForTest scoped_feature(true);
WebPointerEvent pointer_event = CreateTestPointerEvent(
- WebInputEvent::kPointerMove, WebPointerProperties::PointerType::kMouse,
- gfx::PointF(150, 210), gfx::PointF(113.8, 32.7), 0, 0);
+ WebInputEvent::Type::kPointerMove,
+ WebPointerProperties::PointerType::kMouse, gfx::PointF(150, 210),
+ gfx::PointF(113.8, 32.7), 0, 0);
WebView().MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(pointer_event));
+ WebCoalescedInputEvent(pointer_event, ui::LatencyInfo()));
ASSERT_FLOAT_EQ(callback->last_movement_x_, 0);
ASSERT_FLOAT_EQ(callback->last_movement_y_, 0);
pointer_event.SetPositionInScreen(113.4, 32.9);
WebView().MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(pointer_event));
+ WebCoalescedInputEvent(pointer_event, ui::LatencyInfo()));
ASSERT_FLOAT_EQ(callback->last_movement_x_, 0);
ASSERT_FLOAT_EQ(callback->last_movement_y_, 0);
pointer_event.SetPositionInScreen(113.0, 33.1);
WebView().MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(pointer_event));
+ WebCoalescedInputEvent(pointer_event, ui::LatencyInfo()));
ASSERT_FLOAT_EQ(callback->last_movement_x_, 0);
ASSERT_FLOAT_EQ(callback->last_movement_y_, 1);
pointer_event.SetPositionInScreen(112.6, 33.3);
WebView().MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(pointer_event));
+ WebCoalescedInputEvent(pointer_event, ui::LatencyInfo()));
ASSERT_FLOAT_EQ(callback->last_movement_x_, -1);
ASSERT_FLOAT_EQ(callback->last_movement_y_, 0);
}
@@ -366,11 +378,12 @@ TEST_F(PointerEventManagerTest, PointerRawUpdateMovements) {
ScopedConsolidatedMovementXYForTest scoped_feature(true);
WebView().MainFrameWidget()->HandleInputEvent(WebCoalescedInputEvent(
- CreateTestPointerEvent(WebInputEvent::kPointerRawUpdate,
+ CreateTestPointerEvent(WebInputEvent::Type::kPointerRawUpdate,
WebPointerProperties::PointerType::kMouse,
gfx::PointF(150, 210), gfx::PointF(100, 50), 10,
- 10),
- {}, {}));
+ 10)
+ .Clone(),
+ {}, {}, ui::LatencyInfo()));
// The first pointerrawupdate event has movement_x/y 0.
ASSERT_EQ(callback->last_screen_x_, 100);
ASSERT_EQ(callback->last_screen_y_, 50);
@@ -378,11 +391,12 @@ TEST_F(PointerEventManagerTest, PointerRawUpdateMovements) {
ASSERT_EQ(callback->last_movement_y_, 0);
WebView().MainFrameWidget()->HandleInputEvent(WebCoalescedInputEvent(
- CreateTestPointerEvent(WebInputEvent::kPointerRawUpdate,
+ CreateTestPointerEvent(WebInputEvent::Type::kPointerRawUpdate,
WebPointerProperties::PointerType::kMouse,
gfx::PointF(150, 200), gfx::PointF(132, 29), 10,
- 10),
- {}, {}));
+ 10)
+ .Clone(),
+ {}, {}, ui::LatencyInfo()));
// pointerrawupdate event movement = event.screenX/Y - last_event.screenX/Y.
ASSERT_EQ(callback->last_screen_x_, 132);
ASSERT_EQ(callback->last_screen_y_, 29);
@@ -390,11 +404,12 @@ TEST_F(PointerEventManagerTest, PointerRawUpdateMovements) {
ASSERT_EQ(callback->last_movement_y_, -21);
WebView().MainFrameWidget()->HandleInputEvent(WebCoalescedInputEvent(
- CreateTestPointerEvent(WebInputEvent::kPointerMove,
+ CreateTestPointerEvent(WebInputEvent::Type::kPointerMove,
WebPointerProperties::PointerType::kMouse,
gfx::PointF(150, 200), gfx::PointF(144, 30), 10,
- 10),
- {}, {}));
+ 10)
+ .Clone(),
+ {}, {}, ui::LatencyInfo()));
// First pointermove, have 0 movements.
ASSERT_EQ(callback->last_screen_x_, 144);
ASSERT_EQ(callback->last_screen_y_, 30);
@@ -402,11 +417,12 @@ TEST_F(PointerEventManagerTest, PointerRawUpdateMovements) {
ASSERT_EQ(callback->last_movement_y_, 0);
WebView().MainFrameWidget()->HandleInputEvent(WebCoalescedInputEvent(
- CreateTestPointerEvent(WebInputEvent::kPointerRawUpdate,
+ CreateTestPointerEvent(WebInputEvent::Type::kPointerRawUpdate,
WebPointerProperties::PointerType::kMouse,
gfx::PointF(150, 200), gfx::PointF(142, 32), 10,
- 10),
- {}, {}));
+ 10)
+ .Clone(),
+ {}, {}, ui::LatencyInfo()));
// pointerrawupdate event's movement is independent from pointermoves.
ASSERT_EQ(callback->last_screen_x_, 142);
ASSERT_EQ(callback->last_screen_y_, 32);
@@ -427,11 +443,12 @@ TEST_F(PointerEventManagerTest, PointerUnadjustedMovement) {
callback);
WebPointerEvent event = CreateTestPointerEvent(
- WebInputEvent::kPointerMove, WebPointerProperties::PointerType::kMouse,
- gfx::PointF(150, 210), gfx::PointF(100, 50), 120, -321);
+ WebInputEvent::Type::kPointerMove,
+ WebPointerProperties::PointerType::kMouse, gfx::PointF(150, 210),
+ gfx::PointF(100, 50), 120, -321);
event.is_raw_movement_event = true;
WebView().MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(event, {}, {}));
+ WebCoalescedInputEvent(event.Clone(), {}, {}, ui::LatencyInfo()));
// If is_raw_movement_event is true, PE use the raw movement value from
// movement_x/y.
diff --git a/chromium/third_party/blink/renderer/core/input/scroll_manager.cc b/chromium/third_party/blink/renderer/core/input/scroll_manager.cc
index a887b7dd737..a862630dd4a 100644
--- a/chromium/third_party/blink/renderer/core/input/scroll_manager.cc
+++ b/chromium/third_party/blink/renderer/core/input/scroll_manager.cc
@@ -42,11 +42,11 @@ namespace {
cc::SnapFlingController::GestureScrollType ToGestureScrollType(
WebInputEvent::Type web_event_type) {
switch (web_event_type) {
- case WebInputEvent::kGestureScrollBegin:
+ case WebInputEvent::Type::kGestureScrollBegin:
return cc::SnapFlingController::GestureScrollType::kBegin;
- case WebInputEvent::kGestureScrollUpdate:
+ case WebInputEvent::Type::kGestureScrollUpdate:
return cc::SnapFlingController::GestureScrollType::kUpdate;
- case WebInputEvent::kGestureScrollEnd:
+ case WebInputEvent::Type::kGestureScrollEnd:
return cc::SnapFlingController::GestureScrollType::kEnd;
default:
NOTREACHED();
@@ -228,6 +228,14 @@ bool ScrollManager::CanScroll(const ScrollState& scroll_state,
if (!scrollable_area->UserInputScrollable(kVerticalScrollbar))
delta_y = 0;
+ if (scroll_state.deltaGranularity() ==
+ static_cast<double>(ui::ScrollGranularity::kScrollByPercentage)) {
+ delta_x *= scrollable_area->ScrollStep(
+ ui::ScrollGranularity::kScrollByPercentage, kHorizontalScrollbar);
+ delta_y *= scrollable_area->ScrollStep(
+ ui::ScrollGranularity::kScrollByPercentage, kVerticalScrollbar);
+ }
+
ScrollOffset current_offset = scrollable_area->GetScrollOffset();
ScrollOffset target_offset = current_offset + ScrollOffset(delta_x, delta_y);
ScrollOffset clamped_offset =
@@ -473,6 +481,7 @@ WebInputEventResult ScrollManager::HandleGestureScrollBegin(
scroll_state_data->position_y = position.Y();
scroll_state_data->delta_x_hint = -gesture_event.DeltaXInRootFrame();
scroll_state_data->delta_y_hint = -gesture_event.DeltaYInRootFrame();
+ scroll_state_data->delta_granularity = gesture_event.DeltaUnits();
scroll_state_data->is_beginning = true;
scroll_state_data->from_user_input = true;
scroll_state_data->is_direct_manipulation =
@@ -527,7 +536,7 @@ WebInputEventResult ScrollManager::HandleGestureScrollBegin(
WebInputEventResult ScrollManager::HandleGestureScrollUpdate(
const WebGestureEvent& gesture_event) {
TRACE_EVENT0("input", "ScrollManager::handleGestureScrollUpdate");
- DCHECK_EQ(gesture_event.GetType(), WebInputEvent::kGestureScrollUpdate);
+ DCHECK_EQ(gesture_event.GetType(), WebInputEvent::Type::kGestureScrollUpdate);
Node* node = scroll_gesture_handling_node_.Get();
if (!node || !node->GetLayoutObject()) {
@@ -908,10 +917,11 @@ WebInputEventResult ScrollManager::HandleGestureScrollEvent(
Node* event_target = nullptr;
Scrollbar* scrollbar = nullptr;
- if (gesture_event.GetType() != WebInputEvent::kGestureScrollBegin) {
+ if (gesture_event.GetType() != WebInputEvent::Type::kGestureScrollBegin) {
scrollbar = scrollbar_handling_scroll_gesture_.Get();
event_target = scroll_gesture_handling_node_.Get();
- } else if (gesture_event.GetType() == WebInputEvent::kGestureScrollBegin &&
+ } else if (gesture_event.GetType() ==
+ WebInputEvent::Type::kGestureScrollBegin &&
gesture_event.data.scroll_begin.scrollable_area_element_id) {
CompositorElementId element_id = CompositorElementId(
gesture_event.data.scroll_begin.scrollable_area_element_id);
@@ -1008,14 +1018,14 @@ WebInputEventResult ScrollManager::HandleGestureScrollEvent(
}
}
switch (gesture_event.GetType()) {
- case WebInputEvent::kGestureScrollBegin:
+ case WebInputEvent::Type::kGestureScrollBegin:
return HandleGestureScrollBegin(gesture_event);
- case WebInputEvent::kGestureScrollUpdate:
+ case WebInputEvent::Type::kGestureScrollUpdate:
return HandleGestureScrollUpdate(gesture_event);
- case WebInputEvent::kGestureScrollEnd:
+ case WebInputEvent::Type::kGestureScrollEnd:
return HandleGestureScrollEnd(gesture_event);
- case WebInputEvent::kGestureFlingStart:
- case WebInputEvent::kGestureFlingCancel:
+ case WebInputEvent::Type::kGestureFlingStart:
+ case WebInputEvent::Type::kGestureFlingCancel:
return WebInputEventResult::kNotHandled;
default:
NOTREACHED();
@@ -1085,7 +1095,7 @@ bool ScrollManager::HandleScrollGestureOnResizer(
if (gesture_event.SourceDevice() != WebGestureDevice::kTouchscreen)
return false;
- if (gesture_event.GetType() == WebInputEvent::kGestureScrollBegin) {
+ if (gesture_event.GetType() == WebInputEvent::Type::kGestureScrollBegin) {
PaintLayer* layer = event_target->GetLayoutObject()
? event_target->GetLayoutObject()->EnclosingLayer()
: nullptr;
@@ -1100,7 +1110,8 @@ bool ScrollManager::HandleScrollGestureOnResizer(
LayoutSize(resize_scrollable_area_->OffsetFromResizeCorner(p));
return true;
}
- } else if (gesture_event.GetType() == WebInputEvent::kGestureScrollUpdate) {
+ } else if (gesture_event.GetType() ==
+ WebInputEvent::Type::kGestureScrollUpdate) {
if (resize_scrollable_area_ && resize_scrollable_area_->InResizeMode()) {
IntPoint pos =
RoundedIntPoint(FloatPoint(gesture_event.PositionInRootFrame()));
@@ -1109,7 +1120,8 @@ bool ScrollManager::HandleScrollGestureOnResizer(
resize_scrollable_area_->Resize(pos, offset_from_resize_corner_);
return true;
}
- } else if (gesture_event.GetType() == WebInputEvent::kGestureScrollEnd) {
+ } else if (gesture_event.GetType() ==
+ WebInputEvent::Type::kGestureScrollEnd) {
if (resize_scrollable_area_ && resize_scrollable_area_->InResizeMode()) {
resize_scrollable_area_->SetInResizeMode(false);
resize_scrollable_area_ = nullptr;
@@ -1125,7 +1137,7 @@ bool ScrollManager::InResizeMode() const {
}
void ScrollManager::Resize(const WebMouseEvent& evt) {
- if (evt.GetType() == WebInputEvent::kMouseMove) {
+ if (evt.GetType() == WebInputEvent::Type::kMouseMove) {
if (!frame_->GetEventHandler().MousePressed())
return;
resize_scrollable_area_->Resize(FlooredIntPoint(evt.PositionInRootFrame()),
@@ -1167,9 +1179,9 @@ bool ScrollManager::CanHandleGestureEvent(
WebGestureEvent ScrollManager::SynthesizeGestureScrollBegin(
const WebGestureEvent& update_event) {
- DCHECK_EQ(update_event.GetType(), WebInputEvent::kGestureScrollUpdate);
+ DCHECK_EQ(update_event.GetType(), WebInputEvent::Type::kGestureScrollUpdate);
WebGestureEvent scroll_begin(update_event);
- scroll_begin.SetType(WebInputEvent::kGestureScrollBegin);
+ scroll_begin.SetType(WebInputEvent::Type::kGestureScrollBegin);
scroll_begin.data.scroll_begin.delta_x_hint =
update_event.data.scroll_update.delta_x;
scroll_begin.data.scroll_begin.delta_y_hint =
diff --git a/chromium/third_party/blink/renderer/core/input/scroll_snap_test.cc b/chromium/third_party/blink/renderer/core/input/scroll_snap_test.cc
index fd8b8a5c7fa..2580a6dca1a 100644
--- a/chromium/third_party/blink/renderer/core/input/scroll_snap_test.cc
+++ b/chromium/third_party/blink/renderer/core/input/scroll_snap_test.cc
@@ -90,7 +90,7 @@ void ScrollSnapTest::ScrollBegin(double x,
double y,
double hint_x,
double hint_y) {
- WebGestureEvent event(WebInputEvent::kGestureScrollBegin,
+ WebGestureEvent event(WebInputEvent::Type::kGestureScrollBegin,
WebInputEvent::kNoModifiers, base::TimeTicks::Now(),
WebGestureDevice::kTouchscreen);
event.SetPositionInWidget(gfx::PointF(x, y));
@@ -107,7 +107,7 @@ void ScrollSnapTest::ScrollUpdate(double x,
double delta_x,
double delta_y,
bool is_in_inertial_phase) {
- WebGestureEvent event(WebInputEvent::kGestureScrollUpdate,
+ WebGestureEvent event(WebInputEvent::Type::kGestureScrollUpdate,
WebInputEvent::kNoModifiers, base::TimeTicks::Now(),
WebGestureDevice::kTouchscreen);
event.SetPositionInWidget(gfx::PointF(x, y));
@@ -124,7 +124,7 @@ void ScrollSnapTest::ScrollUpdate(double x,
}
void ScrollSnapTest::ScrollEnd(double x, double y, bool is_in_inertial_phase) {
- WebGestureEvent event(WebInputEvent::kGestureScrollEnd,
+ WebGestureEvent event(WebInputEvent::Type::kGestureScrollEnd,
WebInputEvent::kNoModifiers, base::TimeTicks::Now(),
WebGestureDevice::kTouchscreen);
event.SetPositionInWidget(gfx::PointF(x, y));
diff --git a/chromium/third_party/blink/renderer/core/input/touch_action_test.cc b/chromium/third_party/blink/renderer/core/input/touch_action_test.cc
index 38be891a9e9..7a766694ae2 100644
--- a/chromium/third_party/blink/renderer/core/input/touch_action_test.cc
+++ b/chromium/third_party/blink/renderer/core/input/touch_action_test.cc
@@ -29,8 +29,8 @@
*/
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/input/web_coalesced_input_event.h"
#include "third_party/blink/public/common/input/web_touch_event.h"
-#include "third_party/blink/public/platform/web_coalesced_input_event.h"
#include "third_party/blink/public/platform/web_url_loader_mock_factory.h"
#include "third_party/blink/public/web/web_document.h"
#include "third_party/blink/public/web/web_frame.h"
@@ -270,6 +270,8 @@ void TouchActionTest::RunTestOnTree(
// debugging).
Persistent<DOMRectList> rects = element->getClientRects();
ASSERT_GE(rects->length(), 0u) << failure_context.ToString();
+ if (!rects->length())
+ continue;
Persistent<DOMRect> r = rects->item(0);
FloatRect client_float_rect =
FloatRect(r->left(), r->top(), r->width(), r->height());
@@ -335,7 +337,7 @@ void TouchActionTest::RunTestOnTree(
<< ExternalRepresentation(root->GetDocument().GetFrame()).Utf8();
// Now send the touch event and check any touch action result.
- SendTouchEvent(web_view, WebInputEvent::kPointerDown, window_point);
+ SendTouchEvent(web_view, WebInputEvent::Type::kPointerDown, window_point);
AtomicString expected_action = element->getAttribute("expected-action");
// Should have received exactly one touch action, even for auto.
@@ -367,7 +369,8 @@ void TouchActionTest::RunTestOnTree(
// Reset webview touch state.
client.Reset();
- SendTouchEvent(web_view, WebInputEvent::kPointerCancel, window_point);
+ SendTouchEvent(web_view, WebInputEvent::Type::kPointerCancel,
+ window_point);
EXPECT_EQ(0, client.TouchActionSetCount());
}
}
@@ -375,8 +378,8 @@ void TouchActionTest::RunTestOnTree(
void TouchActionTest::SendTouchEvent(WebView* web_view,
WebInputEvent::Type type,
IntPoint client_point) {
- ASSERT_TRUE(type == WebInputEvent::kPointerDown ||
- type == WebInputEvent::kPointerCancel);
+ ASSERT_TRUE(type == WebInputEvent::Type::kPointerDown ||
+ type == WebInputEvent::Type::kPointerCancel);
WebPointerEvent event(
type,
@@ -385,10 +388,11 @@ void TouchActionTest::SendTouchEvent(WebView* web_view,
gfx::PointF(client_point.X(), client_point.Y()),
gfx::PointF(client_point.X(), client_point.Y())),
10.0f, 10.0f);
- if (type == WebInputEvent::kPointerCancel)
- event.dispatch_type = WebInputEvent::kEventNonBlocking;
+ if (type == WebInputEvent::Type::kPointerCancel)
+ event.dispatch_type = WebInputEvent::DispatchType::kEventNonBlocking;
- web_view->MainFrameWidget()->HandleInputEvent(WebCoalescedInputEvent(event));
+ web_view->MainFrameWidget()->HandleInputEvent(
+ WebCoalescedInputEvent(event, ui::LatencyInfo()));
web_view->MainFrameWidget()->DispatchBufferedTouchEvents();
RunPendingTasks();
}
diff --git a/chromium/third_party/blink/renderer/core/input/touch_event_manager.cc b/chromium/third_party/blink/renderer/core/input/touch_event_manager.cc
index 917ba947697..8032b530bed 100644
--- a/chromium/third_party/blink/renderer/core/input/touch_event_manager.cc
+++ b/chromium/third_party/blink/renderer/core/input/touch_event_manager.cc
@@ -5,8 +5,8 @@
#include "third_party/blink/renderer/core/input/touch_event_manager.h"
#include <memory>
+#include "third_party/blink/public/common/input/web_coalesced_input_event.h"
#include "third_party/blink/public/common/input/web_touch_event.h"
-#include "third_party/blink/public/platform/web_coalesced_input_event.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/flat_tree_traversal.h"
#include "third_party/blink/renderer/core/events/touch_event.h"
@@ -64,13 +64,13 @@ bool HasTouchHandlers(const EventHandlerRegistry& registry) {
const AtomicString& TouchEventNameForPointerEventType(
WebInputEvent::Type type) {
switch (type) {
- case WebInputEvent::kPointerUp:
+ case WebInputEvent::Type::kPointerUp:
return event_type_names::kTouchend;
- case WebInputEvent::kPointerCancel:
+ case WebInputEvent::Type::kPointerCancel:
return event_type_names::kTouchcancel;
- case WebInputEvent::kPointerDown:
+ case WebInputEvent::Type::kPointerDown:
return event_type_names::kTouchstart;
- case WebInputEvent::kPointerMove:
+ case WebInputEvent::Type::kPointerMove:
return event_type_names::kTouchmove;
default:
NOTREACHED();
@@ -82,19 +82,19 @@ WebTouchPoint::State TouchPointStateFromPointerEventType(
WebInputEvent::Type type,
bool stale) {
if (stale)
- return WebTouchPoint::kStateStationary;
+ return WebTouchPoint::State::kStateStationary;
switch (type) {
case WebInputEvent::Type::kPointerUp:
- return WebTouchPoint::kStateReleased;
+ return WebTouchPoint::State::kStateReleased;
case WebInputEvent::Type::kPointerCancel:
- return WebTouchPoint::kStateCancelled;
+ return WebTouchPoint::State::kStateCancelled;
case WebInputEvent::Type::kPointerDown:
- return WebTouchPoint::kStatePressed;
+ return WebTouchPoint::State::kStatePressed;
case WebInputEvent::Type::kPointerMove:
- return WebTouchPoint::kStateMoved;
+ return WebTouchPoint::State::kStateMoved;
default:
NOTREACHED();
- return WebTouchPoint::kStateUndefined;
+ return WebTouchPoint::State::kStateUndefined;
}
}
@@ -233,7 +233,7 @@ WebCoalescedInputEvent TouchEventManager::GenerateWebCoalescedInputEvent() {
first_touch_pointer_event);
SetWebTouchEventAttributesFromWebPointerEvent(&last_coalesced_touch_event_,
first_touch_pointer_event);
- WebInputEvent::Type touch_event_type = WebInputEvent::kTouchMove;
+ WebInputEvent::Type touch_event_type = WebInputEvent::Type::kTouchMove;
Vector<WebPointerEvent> all_coalesced_events;
Vector<int> available_ids;
for (const auto& id : touch_attribute_map_.Keys())
@@ -256,13 +256,14 @@ WebCoalescedInputEvent TouchEventManager::GenerateWebCoalescedInputEvent() {
// TODO(crbug.com/732842): Note that event sender API allows sending any
// mix of input and as long as we don't crash or anything we should be good
// for now.
- if (touch_event_type == WebInputEvent::kTouchMove) {
- if (touch_pointer_event.GetType() == WebInputEvent::kPointerDown)
- touch_event_type = WebInputEvent::kTouchStart;
- else if (touch_pointer_event.GetType() == WebInputEvent::kPointerCancel)
- touch_event_type = WebInputEvent::kTouchCancel;
- else if (touch_pointer_event.GetType() == WebInputEvent::kPointerUp)
- touch_event_type = WebInputEvent::kTouchEnd;
+ if (touch_event_type == WebInputEvent::Type::kTouchMove) {
+ if (touch_pointer_event.GetType() == WebInputEvent::Type::kPointerDown)
+ touch_event_type = WebInputEvent::Type::kTouchStart;
+ else if (touch_pointer_event.GetType() ==
+ WebInputEvent::Type::kPointerCancel)
+ touch_event_type = WebInputEvent::Type::kTouchCancel;
+ else if (touch_pointer_event.GetType() == WebInputEvent::Type::kPointerUp)
+ touch_event_type = WebInputEvent::Type::kTouchEnd;
}
for (const WebPointerEvent& coalesced_event :
@@ -281,9 +282,9 @@ WebCoalescedInputEvent TouchEventManager::GenerateWebCoalescedInputEvent() {
} timestamp_based_event_comparison;
std::sort(all_coalesced_events.begin(), all_coalesced_events.end(),
timestamp_based_event_comparison);
- WebCoalescedInputEvent result(event, {}, {});
+ WebCoalescedInputEvent result(event.Clone(), {}, {}, ui::LatencyInfo());
for (const auto& web_pointer_event : all_coalesced_events) {
- if (web_pointer_event.GetType() == WebInputEvent::kPointerDown) {
+ if (web_pointer_event.GetType() == WebInputEvent::Type::kPointerDown) {
// TODO(crbug.com/732842): Technically we should never receive the
// pointerdown twice for the same touch point. But event sender API allows
// that. So we should handle it gracefully.
@@ -331,9 +332,9 @@ WebCoalescedInputEvent TouchEventManager::GenerateWebCoalescedInputEvent() {
for (unsigned j = 0; j < last_coalesced_touch_event_.touches_length;
j++) {
if (last_coalesced_touch_event_.touches[j].state !=
- WebTouchPoint::kStateCancelled &&
+ WebTouchPoint::State::kStateCancelled &&
last_coalesced_touch_event_.touches[j].state !=
- WebTouchPoint::kStateReleased) {
+ WebTouchPoint::State::kStateReleased) {
last_coalesced_touch_event_.touches[result_size++] =
last_coalesced_touch_event_.touches[j];
}
@@ -345,7 +346,7 @@ WebCoalescedInputEvent TouchEventManager::GenerateWebCoalescedInputEvent() {
}
for (unsigned i = 0; i < event.touches_length; ++i) {
- event.touches[i].state = blink::WebTouchPoint::kStateStationary;
+ event.touches[i].state = blink::WebTouchPoint::State::kStateStationary;
event.touches[i].movement_x = 0;
event.touches[i].movement_y = 0;
}
@@ -368,10 +369,10 @@ TouchEventManager::DispatchTouchEventFromAccumulatdTouchPoints() {
for (const auto& attr : touch_attribute_map_.Values()) {
if (!attr->stale_)
new_touch_point_since_last_dispatch = true;
- if (attr->event_.GetType() == WebInputEvent::kPointerUp ||
- attr->event_.GetType() == WebInputEvent::kPointerCancel)
+ if (attr->event_.GetType() == WebInputEvent::Type::kPointerUp ||
+ attr->event_.GetType() == WebInputEvent::Type::kPointerCancel)
any_touch_canceled_or_ended = true;
- if (attr->event_.GetType() != WebInputEvent::kPointerDown)
+ if (attr->event_.GetType() != WebInputEvent::Type::kPointerDown)
all_touch_points_pressed = false;
}
@@ -387,7 +388,7 @@ TouchEventManager::DispatchTouchEventFromAccumulatdTouchPoints() {
DCHECK_EQ(1U, touch_attribute_map_.size());
const auto& touch_point_attribute = touch_attribute_map_.begin()->value;
if (touch_point_attribute->event_.GetType() ==
- WebInputEvent::kPointerMove) {
+ WebInputEvent::Type::kPointerMove) {
if (!touch_point_attribute->event_.moved_beyond_slop_region)
return WebInputEventResult::kHandledSuppressed;
suppressing_touchmoves_within_slop_ = false;
@@ -403,8 +404,10 @@ TouchEventManager::DispatchTouchEventFromAccumulatdTouchPoints() {
TargetTouchesHeapMap touches_by_target;
// Array of touches per state, used to assemble the |changedTouches| list.
- ChangedTouches changed_touches[WebInputEvent::kPointerTypeLast -
- WebInputEvent::kPointerTypeFirst + 1];
+ ChangedTouches
+ changed_touches[static_cast<int>(WebInputEvent::Type::kPointerTypeLast) -
+ static_cast<int>(WebInputEvent::Type::kPointerTypeFirst) +
+ 1];
Vector<int> available_ids;
for (const auto& id : touch_attribute_map_.Keys())
@@ -430,8 +433,8 @@ TouchEventManager::DispatchTouchEventFromAccumulatdTouchPoints() {
// |touches| and |targetTouches| should only contain information about
// touches still on the screen, so if this point is released or
// cancelled it will only appear in the |changedTouches| list.
- if (event_type != WebInputEvent::kPointerUp &&
- event_type != WebInputEvent::kPointerCancel) {
+ if (event_type != WebInputEvent::Type::kPointerUp &&
+ event_type != WebInputEvent::Type::kPointerCancel) {
touches->Append(touch);
target_touches_iterator->value->Append(touch);
}
@@ -443,7 +446,9 @@ TouchEventManager::DispatchTouchEventFromAccumulatdTouchPoints() {
// explicitly here. See https://bugs.webkit.org/show_bug.cgi?id=37609
// for further discussion about the TouchStationary state.
if (!touch_point_attribute->stale_ && known_target) {
- size_t event_type_idx = event_type - WebInputEvent::kPointerTypeFirst;
+ size_t event_type_idx =
+ static_cast<int>(event_type) -
+ static_cast<int>(WebInputEvent::Type::kPointerTypeFirst);
if (!changed_touches[event_type_idx].touches_)
changed_touches[event_type_idx].touches_ = TouchList::Create();
changed_touches[event_type_idx].touches_->Append(touch);
@@ -459,9 +464,12 @@ TouchEventManager::DispatchTouchEventFromAccumulatdTouchPoints() {
// Now iterate through the |changedTouches| list and |m_targets| within it,
// sending TouchEvents to the targets as required.
- for (unsigned action = WebInputEvent::kPointerTypeFirst;
- action <= WebInputEvent::kPointerTypeLast; ++action) {
- size_t action_idx = action - WebInputEvent::kPointerTypeFirst;
+ for (unsigned action =
+ static_cast<int>(WebInputEvent::Type::kPointerTypeFirst);
+ action <= static_cast<int>(WebInputEvent::Type::kPointerTypeLast);
+ ++action) {
+ size_t action_idx =
+ action - static_cast<int>(WebInputEvent::Type::kPointerTypeFirst);
if (!changed_touches[action_idx].touches_)
continue;
@@ -505,7 +513,7 @@ void TouchEventManager::UpdateTouchAttributeMapsForPointerDown(
// active/hover states themselves (Gesture events do). So we only need
// to hit-test on touchstart and when the target could be different than
// the corresponding pointer event target.
- DCHECK(event.GetType() == WebInputEvent::kPointerDown);
+ DCHECK(event.GetType() == WebInputEvent::Type::kPointerDown);
// Ideally we'd DCHECK(!touch_attribute_map_.Contains(event.id))
// since we shouldn't get a touchstart for a touch that's already
// down. However EventSender allows this to be violated and there's
@@ -595,9 +603,9 @@ void TouchEventManager::HandleTouchPoint(
const WebPointerEvent& event,
const Vector<WebPointerEvent>& coalesced_events,
const event_handling_util::PointerEventTarget& pointer_event_target) {
- DCHECK_GE(event.GetType(), WebInputEvent::kPointerTypeFirst);
- DCHECK_LE(event.GetType(), WebInputEvent::kPointerTypeLast);
- DCHECK_NE(event.GetType(), WebInputEvent::kPointerCausedUaAction);
+ DCHECK_GE(event.GetType(), WebInputEvent::Type::kPointerTypeFirst);
+ DCHECK_LE(event.GetType(), WebInputEvent::Type::kPointerTypeLast);
+ DCHECK_NE(event.GetType(), WebInputEvent::Type::kPointerCausedUaAction);
if (touch_attribute_map_.IsEmpty()) {
// Ideally we'd DCHECK(!m_touchSequenceDocument) here since we should
@@ -624,7 +632,7 @@ void TouchEventManager::HandleTouchPoint(
// In touch event model only touch starts can set the target and after that
// the touch event always goes to that target.
- if (event.GetType() == WebInputEvent::kPointerDown) {
+ if (event.GetType() == WebInputEvent::Type::kPointerDown) {
UpdateTouchAttributeMapsForPointerDown(event, pointer_event_target);
}
@@ -660,8 +668,8 @@ WebInputEventResult TouchEventManager::FlushEvents() {
// touch points.
Vector<int> released_canceled_points;
for (auto& attributes : touch_attribute_map_.Values()) {
- if (attributes->event_.GetType() == WebInputEvent::kPointerUp ||
- attributes->event_.GetType() == WebInputEvent::kPointerCancel) {
+ if (attributes->event_.GetType() == WebInputEvent::Type::kPointerUp ||
+ attributes->event_.GetType() == WebInputEvent::Type::kPointerCancel) {
released_canceled_points.push_back(attributes->event_.id);
} else {
attributes->stale_ = true;
diff --git a/chromium/third_party/blink/renderer/core/input/touch_event_manager.h b/chromium/third_party/blink/renderer/core/input/touch_event_manager.h
index 693f2d93743..2d4a92c797e 100644
--- a/chromium/third_party/blink/renderer/core/input/touch_event_manager.h
+++ b/chromium/third_party/blink/renderer/core/input/touch_event_manager.h
@@ -6,9 +6,9 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_INPUT_TOUCH_EVENT_MANAGER_H_
#include "base/macros.h"
+#include "third_party/blink/public/common/input/web_coalesced_input_event.h"
#include "third_party/blink/public/common/input/web_pointer_event.h"
#include "third_party/blink/public/common/input/web_touch_event.h"
-#include "third_party/blink/public/platform/web_coalesced_input_event.h"
#include "third_party/blink/public/platform/web_input_event_result.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/events/pointer_event_factory.h"
diff --git a/chromium/third_party/blink/renderer/core/input/touch_event_manager_test.cc b/chromium/third_party/blink/renderer/core/input/touch_event_manager_test.cc
index 255b908701f..54a2b8cdf0d 100644
--- a/chromium/third_party/blink/renderer/core/input/touch_event_manager_test.cc
+++ b/chromium/third_party/blink/renderer/core/input/touch_event_manager_test.cc
@@ -61,19 +61,19 @@ TEST_F(TouchEventManagerTest, LostTouchDueToInnerIframeRemove) {
callback);
GetEventHandler().HandlePointerEvent(
- CreateTouchPointerEvent(WebInputEvent::kPointerDown),
+ CreateTouchPointerEvent(WebInputEvent::Type::kPointerDown),
Vector<WebPointerEvent>(), Vector<WebPointerEvent>());
GetEventHandler().DispatchBufferedTouchEvents();
GetDocument().getElementById("target")->remove();
GetEventHandler().HandlePointerEvent(
- CreateTouchPointerEvent(WebInputEvent::kPointerUp),
+ CreateTouchPointerEvent(WebInputEvent::Type::kPointerUp),
Vector<WebPointerEvent>(), Vector<WebPointerEvent>());
GetEventHandler().DispatchBufferedTouchEvents();
GetEventHandler().HandlePointerEvent(
- CreateTouchPointerEvent(WebInputEvent::kPointerDown),
+ CreateTouchPointerEvent(WebInputEvent::Type::kPointerDown),
Vector<WebPointerEvent>(), Vector<WebPointerEvent>());
GetEventHandler().DispatchBufferedTouchEvents();
@@ -94,7 +94,7 @@ TEST_F(TouchEventManagerTest, AbosolutePosWithScrollAndZoom) {
Window().scrollTo(100, 100);
GetEventHandler().HandlePointerEvent(
- CreateTouchPointerEvent(WebInputEvent::kPointerDown),
+ CreateTouchPointerEvent(WebInputEvent::Type::kPointerDown),
Vector<WebPointerEvent>(), Vector<WebPointerEvent>());
GetEventHandler().DispatchBufferedTouchEvents();
diff --git a/chromium/third_party/blink/renderer/core/input/touch_list.idl b/chromium/third_party/blink/renderer/core/input/touch_list.idl
index f8381a43cf5..083f6902498 100644
--- a/chromium/third_party/blink/renderer/core/input/touch_list.idl
+++ b/chromium/third_party/blink/renderer/core/input/touch_list.idl
@@ -25,7 +25,9 @@
// https://w3c.github.io/touch-events/#touchlist-interface
-interface TouchList {
+[
+ Exposed=Window
+] interface TouchList {
readonly attribute unsigned long length;
getter Touch? item(unsigned long index);
};
diff --git a/chromium/third_party/blink/renderer/core/inspector/BUILD.gn b/chromium/third_party/blink/renderer/core/inspector/BUILD.gn
index a61b241165b..e8a912f1766 100644
--- a/chromium/third_party/blink/renderer/core/inspector/BUILD.gn
+++ b/chromium/third_party/blink/renderer/core/inspector/BUILD.gn
@@ -28,6 +28,8 @@ blink_core_sources("inspector") {
"dom_editor.h",
"dom_patch_support.cc",
"dom_patch_support.h",
+ "dom_traversal_utils.cc",
+ "dom_traversal_utils.h",
"identifiers_factory.cc",
"identifiers_factory.h",
"inspect_tools.cc",
diff --git a/chromium/third_party/blink/renderer/core/inspector/dom_traversal_utils.cc b/chromium/third_party/blink/renderer/core/inspector/dom_traversal_utils.cc
new file mode 100644
index 00000000000..71a752e0ed9
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/inspector/dom_traversal_utils.cc
@@ -0,0 +1,46 @@
+#include "third_party/blink/renderer/core/inspector/dom_traversal_utils.h"
+
+#include "third_party/blink/renderer/core/dom/flat_tree_traversal.h"
+#include "third_party/blink/renderer/core/dom/node.h"
+#include "third_party/blink/renderer/core/dom/shadow_root.h"
+
+namespace blink {
+namespace dom_traversal_utils {
+
+Node* FirstChild(const Node& node, bool include_user_agent_shadow_tree) {
+ DCHECK(include_user_agent_shadow_tree || !node.IsInUserAgentShadowRoot());
+ if (!include_user_agent_shadow_tree) {
+ ShadowRoot* shadow_root = node.GetShadowRoot();
+ if (shadow_root && shadow_root->GetType() == ShadowRootType::kUserAgent) {
+ Node* child = node.firstChild();
+ while (child && !child->CanParticipateInFlatTree())
+ child = child->nextSibling();
+ return child;
+ }
+ }
+ return FlatTreeTraversal::FirstChild(node);
+}
+
+// static
+bool HasChildren(const Node& node, bool include_user_agent_shadow_tree) {
+ return FirstChild(node, include_user_agent_shadow_tree);
+}
+
+// static
+Node* NextSibling(const Node& node, bool include_user_agent_shadow_tree) {
+ DCHECK(include_user_agent_shadow_tree || !node.IsInUserAgentShadowRoot());
+ if (!include_user_agent_shadow_tree) {
+ if (node.ParentElementShadowRoot() &&
+ node.ParentElementShadowRoot()->GetType() ==
+ ShadowRootType::kUserAgent) {
+ Node* sibling = node.nextSibling();
+ while (sibling && !sibling->CanParticipateInFlatTree())
+ sibling = sibling->nextSibling();
+ return sibling;
+ }
+ }
+ return FlatTreeTraversal::NextSibling(node);
+}
+
+} // namespace dom_traversal_utils
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/inspector/dom_traversal_utils.h b/chromium/third_party/blink/renderer/core/inspector/dom_traversal_utils.h
new file mode 100644
index 00000000000..d4a52a40844
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/inspector/dom_traversal_utils.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_CORE_INSPECTOR_DOM_TRAVERSAL_UTILS_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_INSPECTOR_DOM_TRAVERSAL_UTILS_H_
+
+namespace blink {
+
+class Node;
+
+namespace dom_traversal_utils {
+
+// These are deprecated, do not use in new code. Use FlatTreeTraversal directly.
+Node* FirstChild(const Node& node, bool include_user_agent_shadow_tree);
+bool HasChildren(const Node& node, bool include_user_agent_shadow_tree);
+Node* NextSibling(const Node& node, bool include_user_agent_shadow_tree);
+
+} // namespace dom_traversal_utils
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_INSPECTOR_DOM_TRAVERSAL_UTILS_H_
diff --git a/chromium/third_party/blink/renderer/core/inspector/inspect_tool_highlight.html b/chromium/third_party/blink/renderer/core/inspector/inspect_tool_highlight.html
index 2f9157c4a22..b5c7dbdb50f 100644
--- a/chromium/third_party/blink/renderer/core/inspector/inspect_tool_highlight.html
+++ b/chromium/third_party/blink/renderer/core/inspector/inspect_tool_highlight.html
@@ -66,7 +66,7 @@ body {
border-radius: 3px;
box-sizing: border-box;
min-width: 100px;
- max-width: 300px;
+ max-width: min(300px, 100% - 4px);
z-index: 1;
background-clip: padding-box;
will-change: transform;
@@ -87,6 +87,20 @@ body {
visibility: var(--arrow-visibility);
}
+.element-info-section {
+ margin-top: 12px;
+ margin-bottom: 6px;
+}
+
+.section-name {
+ color: #333;
+ font-weight: 500;
+ font-size: 10px;
+ text-transform: uppercase;
+ letter-spacing: .05em;
+ line-height: 12px;
+}
+
.element-info {
display: flex;
flex-direction: column;
@@ -109,13 +123,20 @@ body {
line-height: 19px;
}
-.element-info-contrast-row {
+.separator-container {
+ display: flex;
+ align-items: center;
+ flex: auto;
+ margin-left: 7px;
+}
+
+.separator {
border-top: 1px solid #ddd;
- padding-top: 5px;
- margin-top: 5px;
+ width: 100%;
}
.element-info-name {
+ flex-shrink: 0;
color: #666;
}
@@ -132,11 +153,21 @@ body {
.element-info-value-contrast {
display: flex;
+ align-items: center;
text-align: right;
color: rgb(48, 57, 66);
margin-left: 10px;
}
+.element-info-value-contrast .a11y-icon {
+ margin-left: 8px;
+}
+
+.element-info-value-icon {
+ display: flex;
+ align-items: center;
+}
+
.element-info-value-text {
text-align: right;
color: rgb(48, 57, 66);
@@ -205,16 +236,20 @@ body {
.a11y-icon {
width: 16px;
height: 16px;
- margin-left: 2px;
background-repeat: no-repeat;
+ display: inline-block;
+}
+
+.a11y-icon-not-ok {
+ background-image: url('data:image/svg+xml,<svg fill="none" viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg"><path d="m9 1.5c-4.14 0-7.5 3.36-7.5 7.5s3.36 7.5 7.5 7.5 7.5-3.36 7.5-7.5-3.36-7.5-7.5-7.5zm0 13.5c-3.315 0-6-2.685-6-6 0-1.3875.4725-2.6625 1.2675-3.675l8.4075 8.4075c-1.0125.795-2.2875 1.2675-3.675 1.2675zm4.7325-2.325-8.4075-8.4075c1.0125-.795 2.2875-1.2675 3.675-1.2675 3.315 0 6 2.685 6 6 0 1.3875-.4725 2.6625-1.2675 3.675z" fill="%239e9e9e"/></svg>');
}
.a11y-icon-warning {
- background-image: url("data:image/svg+xml;charset=UTF-8, %3csvg xmlns='http://www.w3.org/2000/svg' width='16px' height='16px' viewBox='0 0 18 18' fill='%23ffc107'%3e%3cpath d='M0 0h18v18H0z' fill='none'/%3e%3cpath d='M.5 16h17L9 1 .5 16zm9.5-2H8v-2h2v2zm0-3H8V7h2v4z'/%3e%3c/svg%3e ");
+ background-image: url('data:image/svg+xml,<svg fill="none" viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg"><path d="m8.25 11.25h1.5v1.5h-1.5zm0-6h1.5v4.5h-1.5zm.7425-3.75c-4.14 0-7.4925 3.36-7.4925 7.5s3.3525 7.5 7.4925 7.5c4.1475 0 7.5075-3.36 7.5075-7.5s-3.36-7.5-7.5075-7.5zm.0075 13.5c-3.315 0-6-2.685-6-6s2.685-6 6-6 6 2.685 6 6-2.685 6-6 6z" fill="%23e37400"/></svg>');
}
.a11y-icon-ok {
- background-image: url("data:image/svg+xml;charset=UTF-8, %3csvg xmlns='http://www.w3.org/2000/svg' width='16px' height='16px' viewBox='0 0 48 48' fill='%2300a000'%3e%3cpath d='M0 0h48v48H0z' fill='none'/%3e%3cpath d='M18 32.34L9.66 24l-2.83 2.83L18 38l24-24-2.83-2.83z'/%3e%3c/svg%3e");
+ background-image: url('data:image/svg+xml,<svg fill="none" viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg"><path d="m9 1.5c-4.14 0-7.5 3.36-7.5 7.5s3.36 7.5 7.5 7.5 7.5-3.36 7.5-7.5-3.36-7.5-7.5-7.5zm0 13.5c-3.3075 0-6-2.6925-6-6s2.6925-6 6-6 6 2.6925 6 6-2.6925 6-6 6zm-1.5-4.35-1.95-1.95-1.05 1.05 3 3 6-6-1.05-1.05z" fill="%230ca40c"/></svg>');
}
@media (forced-colors: active) {
@@ -233,13 +268,14 @@ body {
}
.color-swatch-inner,
.contrast-text,
- .element-info-contrast-row {
+ .separator {
border-color: Highlight;
}
.dimensions,
.element-info-name,
.element-info-value-color,
.element-info-value-contrast,
+ .element-info-value-icon,
.element-info-value-text,
.material-tag-name,
.material-class-name,
@@ -407,14 +443,68 @@ function parseHexa(hexa) {
}
/**
- * @param {!String} hexa
+ * TODO(alexrudenko): import this and other color helpers from DevTools
+ * @param {!Array<number>} rgba
* @return {!Array<number>}
*/
-function normalizeColorString(hexa) {
- if (hexa.endsWith("FF"))
+function rgbaToHsla(rgba) {
+ const [r, g, b] = rgba;
+ const max = Math.max(r, g, b);
+ const min = Math.min(r, g, b);
+ const diff = max - min;
+ const sum = max + min;
+
+ let h;
+ if (min === max) {
+ h = 0;
+ } else if (r === max) {
+ h = ((1 / 6 * (g - b) / diff) + 1) % 1;
+ } else if (g === max) {
+ h = (1 / 6 * (b - r) / diff) + 1 / 3;
+ } else {
+ h = (1 / 6 * (r - g) / diff) + 2 / 3;
+ }
+
+ const l = 0.5 * sum;
+
+ let s;
+ if (l === 0) {
+ s = 0;
+ } else if (l === 1) {
+ s = 0;
+ } else if (l <= 0.5) {
+ s = diff / sum;
+ } else {
+ s = diff / (2 - sum);
+ }
+
+ return [h, s, l, rgba[3]];
+}
+
+/**
+ * @param {!String} hexa
+ * @param {!String} colorFormat
+ * @return {!String}
+ */
+function formatColor(hexa, colorFormat) {
+ if (colorFormat === 'rgb') {
+ const [r, g, b, a] = parseHexa(hexa);
+ // rgb(r g b [ / a])
+ return `rgb(${(r * 255).toFixed()} ${(g * 255).toFixed()} ${(b * 255).toFixed()}${a === 1 ? '' : ' / ' + Math.round(a * 100) / 100})`;
+ }
+
+ if (colorFormat === 'hsl') {
+ const [h, s, l, a] = rgbaToHsla(parseHexa(hexa));
+ // hsl(hdeg s l [ / a])
+ return `hsl(${Math.round(h * 360)}deg ${Math.round(s * 100)} ${Math.round(l * 100)}${a === 1 ? '' : ' / ' + Math.round(a * 100) / 100})`;
+ }
+
+ if (hexa.endsWith("FF")) {
+ // short hex if no alpha
return hexa.substr(0, 7);
- const [r, g, b, a] = parseHexa(hexa);
- return `rgba(${(r * 255).toFixed()}, ${(g * 255).toFixed()}, ${(b * 255).toFixed()}, ${Math.round(a * 100) / 100})`;
+ }
+
+ return hexa;
}
/**
@@ -484,7 +574,7 @@ function computeIsLargeFont(contrast) {
return fontSizePt >= 18;
}
-function _createElementDescription(elementInfo)
+function _createElementDescription(elementInfo, colorFormat)
{
const elementInfoElement = createElement("div", "element-info");
const elementInfoHeaderElement = elementInfoElement.createChild("div", "element-info-header");
@@ -513,7 +603,7 @@ function _createElementDescription(elementInfo)
const color = style["color"];
if (color && color !== "#00000000")
- addColorRow("Color", color);
+ addColorRow("Color", color, colorFormat);
const fontFamily = style["font-family"];
const fontSize = style["font-size"];
@@ -522,7 +612,7 @@ function _createElementDescription(elementInfo)
const bgcolor = style["background-color"];
if (bgcolor && bgcolor !== "#00000000")
- addColorRow("Background", bgcolor);
+ addColorRow("Background", bgcolor, colorFormat);
const margin = style["margin"];
if (margin && margin !== "0px")
@@ -533,12 +623,36 @@ function _createElementDescription(elementInfo)
addTextRow("Padding", padding);
const cbgColor = elementInfo.contrast ? elementInfo.contrast.backgroundColor : null;
- if (color && color !== "#00000000" && cbgColor && cbgColor !== "#00000000")
- addContrastRow(style["color"], elementInfo.contrast);
+ const hasContrastInfo = color && color !== "#00000000" && cbgColor && cbgColor !== "#00000000";
- function addRow(name, rowClassName, valueClassName) {
+ if (elementInfo.showAccessibilityInfo) {
+ addSection("Accessibility");
+
+ if (hasContrastInfo)
+ addContrastRow(style["color"], elementInfo.contrast);
+
+ addTextRow("Name", elementInfo.accessibleName);
+ addTextRow("Role", elementInfo.accessibleRole);
+ addIconRow("Keyboard-focusable", elementInfo.isKeyboardFocusable ? "a11y-icon a11y-icon-ok" : "a11y-icon a11y-icon-not-ok");
+ }
+
+ function ensureElementInfoBody() {
if (!elementInfoBodyElement)
elementInfoBodyElement = elementInfoElement.createChild("div", "element-info-body")
+ }
+
+ function addSection(name) {
+ ensureElementInfoBody();
+ const rowElement = elementInfoBodyElement.createChild("div", "element-info-row element-info-section");
+ const nameElement = rowElement.createChild("div", "section-name");
+ nameElement.textContent = name;
+ const separatorElement = rowElement
+ .createChild("div", "separator-container")
+ .createChild("div", "separator");
+ }
+
+ function addRow(name, rowClassName, valueClassName) {
+ ensureElementInfoBody();
const rowElement = elementInfoBodyElement.createChild("div", "element-info-row");
if (rowClassName)
rowElement.classList.add(rowClassName);
@@ -548,22 +662,26 @@ function _createElementDescription(elementInfo)
return rowElement.createChild("div", valueClassName || "");
}
+ function addIconRow(name, value) {
+ addRow(name, "", "element-info-value-icon").createChild('div', value);
+ }
+
function addTextRow(name, value) {
addRow(name, "", "element-info-value-text").createTextChild(value);
}
- function addColorRow(name, color) {
+ function addColorRow(name, color, colorFormat) {
const valueElement = addRow(name, "", "element-info-value-color");
const swatch = valueElement.createChild("div", "color-swatch");
const inner = swatch.createChild("div", "color-swatch-inner");
inner.style.backgroundColor = color;
- valueElement.createTextChild(normalizeColorString(color));
+ valueElement.createTextChild(formatColor(color, colorFormat));
}
function addContrastRow(fgColor, contrast) {
const ratio = contrastRatio(parseHexa(fgColor), parseHexa(contrast.backgroundColor));
const threshold = computeIsLargeFont(contrast) ? 3.0 : 4.5;
- const valueElement = addRow("Contrast", "element-info-contrast-row", "element-info-value-contrast");
+ const valueElement = addRow("Contrast", "", "element-info-value-contrast");
const sampleText = valueElement.createChild("div", "contrast-text");
sampleText.style.color = fgColor;
sampleText.style.backgroundColor = contrast.backgroundColor;
@@ -576,11 +694,11 @@ function _createElementDescription(elementInfo)
return elementInfoElement;
}
-function _drawElementTitle(elementInfo, bounds)
+function _drawElementTitle(elementInfo, bounds, colorFormat)
{
const tooltipContainer = document.getElementById("tooltip-container");
tooltipContainer.removeChildren();
- _createMaterialTooltip(tooltipContainer, bounds, _createElementDescription(elementInfo), true);
+ _createMaterialTooltip(tooltipContainer, bounds, _createElementDescription(elementInfo, colorFormat), true);
}
function _createMaterialTooltip(parentElement, bounds, contentElement, withArrow)
@@ -651,14 +769,17 @@ function _createMaterialTooltip(parentElement, bounds, contentElement, withArrow
tooltipContent.style.setProperty('--arrow-left', (arrowX - boxX) + 'px');
}
-function _drawRulers(context, bounds, rulerAtRight, rulerAtBottom)
+function _drawRulers(context, bounds, rulerAtRight, rulerAtBottom, color, dash)
{
context.save();
var width = canvasWidth;
var height = canvasHeight;
- context.strokeStyle = "rgba(128, 128, 128, 0.3)";
+ context.strokeStyle = color || "rgba(128, 128, 128, 0.3)";
context.lineWidth = 1;
context.translate(0.5, 0.5);
+ if (dash) {
+ context.setLineDash([3, 3]);
+ }
if (rulerAtRight) {
for (var y in bounds.rightmostXForY) {
@@ -779,22 +900,150 @@ function emptyBounds()
function _drawLayoutGridHighlight(highlight, context)
{
+ // Draw Grid border
+ if (highlight.gridHighlightConfig.gridBorderColor) {
+ context.save();
+ context.translate(0.5, 0.5);
+ context.lineWidth = 0;
+ if (highlight.gridHighlightConfig.gridBorderDash) {
+ context.setLineDash([3, 3]);
+ }
+ context.strokeStyle = highlight.gridHighlightConfig.gridBorderColor;
+ context.stroke(buildPath(highlight.gridBorder, emptyBounds()));
+ context.restore();
+ }
+
+ // Draw Cell Border
+ if (highlight.gridHighlightConfig.cellBorderColor) {
+ const rowBounds = emptyBounds();
+ const columnBounds = emptyBounds();
+ const rowPath = buildPath(highlight.rows, rowBounds);
+ const columnPath = buildPath(highlight.columns, columnBounds);
+ context.save();
+ context.translate(0.5, 0.5);
+ if (highlight.gridHighlightConfig.cellBorderDash) {
+ context.setLineDash([3, 3]);
+ }
+ context.lineWidth = 0;
+ context.strokeStyle = highlight.gridHighlightConfig.cellBorderColor;
+
+ context.save();
+ context.clip(columnPath);
+ context.stroke(rowPath);
+ context.restore();
+
+ context.save();
+ context.clip(rowPath);
+ context.stroke(columnPath);
+ context.restore();
+
+ context.restore();
+
+ if (highlight.gridHighlightConfig.showGridExtensionLines) {
+ // Extend row gap lines left/up.
+ _drawRulers(context, rowBounds, /* rulerAtRight */ false, /* rulerAtBottom */ false, highlight.gridHighlightConfig.cellBorderColor, highlight.gridHighlightConfig.cellBorderDash);
+ // Extend row gap right/down.
+ _drawRulers(context, rowBounds, /* rulerAtRight */ true, /* rulerAtBottom */ true, highlight.gridHighlightConfig.cellBorderColor, highlight.gridHighlightConfig.cellBorderDash);
+ // Extend column lines left/up.
+ _drawRulers(context, columnBounds, /* rulerAtRight */ false, /* rulerAtBottom */ false, highlight.gridHighlightConfig.cellBorderColor, highlight.gridHighlightConfig.cellBorderDash);
+ // Extend column right/down.
+ _drawRulers(context, columnBounds, /* rulerAtRight */ true, /* rulerAtBottom */ true, highlight.gridHighlightConfig.cellBorderColor, highlight.gridHighlightConfig.cellBorderDash);
+ }
+ }
+
+ // Row Gaps
+ if (highlight.gridHighlightConfig.rowGapColor) {
+ context.save();
+ context.translate(0.5, 0.5);
+ context.lineWidth = 0;
+ context.fillStyle = highlight.gridHighlightConfig.rowGapColor;
+ let bounds = emptyBounds();
+ const path = buildPath(highlight.rowGaps, bounds);
+ if (highlight.gridHighlightConfig.rowHatchColor) {
+ hatchFillPath(context, path, bounds, 10, highlight.gridHighlightConfig.rowHatchColor, /* flipDirection */ true);
+ }
+ context.fill(path);
+ context.restore();
+ }
+
+ // Column Gaps
+ if (highlight.gridHighlightConfig.columnGapColor) {
+ context.save();
+ context.translate(0.5, 0.5);
+ context.lineWidth = 0;
+ context.fillStyle = highlight.gridHighlightConfig.columnGapColor;
+ let bounds = emptyBounds();
+ const path = buildPath(highlight.columnGaps, bounds);
+ if (highlight.gridHighlightConfig.columnHatchColor) {
+ hatchFillPath(context, path, bounds, 10, highlight.gridHighlightConfig.columnHatchColor);
+ }
+ context.fill(path);
+ context.restore();
+ }
+}
+
+/**
+ * Draw line hatching at a 45 degree angle for a given
+ * path.
+ * __________
+ * |\ \ \ |
+ * | \ \ \|
+ * | \ \ |
+ * |\ \ \ |
+ * **********
+ *
+ * @param {CanvasRenderingContext2D} context
+ * @param {Path2D} path
+ * @param {Object} bounds
+ * @param {delta} delta - vertical gap between hatching lines in pixels
+ * @param {string} color
+ * @param {boolean=} flipDirection - lines are drawn from top right to bottom left
+ *
+ */
+function hatchFillPath(context, path, bounds, delta, color, flipDirection) {
+ const dx = bounds.maxX - bounds.minX;
+ const dy = bounds.maxY - bounds.minY;
+ context.rect(bounds.minX, bounds.minY, dx, dy);
context.save();
- context.translate(0.5, 0.5);
- context.setLineDash([3, 3]);
- context.lineWidth = 0;
- context.strokeStyle = highlight.color;
- context.stroke(buildPath(highlight.cells, emptyBounds()));
+ context.clip(path);
+ context.setLineDash([5, 3]);
+ const majorAxis = Math.max(dx, dy);
+ context.strokeStyle = color;
+ if (flipDirection) {
+ for (let i = -majorAxis; i < majorAxis; i += delta) {
+ context.beginPath();
+ context.moveTo(bounds.maxX - i , bounds.minY);
+ context.lineTo(bounds.maxX - dy - i, bounds.maxY);
+ context.stroke();
+ }
+ } else {
+ for (let i = -majorAxis; i < majorAxis; i += delta) {
+ context.beginPath();
+ context.moveTo(i + bounds.minX, bounds.minY);
+ context.lineTo(dy + i + bounds.minX, bounds.maxY);
+ context.stroke();
+ }
+ }
context.restore();
}
-function clipLayoutGridCells(highlight) {
+function clipLayoutGridCells(highlight, context) {
+ // It may seem simpler to, before drawing the desired path, call context.clip()
+ // with the rows and then with the columns. However, the 2nd context.clip() call
+ // would try to find the intersection of the rows and columns, which is way too
+ // expensive if the grid is huge, e.g. a 1000x1000 grid has 1M cells.
+ // Therefore, it's better to draw the path first, set the globalCompositeOperation
+ // so that the existing canvas content is kept where it overlaps with new content,
+ // and then draw the rows and columns.
if (highlight.gridInfo) {
for (const grid of highlight.gridInfo) {
if (!grid.isPrimaryGrid)
continue;
- const path = buildPath(grid.cells, emptyBounds());
- context.clip(path);
+ context.save();
+ context.globalCompositeOperation = "destination-in";
+ drawPath(context, grid.rows, "red", null, emptyBounds());
+ drawPath(context, grid.columns, "red", null, emptyBounds());
+ context.restore();
}
}
}
@@ -808,15 +1057,15 @@ function drawHighlight(highlight, context)
for (var paths = highlight.paths.slice(); paths.length;) {
var path = paths.pop();
- // Clip content quad using the data grid cells info to create white stripes.
context.save();
- if (path.name === "content")
- clipLayoutGridCells(highlight);
drawPath(context, path.path, path.fillColor, path.outlineColor, bounds);
if (paths.length) {
context.globalCompositeOperation = "destination-out";
drawPath(context, paths[paths.length - 1].path, "red", null, bounds);
}
+ // Clip content quad using the data grid cells info to create white stripes.
+ if (path.name === "content")
+ clipLayoutGridCells(highlight, context);
context.restore();
}
context.restore();
@@ -834,7 +1083,7 @@ function drawHighlight(highlight, context)
_drawRulers(context, bounds, rulerAtRight, rulerAtBottom);
if (highlight.elementInfo)
- _drawElementTitle(highlight.elementInfo, bounds);
+ _drawElementTitle(highlight.elementInfo, bounds, highlight.colorFormat);
}
if (highlight.gridInfo) {
for (var grid of highlight.gridInfo)
@@ -851,7 +1100,7 @@ function test() {
drawHighlight(
{"paths":[{"path":["M",122,133.796875,"L",822,133.796875,"L",822,208.796875,"L",122,208.796875,"Z"], "fillColor":"rgba(111, 168, 220, 0.658823529411765)","name":"content"},
{"path":["M",122,113.796875,"L",822,113.796875,"L",822,228.796875,"L",122,228.796875,"Z"],"fillColor":"rgba(246, 178, 107, 0.66)","name":"margin"}],"showRulers":false,"showExtensionLines":false,
- "elementInfo":{"tagName":"button","className":"class.name", "idValue":"download-hero","nodeWidth":"700","nodeHeight":"75","style":{"color":"#FFFFFFFF","font-family":"\"Product Sans\", \"Open Sans\", Roboto, Arial, \"Product Sans\", \"Open Sans\", Roboto, Arial","font-size":"20px","line-height":"25px","padding":"0px","margin":"20px 0px","background-color":"#00000000"},"contrast":{"fontSize":"20px","fontWeight":"400","backgroundColor":"#F9B826BF"}}, showExtensionLines: true, showRulers: true});
+ "elementInfo":{"tagName":"button","className":"class.name", "idValue":"download-hero","nodeWidth":"700","nodeHeight":"75","style":{"color":"#FFFFFFFF","font-family":"\"Product Sans\", \"Open Sans\", Roboto, Arial, \"Product Sans\", \"Open Sans\", Roboto, Arial","font-size":"20px","line-height":"25px","padding":"0px","margin":"20px 0px","background-color":"#00000000"},"contrast":{"fontSize":"20px","fontWeight":"400","backgroundColor":"#F9B826BF"},"isKeyboardFocusable":false,"accessibleName":"name","accessibleRole":"role","showAccessibilityInfo":true}, showExtensionLines: true, showRulers: true, colorFormat: "hsl"});
}
</script>
diff --git a/chromium/third_party/blink/renderer/core/inspector/inspect_tools.cc b/chromium/third_party/blink/renderer/core/inspector/inspect_tools.cc
index 866afa057bf..502c7676fca 100644
--- a/chromium/third_party/blink/renderer/core/inspector/inspect_tools.cc
+++ b/chromium/third_party/blink/renderer/core/inspector/inspect_tools.cc
@@ -142,8 +142,8 @@ void SearchingForNodeTool::Draw(float scale) {
bool SearchingForNodeTool::HandleInputEvent(LocalFrameView* frame_view,
const WebInputEvent& input_event,
bool* swallow_next_mouse_up) {
- if (input_event.GetType() == WebInputEvent::kGestureScrollBegin ||
- input_event.GetType() == WebInputEvent::kGestureScrollUpdate) {
+ if (input_event.GetType() == WebInputEvent::Type::kGestureScrollBegin ||
+ input_event.GetType() == WebInputEvent::Type::kGestureScrollUpdate) {
hovered_node_.Clear();
event_target_node_.Clear();
overlay_->ScheduleUpdate();
@@ -297,6 +297,10 @@ bool NodeHighlightTool::HideOnHideHighlight() {
return true;
}
+bool NodeHighlightTool::HideOnMouseMove() {
+ return true;
+}
+
void NodeHighlightTool::Draw(float scale) {
DrawNode();
DrawMatchingSelector();
diff --git a/chromium/third_party/blink/renderer/core/inspector/inspect_tools.h b/chromium/third_party/blink/renderer/core/inspector/inspect_tools.h
index 5117ebd7760..3d19e9ada1b 100644
--- a/chromium/third_party/blink/renderer/core/inspector/inspect_tools.h
+++ b/chromium/third_party/blink/renderer/core/inspector/inspect_tools.h
@@ -75,6 +75,7 @@ class NodeHighlightTool : public InspectTool {
private:
bool ForwardEventsToOverlay() override;
+ bool HideOnMouseMove() override;
bool HideOnHideHighlight() override;
void Draw(float scale) override;
void DrawNode();
diff --git a/chromium/third_party/blink/renderer/core/inspector/inspector_animation_agent.cc b/chromium/third_party/blink/renderer/core/inspector/inspector_animation_agent.cc
index 786c300e858..734a3349e14 100644
--- a/chromium/third_party/blink/renderer/core/inspector/inspector_animation_agent.cc
+++ b/chromium/third_party/blink/renderer/core/inspector/inspector_animation_agent.cc
@@ -193,7 +193,7 @@ InspectorAnimationAgent::BuildObjectForAnimation(blink::Animation& animation) {
.setPlayState(animation.PlayStateString())
.setPlaybackRate(animation.playbackRate())
.setStartTime(NormalizedStartTime(animation))
- .setCurrentTime(animation.currentTime())
+ .setCurrentTime(animation.currentTime().value_or(Timing::NullValue()))
.setType(animation_type)
.build();
if (animation_type != AnimationType::WebAnimation)
@@ -225,10 +225,10 @@ Response InspectorAnimationAgent::getCurrentTime(const String& id,
animation = id_to_animation_clone_.at(id);
if (animation->Paused() || !animation->timeline()->IsActive()) {
- *current_time = animation->currentTime();
+ *current_time = animation->currentTime().value_or(Timing::NullValue());
} else {
// Use startTime where possible since currentTime is limited.
- base::Optional<double> timeline_time = animation->timeline()->CurrentTime();
+ base::Optional<double> timeline_time = animation->timeline()->currentTime();
// TODO(crbug.com/916117): Handle NaN values for scroll linked animations.
*current_time =
timeline_time ? timeline_time.value() -
@@ -253,9 +253,9 @@ Response InspectorAnimationAgent::setPaused(
// Ensure we restore a current time if the animation is limited.
double current_time = 0;
if (!clone->timeline()->IsActive()) {
- current_time = clone->currentTime();
+ current_time = clone->currentTime().value_or(Timing::NullValue());
} else {
- base::Optional<double> timeline_time = clone->timeline()->CurrentTime();
+ base::Optional<double> timeline_time = clone->timeline()->currentTime();
// TODO(crbug.com/916117): Handle NaN values.
current_time =
timeline_time ? timeline_time.value() -
@@ -263,7 +263,7 @@ Response InspectorAnimationAgent::setPaused(
: Timing::NullValue();
}
clone->pause();
- clone->setCurrentTime(current_time, false);
+ clone->setCurrentTime(current_time);
} else if (!paused && clone->Paused()) {
clone->Unpause();
}
@@ -310,8 +310,7 @@ blink::Animation* InspectorAnimationAgent::AnimationClone(
id_to_animation_clone_.Set(id, clone);
id_to_animation_.Set(String::Number(clone->SequenceNumber()), clone);
clone->play();
- clone->setStartTime(animation->startTime().value_or(Timing::NullValue()),
- false);
+ clone->setStartTime(animation->startTime().value_or(Timing::NullValue()));
animation->SetEffectSuppressed(true);
}
@@ -331,7 +330,7 @@ Response InspectorAnimationAgent::seekAnimations(
return Response::ServerError("Failed to clone a detached animation.");
if (!clone->Paused())
clone->play();
- clone->setCurrentTime(current_time, false);
+ clone->setCurrentTime(current_time);
}
return Response::Success();
}
@@ -515,7 +514,8 @@ double InspectorAnimationAgent::NormalizedStartTime(
if (document_timeline) {
if (ReferenceTimeline().PlaybackRate() == 0) {
time_ms +=
- ReferenceTimeline().currentTime() - document_timeline->currentTime();
+ ReferenceTimeline().currentTime().value_or(Timing::NullValue()) -
+ document_timeline->currentTime().value_or(Timing::NullValue());
} else {
time_ms +=
(document_timeline->ZeroTime() - ReferenceTimeline().ZeroTime())
diff --git a/chromium/third_party/blink/renderer/core/inspector/inspector_audits_agent.cc b/chromium/third_party/blink/renderer/core/inspector/inspector_audits_agent.cc
index 7dfae515abc..de81a8e3df5 100644
--- a/chromium/third_party/blink/renderer/core/inspector/inspector_audits_agent.cc
+++ b/chromium/third_party/blink/renderer/core/inspector/inspector_audits_agent.cc
@@ -153,31 +153,43 @@ void InspectorAuditsAgent::InnerEnable() {
}
namespace {
-std::unique_ptr<protocol::Array<protocol::Audits::AffectedCookie>> BuildCookies(
- const WTF::Vector<mojom::blink::AffectedCookiePtr>& cookies) {
- auto result =
- std::make_unique<protocol::Array<protocol::Audits::AffectedCookie>>();
- for (const auto& cookie : cookies) {
- auto protocol_cookie = std::move(protocol::Audits::AffectedCookie::create()
- .setName(cookie->name)
- .setPath(cookie->path)
- .setDomain(cookie->domain));
- if (cookie->site_for_cookies) {
- protocol_cookie.setSiteForCookies(*cookie->site_for_cookies);
- }
- result->push_back(protocol_cookie.build());
+std::unique_ptr<protocol::Audits::AffectedCookie> BuildAffectedCookie(
+ const mojom::blink::AffectedCookiePtr& cookie) {
+ auto protocol_cookie = std::move(protocol::Audits::AffectedCookie::create()
+ .setName(cookie->name)
+ .setPath(cookie->path)
+ .setDomain(cookie->domain));
+ return protocol_cookie.build();
+}
+
+std::unique_ptr<protocol::Audits::AffectedRequest> BuildAffectedRequest(
+ const mojom::blink::AffectedRequestPtr& request) {
+ auto protocol_request = protocol::Audits::AffectedRequest::create()
+ .setRequestId(request->request_id)
+ .build();
+ if (!request->url.IsEmpty()) {
+ protocol_request->setUrl(request->url);
}
- return result;
+ return protocol_request;
+}
+
+std::unique_ptr<protocol::Audits::AffectedFrame> BuildAffectedFrame(
+ const mojom::blink::AffectedFramePtr& frame) {
+ return protocol::Audits::AffectedFrame::create()
+ .setFrameId(frame->frame_id)
+ .build();
}
+
blink::protocol::String InspectorIssueCodeValue(
mojom::blink::InspectorIssueCode code) {
switch (code) {
case mojom::blink::InspectorIssueCode::kSameSiteCookieIssue:
return protocol::Audits::InspectorIssueCodeEnum::SameSiteCookieIssue;
+ case mojom::blink::InspectorIssueCode::kMixedContentIssue:
+ return protocol::Audits::InspectorIssueCodeEnum::MixedContentIssue;
}
- NOTREACHED();
- return "unknown";
}
+
protocol::String BuildCookieExclusionReason(
mojom::blink::SameSiteCookieExclusionReason exclusion_reason) {
switch (exclusion_reason) {
@@ -190,9 +202,8 @@ protocol::String BuildCookieExclusionReason(
return protocol::Audits::SameSiteCookieExclusionReasonEnum::
ExcludeSameSiteNoneInsecure;
}
- NOTREACHED();
- return "unknown";
}
+
std::unique_ptr<std::vector<blink::protocol::String>>
BuildCookieExclusionReasons(
const WTF::Vector<mojom::blink::SameSiteCookieExclusionReason>&
@@ -204,6 +215,7 @@ BuildCookieExclusionReasons(
}
return protocol_exclusion_reasons;
}
+
protocol::String BuildCookieWarningReason(
mojom::blink::SameSiteCookieWarningReason warning_reason) {
switch (warning_reason) {
@@ -220,33 +232,28 @@ protocol::String BuildCookieWarningReason(
return protocol::Audits::SameSiteCookieWarningReasonEnum::
WarnSameSiteUnspecifiedLaxAllowUnsafe;
case blink::mojom::blink::SameSiteCookieWarningReason::
- WarnSameSiteCrossSchemeSecureUrlMethodUnsafe:
- return protocol::Audits::SameSiteCookieWarningReasonEnum::
- WarnSameSiteCrossSchemeSecureUrlMethodUnsafe;
- case blink::mojom::blink::SameSiteCookieWarningReason::
- WarnSameSiteCrossSchemeSecureUrlLax:
+ WarnSameSiteStrictLaxDowngradeStrict:
return protocol::Audits::SameSiteCookieWarningReasonEnum::
- WarnSameSiteCrossSchemeSecureUrlLax;
+ WarnSameSiteStrictLaxDowngradeStrict;
case blink::mojom::blink::SameSiteCookieWarningReason::
- WarnSameSiteCrossSchemeSecureUrlStrict:
+ WarnSameSiteStrictCrossDowngradeStrict:
return protocol::Audits::SameSiteCookieWarningReasonEnum::
- WarnSameSiteCrossSchemeSecureUrlStrict;
+ WarnSameSiteStrictCrossDowngradeStrict;
case blink::mojom::blink::SameSiteCookieWarningReason::
- WarnSameSiteCrossSchemeInsecureUrlMethodUnsafe:
+ WarnSameSiteStrictCrossDowngradeLax:
return protocol::Audits::SameSiteCookieWarningReasonEnum::
- WarnSameSiteCrossSchemeInsecureUrlMethodUnsafe;
+ WarnSameSiteStrictCrossDowngradeLax;
case blink::mojom::blink::SameSiteCookieWarningReason::
- WarnSameSiteCrossSchemeInsecureUrlLax:
+ WarnSameSiteLaxCrossDowngradeStrict:
return protocol::Audits::SameSiteCookieWarningReasonEnum::
- WarnSameSiteCrossSchemeInsecureUrlLax;
+ WarnSameSiteLaxCrossDowngradeStrict;
case blink::mojom::blink::SameSiteCookieWarningReason::
- WarnSameSiteCrossSchemeInsecureUrlStrict:
+ WarnSameSiteLaxCrossDowngradeLax:
return protocol::Audits::SameSiteCookieWarningReasonEnum::
- WarnSameSiteCrossSchemeInsecureUrlStrict;
+ WarnSameSiteLaxCrossDowngradeLax;
}
- NOTREACHED();
- return "unknown";
}
+
std::unique_ptr<std::vector<blink::protocol::String>> BuildCookieWarningReasons(
const WTF::Vector<mojom::blink::SameSiteCookieWarningReason>&
warning_reasons) {
@@ -257,32 +264,154 @@ std::unique_ptr<std::vector<blink::protocol::String>> BuildCookieWarningReasons(
}
return protocol_warning_reasons;
}
+protocol::String BuildCookieOperation(
+ mojom::blink::SameSiteCookieOperation operation) {
+ switch (operation) {
+ case blink::mojom::blink::SameSiteCookieOperation::SetCookie:
+ return protocol::Audits::SameSiteCookieOperationEnum::SetCookie;
+ case blink::mojom::blink::SameSiteCookieOperation::ReadCookie:
+ return protocol::Audits::SameSiteCookieOperationEnum::ReadCookie;
+ }
+}
+
+protocol::String BuildMixedContentResolutionStatus(
+ mojom::blink::MixedContentResolutionStatus resolution_type) {
+ switch (resolution_type) {
+ case blink::mojom::blink::MixedContentResolutionStatus::MixedContentBlocked:
+ return protocol::Audits::MixedContentResolutionStatusEnum::
+ MixedContentBlocked;
+ case blink::mojom::blink::MixedContentResolutionStatus::
+ MixedContentAutomaticallyUpgraded:
+ return protocol::Audits::MixedContentResolutionStatusEnum::
+ MixedContentAutomaticallyUpgraded;
+ case blink::mojom::blink::MixedContentResolutionStatus::MixedContentWarning:
+ return protocol::Audits::MixedContentResolutionStatusEnum::
+ MixedContentWarning;
+ }
+}
+
+protocol::String BuildMixedContentResourceType(
+ mojom::blink::RequestContextType request_context) {
+ switch (request_context) {
+ case blink::mojom::blink::RequestContextType::AUDIO:
+ return protocol::Audits::MixedContentResourceTypeEnum::Audio;
+ case blink::mojom::blink::RequestContextType::BEACON:
+ return protocol::Audits::MixedContentResourceTypeEnum::Beacon;
+ case blink::mojom::blink::RequestContextType::CSP_REPORT:
+ return protocol::Audits::MixedContentResourceTypeEnum::CSPReport;
+ case blink::mojom::blink::RequestContextType::DOWNLOAD:
+ return protocol::Audits::MixedContentResourceTypeEnum::Download;
+ case blink::mojom::blink::RequestContextType::EMBED:
+ return protocol::Audits::MixedContentResourceTypeEnum::PluginResource;
+ case blink::mojom::blink::RequestContextType::EVENT_SOURCE:
+ return protocol::Audits::MixedContentResourceTypeEnum::EventSource;
+ case blink::mojom::blink::RequestContextType::FAVICON:
+ return protocol::Audits::MixedContentResourceTypeEnum::Favicon;
+ case blink::mojom::blink::RequestContextType::FETCH:
+ return protocol::Audits::MixedContentResourceTypeEnum::Resource;
+ case blink::mojom::blink::RequestContextType::FONT:
+ return protocol::Audits::MixedContentResourceTypeEnum::Font;
+ case blink::mojom::blink::RequestContextType::FORM:
+ return protocol::Audits::MixedContentResourceTypeEnum::Form;
+ case blink::mojom::blink::RequestContextType::FRAME:
+ return protocol::Audits::MixedContentResourceTypeEnum::Frame;
+ case blink::mojom::blink::RequestContextType::HYPERLINK:
+ return protocol::Audits::MixedContentResourceTypeEnum::Resource;
+ case blink::mojom::blink::RequestContextType::IFRAME:
+ return protocol::Audits::MixedContentResourceTypeEnum::Frame;
+ case blink::mojom::blink::RequestContextType::IMAGE:
+ return protocol::Audits::MixedContentResourceTypeEnum::Image;
+ case blink::mojom::blink::RequestContextType::IMAGE_SET:
+ return protocol::Audits::MixedContentResourceTypeEnum::Image;
+ case blink::mojom::blink::RequestContextType::IMPORT:
+ return protocol::Audits::MixedContentResourceTypeEnum::Import;
+ case blink::mojom::blink::RequestContextType::INTERNAL:
+ return protocol::Audits::MixedContentResourceTypeEnum::Resource;
+ case blink::mojom::blink::RequestContextType::LOCATION:
+ return protocol::Audits::MixedContentResourceTypeEnum::Resource;
+ case blink::mojom::blink::RequestContextType::MANIFEST:
+ return protocol::Audits::MixedContentResourceTypeEnum::Manifest;
+ case blink::mojom::blink::RequestContextType::OBJECT:
+ return protocol::Audits::MixedContentResourceTypeEnum::PluginResource;
+ case blink::mojom::blink::RequestContextType::PING:
+ return protocol::Audits::MixedContentResourceTypeEnum::Ping;
+ case blink::mojom::blink::RequestContextType::PLUGIN:
+ return protocol::Audits::MixedContentResourceTypeEnum::PluginData;
+ case blink::mojom::blink::RequestContextType::PREFETCH:
+ return protocol::Audits::MixedContentResourceTypeEnum::Prefetch;
+ case blink::mojom::blink::RequestContextType::SCRIPT:
+ return protocol::Audits::MixedContentResourceTypeEnum::Script;
+ case blink::mojom::blink::RequestContextType::SERVICE_WORKER:
+ return protocol::Audits::MixedContentResourceTypeEnum::ServiceWorker;
+ case blink::mojom::blink::RequestContextType::SHARED_WORKER:
+ return protocol::Audits::MixedContentResourceTypeEnum::SharedWorker;
+ case blink::mojom::blink::RequestContextType::STYLE:
+ return protocol::Audits::MixedContentResourceTypeEnum::Stylesheet;
+ case blink::mojom::blink::RequestContextType::SUBRESOURCE:
+ return protocol::Audits::MixedContentResourceTypeEnum::Resource;
+ case blink::mojom::blink::RequestContextType::TRACK:
+ return protocol::Audits::MixedContentResourceTypeEnum::Track;
+ case blink::mojom::blink::RequestContextType::UNSPECIFIED:
+ return protocol::Audits::MixedContentResourceTypeEnum::Resource;
+ case blink::mojom::blink::RequestContextType::VIDEO:
+ return protocol::Audits::MixedContentResourceTypeEnum::Video;
+ case blink::mojom::blink::RequestContextType::WORKER:
+ return protocol::Audits::MixedContentResourceTypeEnum::Worker;
+ case blink::mojom::blink::RequestContextType::XML_HTTP_REQUEST:
+ return protocol::Audits::MixedContentResourceTypeEnum::XMLHttpRequest;
+ case blink::mojom::blink::RequestContextType::XSLT:
+ return protocol::Audits::MixedContentResourceTypeEnum::XSLT;
+ }
+}
+
} // namespace
void InspectorAuditsAgent::InspectorIssueAdded(InspectorIssue* issue) {
auto issueDetails = protocol::Audits::InspectorIssueDetails::create();
- if (issue->Details()->sameSiteCookieIssueDetails) {
+ if (const auto* d = issue->Details()->sameSiteCookieIssueDetails.get()) {
auto sameSiteCookieDetails =
- protocol::Audits::SameSiteCookieIssueDetails::create()
- .setCookieExclusionReasons(BuildCookieExclusionReasons(
- issue->Details()->sameSiteCookieIssueDetails->exclusionReason))
- .setCookieWarningReasons(BuildCookieWarningReasons(
- issue->Details()->sameSiteCookieIssueDetails->warningReason))
- .build();
- issueDetails.setSameSiteCookieIssueDetails(
- std::move(sameSiteCookieDetails));
+ std::move(protocol::Audits::SameSiteCookieIssueDetails::create()
+ .setCookie(BuildAffectedCookie(d->cookie))
+ .setCookieExclusionReasons(
+ BuildCookieExclusionReasons(d->exclusionReason))
+ .setCookieWarningReasons(
+ BuildCookieWarningReasons(d->warningReason))
+ .setOperation(BuildCookieOperation(d->operation)));
+
+ if (d->site_for_cookies) {
+ sameSiteCookieDetails.setSiteForCookies(*d->site_for_cookies);
+ }
+ if (d->cookie_url) {
+ sameSiteCookieDetails.setCookieUrl(*d->cookie_url);
+ }
+ if (d->request) {
+ sameSiteCookieDetails.setRequest(BuildAffectedRequest(d->request));
+ }
+ issueDetails.setSameSiteCookieIssueDetails(sameSiteCookieDetails.build());
}
- auto affectedResources =
- protocol::Audits::AffectedResources::create()
- .setCookies(BuildCookies(issue->Resources()->cookies))
- .build();
+ if (const auto* d = issue->Details()->mixed_content_issue_details.get()) {
+ auto mixedContentDetails =
+ protocol::Audits::MixedContentIssueDetails::create()
+ .setResourceType(BuildMixedContentResourceType(d->request_context))
+ .setResolutionStatus(
+ BuildMixedContentResolutionStatus(d->resolution_status))
+ .setInsecureURL(d->insecure_url)
+ .setMainResourceURL(d->main_resource_url)
+ .build();
+ if (d->request) {
+ mixedContentDetails->setRequest(BuildAffectedRequest(d->request));
+ }
+ if (d->frame) {
+ mixedContentDetails->setFrame(BuildAffectedFrame(d->frame));
+ }
+ issueDetails.setMixedContentIssueDetails(std::move(mixedContentDetails));
+ }
auto inspector_issue = protocol::Audits::InspectorIssue::create()
.setCode(InspectorIssueCodeValue(issue->Code()))
.setDetails(issueDetails.build())
- .setResources(std::move(affectedResources))
.build();
GetFrontend()->issueAdded(std::move(inspector_issue));
diff --git a/chromium/third_party/blink/renderer/core/inspector/inspector_css_agent.cc b/chromium/third_party/blink/renderer/core/inspector/inspector_css_agent.cc
index b7637eadd7e..ef7c1ca3a0a 100644
--- a/chromium/third_party/blink/renderer/core/inspector/inspector_css_agent.cc
+++ b/chromium/third_party/blink/renderer/core/inspector/inspector_css_agent.cc
@@ -60,6 +60,7 @@
#include "third_party/blink/renderer/core/display_lock/display_lock_utilities.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
#include "third_party/blink/renderer/core/dom/dom_node_ids.h"
+#include "third_party/blink/renderer/core/dom/flat_tree_traversal.h"
#include "third_party/blink/renderer/core/dom/node.h"
#include "third_party/blink/renderer/core/dom/text.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
@@ -860,6 +861,19 @@ void InspectorCSSAgent::ForcePseudoState(Element* element,
if (!node_id)
return;
+ // First check whether focus-within was set because focus or focus-within was
+ // forced for a child node.
+ NodeIdToNumberFocusedChildren::iterator focused_it =
+ node_id_to_number_focused_children_.find(node_id);
+ unsigned focused_count =
+ focused_it == node_id_to_number_focused_children_.end()
+ ? 0
+ : focused_it->value;
+ if (pseudo_type == CSSSelector::kPseudoFocusWithin && focused_count > 0) {
+ *result = true;
+ return;
+ }
+
NodeIdToForcedPseudoState::iterator it =
node_id_to_forced_pseudo_state_.find(node_id);
if (it == node_id_to_forced_pseudo_state_.end())
@@ -867,6 +881,7 @@ void InspectorCSSAgent::ForcePseudoState(Element* element,
bool force = false;
unsigned forced_pseudo_state = it->value;
+
switch (pseudo_type) {
case CSSSelector::kPseudoActive:
force = forced_pseudo_state & kPseudoActive;
@@ -1637,11 +1652,65 @@ Response InspectorCSSAgent::forcePseudoState(
node_id_to_forced_pseudo_state_.Set(node_id, forced_pseudo_state);
else
node_id_to_forced_pseudo_state_.erase(node_id);
+
+ // When adding focus or focus-within, we force focus-within for ancestor
+ // nodes to emulate real focus for user convenience.
+
+ // Flips from no forced focus to the forced focus (:focus or :focus-within).
+ if (((forced_pseudo_state & kPseudoFocus) == kPseudoFocus &&
+ (current_forced_pseudo_state & kPseudoFocus) == 0) ||
+ ((forced_pseudo_state & kPseudoFocusWithin) == kPseudoFocusWithin &&
+ (current_forced_pseudo_state & kPseudoFocusWithin) == 0)) {
+ IncrementFocusedCountForAncestors(element);
+ }
+
+ // Flips from the forced focus (:focus or :focus-within) to no focus.
+ if (((forced_pseudo_state & kPseudoFocus) == 0 &&
+ (current_forced_pseudo_state & kPseudoFocus) == kPseudoFocus) ||
+ ((forced_pseudo_state & kPseudoFocusWithin) == 0 &&
+ (current_forced_pseudo_state & kPseudoFocusWithin) ==
+ kPseudoFocusWithin)) {
+ DecrementFocusedCountForAncestors(element);
+ }
+
element->ownerDocument()->GetStyleEngine().MarkAllElementsForStyleRecalc(
StyleChangeReasonForTracing::Create(style_change_reason::kInspector));
return Response::Success();
}
+void InspectorCSSAgent::IncrementFocusedCountForAncestors(Element* element) {
+ for (Node& ancestor : FlatTreeTraversal::AncestorsOf(*element)) {
+ int node_id = dom_agent_->BoundNodeId(&ancestor);
+ if (!node_id)
+ continue;
+ NodeIdToNumberFocusedChildren::iterator it =
+ node_id_to_number_focused_children_.find(node_id);
+ unsigned count =
+ it == node_id_to_number_focused_children_.end() ? 0 : it->value;
+ node_id_to_number_focused_children_.Set(node_id, count + 1);
+ }
+}
+
+void InspectorCSSAgent::DecrementFocusedCountForAncestors(Element* element) {
+ for (Node& ancestor : FlatTreeTraversal::AncestorsOf(*element)) {
+ int node_id = dom_agent_->BoundNodeId(&ancestor);
+ if (!node_id)
+ continue;
+ NodeIdToNumberFocusedChildren::iterator it =
+ node_id_to_number_focused_children_.find(node_id);
+ unsigned count =
+ it == node_id_to_number_focused_children_.end() ? 1 : it->value;
+ if (count <= 1) {
+ // If `count - 1` is zero or overflows, erase the node_id
+ // from the map to save memory. If there is zero focused child
+ // elements, :focus-within should not be forced.
+ node_id_to_number_focused_children_.erase(node_id);
+ } else {
+ node_id_to_number_focused_children_.Set(node_id, count - 1);
+ }
+ }
+}
+
std::unique_ptr<protocol::CSS::CSSMedia> InspectorCSSAgent::BuildMediaObject(
const MediaList* media,
MediaListSource media_list_source,
@@ -2154,7 +2223,14 @@ void InspectorCSSAgent::ResetPseudoStates() {
documents_to_change.insert(element->ownerDocument());
}
+ for (auto& count : node_id_to_number_focused_children_) {
+ auto* element = To<Element>(dom_agent_->NodeForId(count.key));
+ if (element && element->ownerDocument())
+ documents_to_change.insert(element->ownerDocument());
+ }
+
node_id_to_forced_pseudo_state_.clear();
+ node_id_to_number_focused_children_.clear();
for (auto& document : documents_to_change) {
document->GetStyleEngine().MarkAllElementsForStyleRecalc(
StyleChangeReasonForTracing::Create(style_change_reason::kInspector));
diff --git a/chromium/third_party/blink/renderer/core/inspector/inspector_css_agent.h b/chromium/third_party/blink/renderer/core/inspector/inspector_css_agent.h
index 5815c86fbdb..449b85ea315 100644
--- a/chromium/third_party/blink/renderer/core/inspector/inspector_css_agent.h
+++ b/chromium/third_party/blink/renderer/core/inspector/inspector_css_agent.h
@@ -245,6 +245,7 @@ class CORE_EXPORT InspectorCSSAgent final
NodeToInspectorStyleSheet; // bogus "stylesheets" with elements' inline
// styles
typedef HashMap<int, unsigned> NodeIdToForcedPseudoState;
+ typedef HashMap<int, unsigned> NodeIdToNumberFocusedChildren;
void ResourceContentLoaded(std::unique_ptr<EnableCallback>);
void CompleteEnabled();
@@ -303,6 +304,9 @@ class CORE_EXPORT InspectorCSSAgent final
void ResetPseudoStates();
+ void IncrementFocusedCountForAncestors(Element*);
+ void DecrementFocusedCountForAncestors(Element*);
+
Member<InspectorDOMAgent> dom_agent_;
Member<InspectedFrames> inspected_frames_;
Member<InspectorNetworkAgent> network_agent_;
@@ -322,6 +326,7 @@ class CORE_EXPORT InspectorCSSAgent final
NodeToInspectorStyleSheet node_to_inspector_style_sheet_;
NodeIdToForcedPseudoState node_id_to_forced_pseudo_state_;
+ NodeIdToNumberFocusedChildren node_id_to_number_focused_children_;
Member<StyleRuleUsageTracker> tracker_;
diff --git a/chromium/third_party/blink/renderer/core/inspector/inspector_dom_agent.cc b/chromium/third_party/blink/renderer/core/inspector/inspector_dom_agent.cc
index ce49bb82a00..bcf226243cf 100644
--- a/chromium/third_party/blink/renderer/core/inspector/inspector_dom_agent.cc
+++ b/chromium/third_party/blink/renderer/core/inspector/inspector_dom_agent.cc
@@ -1541,9 +1541,13 @@ std::unique_ptr<protocol::DOM::Node> InspectorDOMAgent::BuildObjectForNode(
}
if (auto* template_element = DynamicTo<HTMLTemplateElement>(*element)) {
- value->setTemplateContent(BuildObjectForNode(
- template_element->content(), 0, pierce, nodes_map, flatten_result));
- force_push_children = true;
+ // The inspector should not try to access the .content() property of
+ // declarative Shadow DOM <template> elements, because it will be null.
+ if (!template_element->IsDeclarativeShadowRoot()) {
+ value->setTemplateContent(BuildObjectForNode(
+ template_element->content(), 0, pierce, nodes_map, flatten_result));
+ force_push_children = true;
+ }
}
if (element->GetPseudoId()) {
diff --git a/chromium/third_party/blink/renderer/core/inspector/inspector_dom_snapshot_agent.cc b/chromium/third_party/blink/renderer/core/inspector/inspector_dom_snapshot_agent.cc
index 85e99a901d4..42755c8a650 100644
--- a/chromium/third_party/blink/renderer/core/inspector/inspector_dom_snapshot_agent.cc
+++ b/chromium/third_party/blink/renderer/core/inspector/inspector_dom_snapshot_agent.cc
@@ -141,6 +141,63 @@ String GetOriginUrl(const Node* node) {
return node->GetDocument().Url().GetString();
}
+class DOMTreeIterator {
+ STACK_ALLOCATED();
+
+ public:
+ DOMTreeIterator(Node* root, int root_node_id)
+ : current_(root), path_to_current_node_({root_node_id}) {
+ DCHECK(current_);
+ }
+
+ void Advance(int next_node_id) {
+ DCHECK(current_);
+ const bool skip_shadow_root =
+ current_->GetShadowRoot() && current_->GetShadowRoot()->IsUserAgent();
+ if (Node* first_child = skip_shadow_root
+ ? FirstFlatTreeSibling(current_->firstChild())
+ : FlatTreeTraversal::FirstChild(*current_)) {
+ current_ = first_child;
+ path_to_current_node_.push_back(next_node_id);
+ return;
+ }
+ // No children, let's try siblings, then ancestor siblings.
+ while (current_) {
+ const bool in_ua_shadow_tree =
+ current_->ParentElementShadowRoot() &&
+ current_->ParentElementShadowRoot()->IsUserAgent();
+ if (Node* node = in_ua_shadow_tree
+ ? FirstFlatTreeSibling(current_->nextSibling())
+ : FlatTreeTraversal::NextSibling(*current_)) {
+ path_to_current_node_.back() = next_node_id;
+ current_ = node;
+ return;
+ }
+ current_ = in_ua_shadow_tree ? current_->parentNode()
+ : FlatTreeTraversal::Parent(*current_);
+ path_to_current_node_.pop_back();
+ }
+ DCHECK(path_to_current_node_.IsEmpty());
+ }
+
+ Node* CurrentNode() const { return current_; }
+
+ int ParentNodeId() const {
+ return path_to_current_node_.size() > 1
+ ? *(path_to_current_node_.rbegin() + 1)
+ : -1;
+ }
+
+ private:
+ static Node* FirstFlatTreeSibling(Node* node) {
+ while (node && !node->CanParticipateInFlatTree())
+ node = node->nextSibling();
+ return node;
+ }
+ Node* current_;
+ WTF::Vector<int> path_to_current_node_;
+};
+
} // namespace
// Returns |layout_object|'s bounding box in document coordinates.
@@ -417,11 +474,16 @@ void InspectorDOMSnapshotAgent::VisitDocument(Document* document) {
std::make_unique<protocol::Array<protocol::Array<double>>>());
}
- VisitNode(document, -1);
+ auto* node_names = document_->getNodes()->getNodeName(nullptr);
+ for (DOMTreeIterator it(document, node_names->size()); it.CurrentNode();
+ it.Advance(node_names->size())) {
+ DCHECK(!it.CurrentNode()->IsInUserAgentShadowRoot());
+ VisitNode(it.CurrentNode(), it.ParentNodeId());
+ }
documents_->emplace_back(std::move(document_));
}
-int InspectorDOMSnapshotAgent::VisitNode(Node* node, int parent_index) {
+void InspectorDOMSnapshotAgent::VisitNode(Node* node, int parent_index) {
String node_value;
switch (node->getNodeType()) {
case Node::kTextNode:
@@ -508,62 +570,6 @@ int InspectorDOMSnapshotAgent::VisitNode(Node* node, int parent_index) {
image_element->currentSrc());
}
}
- if (node->IsContainerNode())
- VisitContainerChildren(node, index);
- return index;
-}
-
-// static
-Node* InspectorDOMSnapshotAgent::FirstChild(
- const Node& node,
- bool include_user_agent_shadow_tree) {
- DCHECK(include_user_agent_shadow_tree || !node.IsInUserAgentShadowRoot());
- if (!include_user_agent_shadow_tree) {
- ShadowRoot* shadow_root = node.GetShadowRoot();
- if (shadow_root && shadow_root->GetType() == ShadowRootType::kUserAgent) {
- Node* child = node.firstChild();
- while (child && !child->CanParticipateInFlatTree())
- child = child->nextSibling();
- return child;
- }
- }
- return FlatTreeTraversal::FirstChild(node);
-}
-
-// static
-bool InspectorDOMSnapshotAgent::HasChildren(
- const Node& node,
- bool include_user_agent_shadow_tree) {
- return FirstChild(node, include_user_agent_shadow_tree);
-}
-
-// static
-Node* InspectorDOMSnapshotAgent::NextSibling(
- const Node& node,
- bool include_user_agent_shadow_tree) {
- DCHECK(include_user_agent_shadow_tree || !node.IsInUserAgentShadowRoot());
- if (!include_user_agent_shadow_tree) {
- if (node.ParentElementShadowRoot() &&
- node.ParentElementShadowRoot()->GetType() ==
- ShadowRootType::kUserAgent) {
- Node* sibling = node.nextSibling();
- while (sibling && !sibling->CanParticipateInFlatTree())
- sibling = sibling->nextSibling();
- return sibling;
- }
- }
- return FlatTreeTraversal::NextSibling(node);
-}
-
-void InspectorDOMSnapshotAgent::VisitContainerChildren(Node* container,
- int parent_index) {
- if (!HasChildren(*container, false))
- return;
-
- for (Node* child = FirstChild(*container, false); child;
- child = NextSibling(*child, false)) {
- VisitNode(child, parent_index);
- }
}
void InspectorDOMSnapshotAgent::VisitPseudoElements(Element* parent,
diff --git a/chromium/third_party/blink/renderer/core/inspector/inspector_dom_snapshot_agent.h b/chromium/third_party/blink/renderer/core/inspector/inspector_dom_snapshot_agent.h
index 8587c6147a9..d5ef9a5cee7 100644
--- a/chromium/third_party/blink/renderer/core/inspector/inspector_dom_snapshot_agent.h
+++ b/chromium/third_party/blink/renderer/core/inspector/inspector_dom_snapshot_agent.h
@@ -57,14 +57,6 @@ class CORE_EXPORT InspectorDOMSnapshotAgent final
void CharacterDataModified(CharacterData*);
void DidInsertDOMNode(Node*);
- // Helpers for traversal.
- static bool HasChildren(const Node& node,
- bool include_user_agent_shadow_tree);
- static Node* FirstChild(const Node& node,
- bool include_user_agent_shadow_tree);
- static Node* NextSibling(const Node& node,
- bool include_user_agent_shadow_tree);
-
// Helpers for rects
static PhysicalRect RectInDocument(const LayoutObject* layout_object);
static PhysicalRect TextFragmentRectInDocument(
@@ -88,7 +80,8 @@ class CORE_EXPORT InspectorDOMSnapshotAgent final
const String& value);
void SetRare(protocol::DOMSnapshot::RareBooleanData* data, int index);
void VisitDocument(Document*);
- int VisitNode(Node*, int parent_index);
+
+ void VisitNode(Node*, int parent_index);
void VisitContainerChildren(Node* container, int parent_index);
void VisitPseudoElements(Element* parent, int parent_index);
std::unique_ptr<protocol::Array<int>> BuildArrayForElementAttributes(Node*);
@@ -127,6 +120,7 @@ class CORE_EXPORT InspectorDOMSnapshotAgent final
Member<InspectedFrames> inspected_frames_;
Member<InspectorDOMDebuggerAgent> dom_debugger_agent_;
InspectorAgentState::Boolean enabled_;
+
DISALLOW_COPY_AND_ASSIGN(InspectorDOMSnapshotAgent);
};
diff --git a/chromium/third_party/blink/renderer/core/inspector/inspector_emulation_agent.cc b/chromium/third_party/blink/renderer/core/inspector/inspector_emulation_agent.cc
index 39b3efb5d0f..843b8c340dd 100644
--- a/chromium/third_party/blink/renderer/core/inspector/inspector_emulation_agent.cc
+++ b/chromium/third_party/blink/renderer/core/inspector/inspector_emulation_agent.cc
@@ -45,6 +45,8 @@ InspectorEmulationAgent::InspectorEmulationAgent(
navigator_platform_override_(&agent_state_,
/*default_value=*/WTF::String()),
user_agent_override_(&agent_state_, /*default_value=*/WTF::String()),
+ serialized_ua_metadata_override_(&agent_state_,
+ /*default_value=*/WTF::String()),
accept_language_override_(&agent_state_,
/*default_value=*/WTF::String()),
locale_override_(&agent_state_, /*default_value=*/WTF::String()),
@@ -77,9 +79,19 @@ std::unique_ptr<protocol::DOM::RGBA> ParseRGBA(
} // namespace
void InspectorEmulationAgent::Restore() {
- setUserAgentOverride(user_agent_override_.Get(),
- accept_language_override_.Get(),
- navigator_platform_override_.Get());
+ // Since serialized_ua_metadata_override_ can't directly be converted back
+ // to appropriate protocol message, we initially pass null and decode it
+ // directly.
+ WTF::String save_serialized_ua_metadata_override =
+ serialized_ua_metadata_override_.Get();
+ setUserAgentOverride(
+ user_agent_override_.Get(), accept_language_override_.Get(),
+ navigator_platform_override_.Get(),
+ protocol::Maybe<protocol::Emulation::UserAgentMetadata>());
+ ua_metadata_override_ = blink::UserAgentMetadata::Demarshal(
+ save_serialized_ua_metadata_override.Latin1());
+ serialized_ua_metadata_override_.Set(save_serialized_ua_metadata_override);
+
if (!locale_override_.Get().IsEmpty())
setLocaleOverride(locale_override_.Get());
if (!web_local_frame_)
@@ -155,8 +167,10 @@ Response InspectorEmulationAgent::disable() {
instrumenting_agents_->RemoveInspectorEmulationAgent(this);
enabled_ = false;
}
- setUserAgentOverride(String(), protocol::Maybe<String>(),
- protocol::Maybe<String>());
+
+ setUserAgentOverride(
+ String(), protocol::Maybe<String>(), protocol::Maybe<String>(),
+ protocol::Maybe<protocol::Emulation::UserAgentMetadata>());
if (!locale_override_.Get().IsEmpty())
setLocaleOverride(String());
if (!web_local_frame_)
@@ -530,7 +544,9 @@ Response InspectorEmulationAgent::clearDeviceMetricsOverride() {
Response InspectorEmulationAgent::setUserAgentOverride(
const String& user_agent,
protocol::Maybe<String> accept_language,
- protocol::Maybe<String> platform) {
+ protocol::Maybe<String> platform,
+ protocol::Maybe<protocol::Emulation::UserAgentMetadata>
+ ua_metadata_override) {
if (!user_agent.IsEmpty() || accept_language.isJust() || platform.isJust())
InnerEnable();
user_agent_override_.Set(user_agent);
@@ -540,6 +556,43 @@ Response InspectorEmulationAgent::setUserAgentOverride(
GetWebViewImpl()->GetPage()->GetSettings().SetNavigatorPlatformOverride(
navigator_platform_override_.Get());
}
+
+ if (ua_metadata_override.isJust()) {
+ if (user_agent.IsEmpty()) {
+ ua_metadata_override_ = base::nullopt;
+ serialized_ua_metadata_override_.Set(WTF::String());
+ return Response::InvalidParams(
+ "Can't specify UserAgentMetadata but no UA string");
+ }
+ std::unique_ptr<protocol::Emulation::UserAgentMetadata> ua_metadata =
+ ua_metadata_override.takeJust();
+ ua_metadata_override_.emplace();
+ if (ua_metadata->getBrands()) {
+ for (const auto& bv : *ua_metadata->getBrands()) {
+ blink::UserAgentBrandVersion out_bv;
+ out_bv.brand = bv->getBrand().Ascii();
+ out_bv.major_version = bv->getVersion().Ascii();
+ ua_metadata_override_->brand_version_list.push_back(std::move(out_bv));
+ }
+ }
+ ua_metadata_override_->full_version = ua_metadata->getFullVersion().Ascii();
+ ua_metadata_override_->platform = ua_metadata->getPlatform().Ascii();
+ ua_metadata_override_->platform_version =
+ ua_metadata->getPlatformVersion().Ascii();
+ ua_metadata_override_->architecture =
+ ua_metadata->getArchitecture().Ascii();
+ ua_metadata_override_->model = ua_metadata->getModel().Ascii();
+ ua_metadata_override_->mobile = ua_metadata->getMobile();
+ } else {
+ ua_metadata_override_ = base::nullopt;
+ }
+
+ std::string marshalled =
+ blink::UserAgentMetadata::Marshal(ua_metadata_override_)
+ .value_or(std::string());
+ serialized_ua_metadata_override_.Set(
+ WTF::String(marshalled.data(), marshalled.size()));
+
return Response::Success();
}
@@ -587,6 +640,14 @@ void InspectorEmulationAgent::ApplyUserAgentOverride(String* user_agent) {
*user_agent = user_agent_override_.Get();
}
+void InspectorEmulationAgent::ApplyUserAgentMetadataOverride(
+ base::Optional<blink::UserAgentMetadata>* ua_metadata) {
+ // This applies when UA override is set.
+ if (!user_agent_override_.Get().IsEmpty()) {
+ *ua_metadata = ua_metadata_override_;
+ }
+}
+
void InspectorEmulationAgent::InnerEnable() {
if (enabled_)
return;
diff --git a/chromium/third_party/blink/renderer/core/inspector/inspector_emulation_agent.h b/chromium/third_party/blink/renderer/core/inspector/inspector_emulation_agent.h
index 4c7739644aa..e87627062f5 100644
--- a/chromium/third_party/blink/renderer/core/inspector/inspector_emulation_agent.h
+++ b/chromium/third_party/blink/renderer/core/inspector/inspector_emulation_agent.h
@@ -7,6 +7,7 @@
#include "base/macros.h"
#include "base/optional.h"
+#include "third_party/blink/public/common/user_agent/user_agent_metadata.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/inspector/inspector_base_agent.h"
#include "third_party/blink/renderer/core/inspector/protocol/Emulation.h"
@@ -79,12 +80,16 @@ class CORE_EXPORT InspectorEmulationAgent final
protocol::Response setUserAgentOverride(
const String& user_agent,
protocol::Maybe<String> accept_language,
- protocol::Maybe<String> platform) override;
+ protocol::Maybe<String> platform,
+ protocol::Maybe<protocol::Emulation::UserAgentMetadata>
+ ua_metadata_override) override;
protocol::Response setLocaleOverride(protocol::Maybe<String>) override;
// InspectorInstrumentation API
void ApplyAcceptLanguageOverride(String* accept_lang);
void ApplyUserAgentOverride(String* user_agent);
+ void ApplyUserAgentMetadataOverride(
+ base::Optional<blink::UserAgentMetadata>* ua_metadata);
void FrameStartedLoading(LocalFrame*);
void PrepareRequest(DocumentLoader*,
ResourceRequest&,
@@ -131,6 +136,8 @@ class CORE_EXPORT InspectorEmulationAgent final
InspectorAgentState::String emulated_vision_deficiency_;
InspectorAgentState::String navigator_platform_override_;
InspectorAgentState::String user_agent_override_;
+ InspectorAgentState::String serialized_ua_metadata_override_;
+ base::Optional<blink::UserAgentMetadata> ua_metadata_override_;
InspectorAgentState::String accept_language_override_;
InspectorAgentState::String locale_override_;
InspectorAgentState::Double virtual_time_budget_;
diff --git a/chromium/third_party/blink/renderer/core/inspector/inspector_highlight.cc b/chromium/third_party/blink/renderer/core/inspector/inspector_highlight.cc
index 379b7ccf045..e0b532a2b7b 100644
--- a/chromium/third_party/blink/renderer/core/inspector/inspector_highlight.cc
+++ b/chromium/third_party/blink/renderer/core/inspector/inspector_highlight.cc
@@ -13,8 +13,8 @@
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
#include "third_party/blink/renderer/core/frame/visual_viewport.h"
#include "third_party/blink/renderer/core/geometry/dom_rect.h"
+#include "third_party/blink/renderer/core/inspector/dom_traversal_utils.h"
#include "third_party/blink/renderer/core/inspector/inspector_dom_agent.h"
-#include "third_party/blink/renderer/core/inspector/inspector_dom_snapshot_agent.h"
#include "third_party/blink/renderer/core/layout/adjust_for_absolute_zoom.h"
#include "third_party/blink/renderer/core/layout/layout_box.h"
#include "third_party/blink/renderer/core/layout/layout_grid.h"
@@ -308,6 +308,12 @@ std::unique_ptr<protocol::DictionaryValue> BuildElementInfo(Element* element) {
DOMRect* bounding_box = element->getBoundingClientRect();
element_info->setString("nodeWidth", String::Number(bounding_box->width()));
element_info->setString("nodeHeight", String::Number(bounding_box->height()));
+
+ element_info->setBoolean("showAccessibilityInfo", true);
+ element_info->setBoolean("isKeyboardFocusable",
+ element->IsKeyboardFocusable());
+ element_info->setString("accessibleName", element->computedName());
+ element_info->setString("accessibleRole", element->computedRole());
return element_info;
}
@@ -322,13 +328,50 @@ std::unique_ptr<protocol::DictionaryValue> BuildTextNodeInfo(Text* text_node) {
text_info->setString("nodeWidth", bounding_box.Width().ToString());
text_info->setString("nodeHeight", bounding_box.Height().ToString());
text_info->setString("tagName", "#text");
+ text_info->setBoolean("showAccessibilityInfo", false);
return text_info;
}
+std::unique_ptr<protocol::DictionaryValue> BuildGridHighlightConfigInfo(
+ const InspectorGridHighlightConfig& grid_config) {
+ std::unique_ptr<protocol::DictionaryValue> grid_config_info =
+ protocol::DictionaryValue::create();
+ grid_config_info->setBoolean("gridBorderDash", grid_config.grid_border_dash);
+ grid_config_info->setBoolean("cellBorderDash", grid_config.cell_border_dash);
+ grid_config_info->setBoolean("showGridExtensionLines",
+ grid_config.show_grid_extension_lines);
+
+ if (grid_config.grid_color != Color::kTransparent) {
+ grid_config_info->setString("gridBorderColor",
+ grid_config.grid_color.Serialized());
+ }
+ if (grid_config.cell_color != Color::kTransparent) {
+ grid_config_info->setString("cellBorderColor",
+ grid_config.cell_color.Serialized());
+ }
+ if (grid_config.row_gap_color != Color::kTransparent) {
+ grid_config_info->setString("rowGapColor",
+ grid_config.row_gap_color.Serialized());
+ }
+ if (grid_config.column_gap_color != Color::kTransparent) {
+ grid_config_info->setString("columnGapColor",
+ grid_config.column_gap_color.Serialized());
+ }
+ if (grid_config.row_hatch_color != Color::kTransparent) {
+ grid_config_info->setString("rowHatchColor",
+ grid_config.row_hatch_color.Serialized());
+ }
+ if (grid_config.column_hatch_color != Color::kTransparent) {
+ grid_config_info->setString("columnHatchColor",
+ grid_config.column_hatch_color.Serialized());
+ }
+ return grid_config_info;
+}
+
std::unique_ptr<protocol::DictionaryValue> BuildGridInfo(
LocalFrameView* containing_view,
LayoutGrid* layout_grid,
- Color color,
+ const InspectorHighlightConfig& highlight_config,
float scale,
bool isPrimary) {
std::unique_ptr<protocol::DictionaryValue> grid_info =
@@ -337,29 +380,88 @@ std::unique_ptr<protocol::DictionaryValue> BuildGridInfo(
const auto& rows = layout_grid->RowPositions();
const auto& columns = layout_grid->ColumnPositions();
- PathBuilder cell_builder;
auto row_gap =
layout_grid->GridGap(kForRows) + layout_grid->GridItemOffset(kForRows);
auto column_gap = layout_grid->GridGap(kForColumns) +
layout_grid->GridItemOffset(kForColumns);
+ PathBuilder row_builder;
+ PathBuilder row_gap_builder;
+ LayoutUnit row_left = columns.front();
+ LayoutUnit row_width = columns.back() - columns.front();
for (size_t i = 1; i < rows.size(); ++i) {
- for (size_t j = 1; j < columns.size(); ++j) {
- PhysicalOffset position(columns.at(j - 1), rows.at(i - 1));
- PhysicalSize size(columns.at(j) - columns.at(j - 1),
- rows.at(i) - rows.at(i - 1));
- if (i != rows.size() - 1)
- size.height -= row_gap;
- if (j != columns.size() - 1)
- size.width -= column_gap;
- PhysicalRect cell(position, size);
- FloatQuad cell_quad = layout_grid->LocalRectToAbsoluteQuad(cell);
- FrameQuadToViewport(containing_view, cell_quad);
- cell_builder.AppendPath(QuadToPath(cell_quad), scale);
+ // Rows
+ PhysicalOffset position(row_left, rows.at(i - 1));
+ PhysicalSize size(row_width, rows.at(i) - rows.at(i - 1));
+ if (i != rows.size() - 1)
+ size.height -= row_gap;
+ PhysicalRect row(position, size);
+ FloatQuad row_quad = layout_grid->LocalRectToAbsoluteQuad(row);
+ FrameQuadToViewport(containing_view, row_quad);
+ row_builder.AppendPath(QuadToPath(row_quad), scale);
+ // Row Gaps
+ if (i != rows.size() - 1) {
+ PhysicalOffset gap_position(row_left, rows.at(i) - row_gap);
+ PhysicalSize gap_size(row_width, row_gap);
+ PhysicalRect gap(gap_position, gap_size);
+ FloatQuad gap_quad = layout_grid->LocalRectToAbsoluteQuad(gap);
+ FrameQuadToViewport(containing_view, gap_quad);
+ row_gap_builder.AppendPath(QuadToPath(gap_quad), scale);
+ }
+ }
+ grid_info->setValue("rows", row_builder.Release());
+ grid_info->setValue("rowGaps", row_gap_builder.Release());
+
+ PathBuilder column_builder;
+ PathBuilder column_gap_builder;
+ LayoutUnit column_top = rows.front();
+ LayoutUnit column_height = rows.back() - rows.front();
+ for (size_t i = 1; i < columns.size(); ++i) {
+ PhysicalOffset position(columns.at(i - 1), column_top);
+ PhysicalSize size(columns.at(i) - columns.at(i - 1), column_height);
+ if (i != columns.size() - 1)
+ size.width -= column_gap;
+ PhysicalRect column(position, size);
+ FloatQuad column_quad = layout_grid->LocalRectToAbsoluteQuad(column);
+ FrameQuadToViewport(containing_view, column_quad);
+ column_builder.AppendPath(QuadToPath(column_quad), scale);
+ // Column Gaps
+ if (i != columns.size() - 1) {
+ PhysicalOffset gap_position(columns.at(i) - column_gap, column_top);
+ PhysicalSize gap_size(column_gap, column_height);
+ PhysicalRect gap(gap_position, gap_size);
+ FloatQuad gap_quad = layout_grid->LocalRectToAbsoluteQuad(gap);
+ FrameQuadToViewport(containing_view, gap_quad);
+ column_gap_builder.AppendPath(QuadToPath(gap_quad), scale);
}
}
- grid_info->setValue("cells", cell_builder.Release());
- grid_info->setString("color", color.Serialized());
+ grid_info->setValue("columns", column_builder.Release());
+ grid_info->setValue("columnGaps", column_gap_builder.Release());
+
+ // Grid border
+ PathBuilder grid_border_builder;
+ PhysicalOffset grid_position(row_left, column_top);
+ PhysicalSize grid_size(row_width, column_height);
+ PhysicalRect grid_rect(grid_position, grid_size);
+ FloatQuad grid_quad = layout_grid->LocalRectToAbsoluteQuad(grid_rect);
+ FrameQuadToViewport(containing_view, grid_quad);
+ grid_border_builder.AppendPath(QuadToPath(grid_quad), scale);
+ grid_info->setValue("gridBorder", grid_border_builder.Release());
+
+ if (highlight_config.css_grid != Color::kTransparent) {
+ // Legacy support for highlight_config.css_grid
+ std::unique_ptr<protocol::DictionaryValue> grid_config_info =
+ protocol::DictionaryValue::create();
+ grid_config_info->setString("cellBorderColor",
+ highlight_config.css_grid.Serialized());
+ grid_config_info->setBoolean("cellBorderDash", true);
+ grid_info->setValue("gridHighlightConfig", grid_config_info->clone());
+ } else {
+ grid_info->setValue(
+ "gridHighlightConfig",
+ BuildGridHighlightConfigInfo(*highlight_config.grid_highlight_config));
+ }
+
grid_info->setBoolean("isPrimaryGrid", isPrimary);
return grid_info;
}
@@ -425,17 +527,24 @@ PhysicalRect TextFragmentRectInRootFrame(
} // namespace
+InspectorHighlightConfig::InspectorHighlightConfig()
+ : show_info(false),
+ show_styles(false),
+ show_rulers(false),
+ show_extension_lines(false),
+ color_format(ColorFormat::HEX) {}
+
InspectorHighlight::InspectorHighlight(float scale)
: highlight_paths_(protocol::ListValue::create()),
show_rulers_(false),
show_extension_lines_(false),
- scale_(scale) {}
+ scale_(scale),
+ color_format_(ColorFormat::HEX) {}
-InspectorHighlightConfig::InspectorHighlightConfig()
- : show_info(false),
- show_styles(false),
- show_rulers(false),
- show_extension_lines(false) {}
+InspectorGridHighlightConfig::InspectorGridHighlightConfig()
+ : show_grid_extension_lines(false),
+ grid_border_dash(false),
+ cell_border_dash(false) {}
InspectorHighlight::InspectorHighlight(
Node* node,
@@ -447,7 +556,8 @@ InspectorHighlight::InspectorHighlight(
: highlight_paths_(protocol::ListValue::create()),
show_rulers_(highlight_config.show_rulers),
show_extension_lines_(highlight_config.show_extension_lines),
- scale_(1.f) {
+ scale_(1.f),
+ color_format_(highlight_config.color_format) {
DCHECK(!DisplayLockUtilities::NearestLockedExclusiveAncestor(*node));
LocalFrameView* frame_view = node->GetDocument().View();
if (frame_view) {
@@ -495,10 +605,7 @@ void InspectorHighlight::AppendDistanceInfo(Node* node) {
continue;
if (value->IsColorValue()) {
Color color = static_cast<const cssvalue::CSSColorValue*>(value)->Value();
- String hex_color =
- String::Format("#%02X%02X%02X%02X", color.Red(), color.Green(),
- color.Blue(), color.Alpha());
- computed_style_->setString(name, hex_color);
+ computed_style_->setString(name, ToHEXA(color));
} else {
computed_style_->setString(name, value->CssText());
}
@@ -532,10 +639,10 @@ void InspectorHighlight::VisitAndCollectDistanceInfo(Node* node) {
if (!node->IsContainerNode())
return;
- Node* first_child = InspectorDOMSnapshotAgent::FirstChild(*node, false);
- for (Node* child = first_child; child;
- child = InspectorDOMSnapshotAgent::NextSibling(*child, false))
+ for (Node* child = blink::dom_traversal_utils::FirstChild(*node, false);
+ child; child = blink::dom_traversal_utils::NextSibling(*child, false)) {
VisitAndCollectDistanceInfo(child);
+ }
}
void InspectorHighlight::VisitAndCollectDistanceInfo(
@@ -653,22 +760,24 @@ void InspectorHighlight::AppendNodeHighlight(
AppendQuad(border, highlight_config.border, Color::kTransparent, "border");
AppendQuad(margin, highlight_config.margin, Color::kTransparent, "margin");
- if (highlight_config.css_grid == Color::kTransparent)
+ if (highlight_config.css_grid == Color::kTransparent &&
+ !highlight_config.grid_highlight_config) {
return;
+ }
grid_info_ = protocol::ListValue::create();
if (layout_object->IsLayoutGrid()) {
- grid_info_->pushValue(
- BuildGridInfo(node->GetDocument().View(), ToLayoutGrid(layout_object),
- highlight_config.css_grid, scale_, true));
+ grid_info_->pushValue(BuildGridInfo(node->GetDocument().View(),
+ ToLayoutGrid(layout_object),
+ highlight_config, scale_, true));
}
LayoutObject* parent = layout_object->Parent();
if (!parent || !parent->IsLayoutGrid())
return;
if (!BuildNodeQuads(parent->GetNode(), &content, &padding, &border, &margin))
return;
- grid_info_->pushValue(
- BuildGridInfo(node->GetDocument().View(), ToLayoutGrid(parent),
- highlight_config.css_grid, scale_, false));
+ grid_info_->pushValue(BuildGridInfo(node->GetDocument().View(),
+ ToLayoutGrid(parent), highlight_config,
+ scale_, false));
}
std::unique_ptr<protocol::DictionaryValue> InspectorHighlight::AsProtocolValue()
@@ -678,6 +787,18 @@ std::unique_ptr<protocol::DictionaryValue> InspectorHighlight::AsProtocolValue()
object->setValue("paths", highlight_paths_->clone());
object->setBoolean("showRulers", show_rulers_);
object->setBoolean("showExtensionLines", show_extension_lines_);
+ switch (color_format_) {
+ case ColorFormat::RGB:
+ object->setString("colorFormat", "rgb");
+ break;
+ case ColorFormat::HSL:
+ object->setString("colorFormat", "hsl");
+ break;
+ case ColorFormat::HEX:
+ object->setString("colorFormat", "hex");
+ break;
+ }
+
if (model_) {
std::unique_ptr<protocol::DictionaryValue> distance_info =
protocol::DictionaryValue::create();
@@ -929,7 +1050,25 @@ InspectorHighlightConfig InspectorHighlight::DefaultConfig() {
config.show_styles = false;
config.show_rulers = true;
config.show_extension_lines = true;
- config.css_grid = Color(128, 128, 128, 0);
+ config.css_grid = Color::kTransparent;
+ config.color_format = ColorFormat::HEX;
+ config.grid_highlight_config = std::make_unique<InspectorGridHighlightConfig>(
+ InspectorHighlight::DefaultGridConfig());
+ return config;
+}
+
+// static
+InspectorGridHighlightConfig InspectorHighlight::DefaultGridConfig() {
+ InspectorGridHighlightConfig config;
+ config.grid_color = Color(255, 0, 0, 0);
+ config.cell_color = Color(128, 0, 0, 0);
+ config.row_gap_color = Color(0, 255, 0, 0);
+ config.column_gap_color = Color(0, 0, 255, 0);
+ config.row_hatch_color = Color(255, 255, 255, 0);
+ config.column_hatch_color = Color(128, 128, 128, 0);
+ config.show_grid_extension_lines = true;
+ config.grid_border_dash = false;
+ config.cell_border_dash = true;
return config;
}
diff --git a/chromium/third_party/blink/renderer/core/inspector/inspector_highlight.h b/chromium/third_party/blink/renderer/core/inspector/inspector_highlight.h
index 5ca5060888f..9625b3941cd 100644
--- a/chromium/third_party/blink/renderer/core/inspector/inspector_highlight.h
+++ b/chromium/third_party/blink/renderer/core/inspector/inspector_highlight.h
@@ -17,6 +17,25 @@ namespace blink {
class Color;
+enum class ColorFormat { RGB, HEX, HSL };
+struct CORE_EXPORT InspectorGridHighlightConfig {
+ USING_FAST_MALLOC(InspectorGridHighlightConfig);
+
+ public:
+ InspectorGridHighlightConfig();
+
+ Color grid_color;
+ Color cell_color;
+ Color row_gap_color;
+ Color column_gap_color;
+ Color row_hatch_color;
+ Color column_hatch_color;
+
+ bool show_grid_extension_lines;
+ bool grid_border_dash;
+ bool cell_border_dash;
+};
+
struct CORE_EXPORT InspectorHighlightConfig {
USING_FAST_MALLOC(InspectorHighlightConfig);
@@ -39,6 +58,9 @@ struct CORE_EXPORT InspectorHighlightConfig {
bool show_extension_lines;
String selector_list;
+ ColorFormat color_format;
+
+ std::unique_ptr<InspectorGridHighlightConfig> grid_highlight_config;
};
struct InspectorHighlightContrastInfo {
@@ -67,6 +89,7 @@ class CORE_EXPORT InspectorHighlight {
Node*,
std::unique_ptr<protocol::Array<protocol::Array<double>>>*);
static InspectorHighlightConfig DefaultConfig();
+ static InspectorGridHighlightConfig DefaultGridConfig();
void AppendPath(std::unique_ptr<protocol::ListValue> path,
const Color& fill_color,
@@ -106,6 +129,7 @@ class CORE_EXPORT InspectorHighlight {
bool show_rulers_;
bool show_extension_lines_;
float scale_;
+ ColorFormat color_format_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/inspector/inspector_issue.cc b/chromium/third_party/blink/renderer/core/inspector/inspector_issue.cc
index 93749ebb4e0..3ae80a29047 100644
--- a/chromium/third_party/blink/renderer/core/inspector/inspector_issue.cc
+++ b/chromium/third_party/blink/renderer/core/inspector/inspector_issue.cc
@@ -9,20 +9,15 @@
#include "third_party/blink/renderer/platform/wtf/assertions.h"
#include "third_party/blink/public/platform/web_string.h"
-#include "third_party/blink/public/web/web_inspector_issue.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
namespace blink {
InspectorIssue::InspectorIssue(mojom::blink::InspectorIssueCode code,
- mojom::blink::InspectorIssueDetailsPtr details,
- mojom::blink::AffectedResourcesPtr resources)
- : code_(code),
- details_(std::move(details)),
- resources_(std::move(resources)) {
+ mojom::blink::InspectorIssueDetailsPtr details)
+ : code_(code), details_(std::move(details)) {
DCHECK(details_);
- DCHECK(resources_);
}
InspectorIssue::~InspectorIssue() = default;
@@ -30,9 +25,8 @@ InspectorIssue::~InspectorIssue() = default;
InspectorIssue* InspectorIssue::Create(
mojom::blink::InspectorIssueInfoPtr info) {
DCHECK(info->details);
- DCHECK(info->resources);
- return MakeGarbageCollected<InspectorIssue>(
- info->code, std::move(info->details), std::move(info->resources));
+ return MakeGarbageCollected<InspectorIssue>(info->code,
+ std::move(info->details));
}
mojom::blink::InspectorIssueCode InspectorIssue::Code() const {
@@ -43,10 +37,6 @@ const mojom::blink::InspectorIssueDetailsPtr& InspectorIssue::Details() const {
return details_;
}
-const mojom::blink::AffectedResourcesPtr& InspectorIssue::Resources() const {
- return resources_;
-}
-
void InspectorIssue::Trace(blink::Visitor* visitor) {}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/inspector/inspector_issue.h b/chromium/third_party/blink/renderer/core/inspector/inspector_issue.h
index a97cd2ba467..3dc9037fa4d 100644
--- a/chromium/third_party/blink/renderer/core/inspector/inspector_issue.h
+++ b/chromium/third_party/blink/renderer/core/inspector/inspector_issue.h
@@ -19,22 +19,19 @@ class CORE_EXPORT InspectorIssue final
InspectorIssue() = delete;
InspectorIssue(mojom::blink::InspectorIssueCode code,
- mojom::blink::InspectorIssueDetailsPtr details,
- mojom::blink::AffectedResourcesPtr resources);
+ mojom::blink::InspectorIssueDetailsPtr details);
~InspectorIssue();
static InspectorIssue* Create(mojom::blink::InspectorIssueInfoPtr info);
mojom::blink::InspectorIssueCode Code() const;
const mojom::blink::InspectorIssueDetailsPtr& Details() const;
- const mojom::blink::AffectedResourcesPtr& Resources() const;
void Trace(Visitor*);
private:
mojom::blink::InspectorIssueCode code_;
mojom::blink::InspectorIssueDetailsPtr details_;
- mojom::blink::AffectedResourcesPtr resources_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/inspector/inspector_issue_storage.cc b/chromium/third_party/blink/renderer/core/inspector/inspector_issue_storage.cc
index dd081bbbbe3..803b7775cfd 100644
--- a/chromium/third_party/blink/renderer/core/inspector/inspector_issue_storage.cc
+++ b/chromium/third_party/blink/renderer/core/inspector/inspector_issue_storage.cc
@@ -23,6 +23,12 @@ void InspectorIssueStorage::AddInspectorIssue(ExecutionContext* context,
issues_.push_back(issue);
}
+void InspectorIssueStorage::AddInspectorIssue(
+ ExecutionContext* context,
+ mojom::blink::InspectorIssueInfoPtr info) {
+ AddInspectorIssue(context, InspectorIssue::Create(std::move(info)));
+}
+
void InspectorIssueStorage::Clear() {
issues_.clear();
}
diff --git a/chromium/third_party/blink/renderer/core/inspector/inspector_issue_storage.h b/chromium/third_party/blink/renderer/core/inspector/inspector_issue_storage.h
index d318c96d654..3a99f74185c 100644
--- a/chromium/third_party/blink/renderer/core/inspector/inspector_issue_storage.h
+++ b/chromium/third_party/blink/renderer/core/inspector/inspector_issue_storage.h
@@ -6,6 +6,7 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_INSPECTOR_INSPECTOR_ISSUE_STORAGE_H_
#include "base/macros.h"
+#include "third_party/blink/public/mojom/devtools/inspector_issue.mojom-blink-forward.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/wtf/forward.h"
@@ -21,6 +22,8 @@ class CORE_EXPORT InspectorIssueStorage
InspectorIssueStorage();
void AddInspectorIssue(ExecutionContext*, InspectorIssue*);
+ void AddInspectorIssue(ExecutionContext*,
+ mojom::blink::InspectorIssueInfoPtr);
void Clear();
wtf_size_t size() const;
InspectorIssue* at(wtf_size_t index) const;
diff --git a/chromium/third_party/blink/renderer/core/inspector/inspector_media_agent.cc b/chromium/third_party/blink/renderer/core/inspector/inspector_media_agent.cc
index 16a634f9f44..40e9ae5054b 100644
--- a/chromium/third_party/blink/renderer/core/inspector/inspector_media_agent.cc
+++ b/chromium/third_party/blink/renderer/core/inspector/inspector_media_agent.cc
@@ -13,35 +13,67 @@ namespace blink {
namespace {
-std::unique_ptr<protocol::Media::PlayerEvent> ConvertInspectorPlayerEvent(
- const InspectorPlayerEvent& event) {
- protocol::Media::PlayerEventType event_type;
- switch (event.type) {
- case InspectorPlayerEvent::ERROR_EVENT:
- event_type = protocol::Media::PlayerEventTypeEnum::ErrorEvent;
- break;
- case InspectorPlayerEvent::TRIGGERED_EVENT:
- event_type = protocol::Media::PlayerEventTypeEnum::TriggeredEvent;
- break;
- case InspectorPlayerEvent::MESSAGE_EVENT:
- event_type = protocol::Media::PlayerEventTypeEnum::MessageEvent;
- break;
+const char* ConvertMessageLevelEnum(InspectorPlayerMessage::Level level) {
+ switch (level) {
+ case InspectorPlayerMessage::Level::kError:
+ return protocol::Media::PlayerMessage::LevelEnum::Error;
+ case InspectorPlayerMessage::Level::kWarning:
+ return protocol::Media::PlayerMessage::LevelEnum::Warning;
+ case InspectorPlayerMessage::Level::kInfo:
+ return protocol::Media::PlayerMessage::LevelEnum::Info;
+ case InspectorPlayerMessage::Level::kDebug:
+ return protocol::Media::PlayerMessage::LevelEnum::Debug;
+ }
+}
+
+const char* ConvertErrorTypeEnum(InspectorPlayerError::Type level) {
+ switch (level) {
+ case InspectorPlayerError::Type::kPipelineError:
+ return protocol::Media::PlayerError::TypeEnum::Pipeline_error;
+ case InspectorPlayerError::Type::kMediaStatus:
+ return protocol::Media::PlayerError::TypeEnum::Media_error;
}
+}
+
+std::unique_ptr<protocol::Media::PlayerEvent> ConvertToProtocolType(
+ const InspectorPlayerEvent& event) {
return protocol::Media::PlayerEvent::create()
- .setType(event_type)
.setTimestamp(event.timestamp.since_origin().InSecondsF())
- .setName(event.key)
.setValue(event.value)
.build();
}
-std::unique_ptr<protocol::Media::PlayerProperty> ConvertInspectorPlayerProperty(
+std::unique_ptr<protocol::Media::PlayerProperty> ConvertToProtocolType(
const InspectorPlayerProperty& property) {
- auto builder = std::move(
- protocol::Media::PlayerProperty::create().setName(property.name));
- if (property.value.has_value())
- builder.setValue(property.value.value());
- return builder.build();
+ return protocol::Media::PlayerProperty::create()
+ .setName(property.name)
+ .setValue(property.value)
+ .build();
+}
+
+std::unique_ptr<protocol::Media::PlayerMessage> ConvertToProtocolType(
+ const InspectorPlayerMessage& message) {
+ return protocol::Media::PlayerMessage::create()
+ .setLevel(ConvertMessageLevelEnum(message.level))
+ .setMessage(message.message)
+ .build();
+}
+
+std::unique_ptr<protocol::Media::PlayerError> ConvertToProtocolType(
+ const InspectorPlayerError& error) {
+ return protocol::Media::PlayerError::create()
+ .setType(ConvertErrorTypeEnum(error.type))
+ .setErrorCode(error.errorCode)
+ .build();
+}
+
+template <typename To, typename From>
+std::unique_ptr<protocol::Array<To>> ConvertVector(const Vector<From>& from) {
+ auto result = std::make_unique<protocol::Array<To>>();
+ result->reserve(from.size());
+ for (const From& each : from)
+ result->push_back(ConvertToProtocolType(each));
+ return result;
}
} // namespace
@@ -60,13 +92,19 @@ void InspectorMediaAgent::Restore() {
void InspectorMediaAgent::RegisterAgent() {
instrumenting_agents_->AddInspectorMediaAgent(this);
- auto* cache = MediaInspectorContextImpl::FromLocalFrame(local_frame_);
- Vector<WebString> players = cache->GetAllPlayerIds();
+ auto* cache = MediaInspectorContextImpl::From(*local_frame_->DomWindow());
+ Vector<WebString> players = cache->AllPlayerIds();
PlayersCreated(players);
for (const auto& player_id : players) {
- auto props_events = cache->GetPropertiesAndEvents(player_id);
- PlayerPropertiesChanged(player_id, props_events.first);
- PlayerEventsAdded(player_id, props_events.second);
+ const auto& media_player = cache->MediaPlayerFromId(player_id);
+ Vector<InspectorPlayerProperty> properties;
+ properties.AppendRange(media_player.properties.Values().begin(),
+ media_player.properties.Values().end());
+
+ PlayerPropertiesChanged(player_id, properties);
+ PlayerMessagesLogged(player_id, media_player.messages);
+ PlayerEventsAdded(player_id, media_player.events);
+ PlayerErrorsRaised(player_id, media_player.errors);
}
}
@@ -89,23 +127,29 @@ protocol::Response InspectorMediaAgent::disable() {
void InspectorMediaAgent::PlayerPropertiesChanged(
const WebString& playerId,
const Vector<InspectorPlayerProperty>& properties) {
- auto protocol_props =
- std::make_unique<protocol::Array<protocol::Media::PlayerProperty>>();
- protocol_props->reserve(properties.size());
- for (const auto& property : properties)
- protocol_props->push_back(ConvertInspectorPlayerProperty(property));
- GetFrontend()->playerPropertiesChanged(playerId, std::move(protocol_props));
+ GetFrontend()->playerPropertiesChanged(
+ playerId, ConvertVector<protocol::Media::PlayerProperty>(properties));
}
void InspectorMediaAgent::PlayerEventsAdded(
const WebString& playerId,
const Vector<InspectorPlayerEvent>& events) {
- auto protocol_events =
- std::make_unique<protocol::Array<protocol::Media::PlayerEvent>>();
- protocol_events->reserve(events.size());
- for (const auto& event : events)
- protocol_events->push_back(ConvertInspectorPlayerEvent(event));
- GetFrontend()->playerEventsAdded(playerId, std::move(protocol_events));
+ GetFrontend()->playerEventsAdded(
+ playerId, ConvertVector<protocol::Media::PlayerEvent>(events));
+}
+
+void InspectorMediaAgent::PlayerErrorsRaised(
+ const WebString& playerId,
+ const Vector<InspectorPlayerError>& errors) {
+ GetFrontend()->playerErrorsRaised(
+ playerId, ConvertVector<protocol::Media::PlayerError>(errors));
+}
+
+void InspectorMediaAgent::PlayerMessagesLogged(
+ const WebString& playerId,
+ const Vector<InspectorPlayerMessage>& messages) {
+ GetFrontend()->playerMessagesLogged(
+ playerId, ConvertVector<protocol::Media::PlayerMessage>(messages));
}
void InspectorMediaAgent::PlayersCreated(const Vector<WebString>& player_ids) {
diff --git a/chromium/third_party/blink/renderer/core/inspector/inspector_media_agent.h b/chromium/third_party/blink/renderer/core/inspector/inspector_media_agent.h
index e7292fa4c51..b65460cf07f 100644
--- a/chromium/third_party/blink/renderer/core/inspector/inspector_media_agent.h
+++ b/chromium/third_party/blink/renderer/core/inspector/inspector_media_agent.h
@@ -30,9 +30,13 @@ class CORE_EXPORT InspectorMediaAgent final
protocol::Response disable() override;
// Protocol send messages.
+ void PlayerErrorsRaised(const WebString&,
+ const Vector<InspectorPlayerError>&);
+ void PlayerEventsAdded(const WebString&, const Vector<InspectorPlayerEvent>&);
+ void PlayerMessagesLogged(const WebString&,
+ const Vector<InspectorPlayerMessage>&);
void PlayerPropertiesChanged(const WebString&,
const Vector<InspectorPlayerProperty>&);
- void PlayerEventsAdded(const WebString&, const Vector<InspectorPlayerEvent>&);
void PlayersCreated(const Vector<WebString>&);
// blink-gc methods.
diff --git a/chromium/third_party/blink/renderer/core/inspector/inspector_media_context_impl.cc b/chromium/third_party/blink/renderer/core/inspector/inspector_media_context_impl.cc
index 445786bfedb..a172dc6d697 100644
--- a/chromium/third_party/blink/renderer/core/inspector/inspector_media_context_impl.cc
+++ b/chromium/third_party/blink/renderer/core/inspector/inspector_media_context_impl.cc
@@ -8,9 +8,7 @@
#include <utility>
#include "base/unguessable_token.h"
-#include "third_party/blink/renderer/core/dom/document.h"
-#include "third_party/blink/renderer/core/html/media/html_media_element.h"
-#include "third_party/blink/renderer/core/inspector/inspected_frames.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/probe/core_probes.h"
namespace blink {
@@ -18,40 +16,37 @@ namespace blink {
const char MediaInspectorContextImpl::kSupplementName[] =
"MediaInspectorContextImpl";
-// static
-void MediaInspectorContextImpl::ProvideToLocalFrame(LocalFrame& frame) {
- frame.ProvideSupplement(
- MakeGarbageCollected<MediaInspectorContextImpl>(frame));
-}
// static
-MediaInspectorContextImpl* MediaInspectorContextImpl::FromLocalFrame(
- LocalFrame* frame) {
- return Supplement<LocalFrame>::From<MediaInspectorContextImpl>(frame);
+MediaInspectorContextImpl* MediaInspectorContextImpl::From(
+ LocalDOMWindow& window) {
+ auto* context =
+ Supplement<LocalDOMWindow>::From<MediaInspectorContextImpl>(window);
+ if (!context) {
+ context = MakeGarbageCollected<MediaInspectorContextImpl>(window);
+ Supplement<LocalDOMWindow>::ProvideTo(window, context);
+ }
+ return context;
}
-// static
-MediaInspectorContextImpl* MediaInspectorContextImpl::FromDocument(
- const Document& document) {
- return MediaInspectorContextImpl::FromLocalFrame(document.GetFrame());
-}
+MediaInspectorContextImpl::MediaInspectorContextImpl(LocalDOMWindow& frame)
+ : Supplement<LocalDOMWindow>(frame) {}
-// static
-MediaInspectorContextImpl* MediaInspectorContextImpl::FromHtmlMediaElement(
- const HTMLMediaElement& element) {
- return MediaInspectorContextImpl::FromDocument(element.GetDocument());
+// Local to cc file for converting
+template <typename T, typename Iterable>
+static Vector<T> Iter2Vector(const Iterable& iterable) {
+ Vector<T> result;
+ result.AppendRange(iterable.begin(), iterable.end());
+ return result;
}
-MediaInspectorContextImpl::MediaInspectorContextImpl(LocalFrame& frame)
- : Supplement<LocalFrame>(frame) {}
-
// Garbage collection method.
void MediaInspectorContextImpl::Trace(Visitor* visitor) {
- Supplement<LocalFrame>::Trace(visitor);
+ Supplement<LocalDOMWindow>::Trace(visitor);
visitor->Trace(players_);
}
-Vector<WebString> MediaInspectorContextImpl::GetAllPlayerIds() {
+Vector<WebString> MediaInspectorContextImpl::AllPlayerIds() {
Vector<WebString> existing_players;
existing_players.ReserveCapacity(players_.size());
for (const auto& player_id : players_.Keys())
@@ -59,22 +54,11 @@ Vector<WebString> MediaInspectorContextImpl::GetAllPlayerIds() {
return existing_players;
}
-std::pair<Vector<InspectorPlayerProperty>, Vector<InspectorPlayerEvent>>
-MediaInspectorContextImpl::GetPropertiesAndEvents(const WebString& player_id) {
- Vector<InspectorPlayerProperty> to_send_properties;
- Vector<InspectorPlayerEvent> to_send_events;
-
- const auto& player_search = players_.find(player_id);
- if (player_search != players_.end()) {
- to_send_properties.ReserveCapacity(player_search->value->properties.size());
- for (const auto& prop : player_search->value->properties.Values())
- to_send_properties.push_back(prop);
- to_send_events.ReserveCapacity(player_search->value->events.size());
- for (const auto& event : player_search->value->events)
- to_send_events.insert(to_send_events.size(), event);
- }
-
- return {std::move(to_send_properties), std::move(to_send_events)};
+const MediaPlayer& MediaInspectorContextImpl::MediaPlayerFromId(
+ const WebString& player_id) {
+ const auto& player = players_.find(player_id);
+ DCHECK_NE(player, players_.end());
+ return *player->value;
}
WebString MediaInspectorContextImpl::CreatePlayer() {
@@ -86,34 +70,53 @@ WebString MediaInspectorContextImpl::CreatePlayer() {
}
// Convert public version of event to protocol version, and send it.
+void MediaInspectorContextImpl::NotifyPlayerErrors(
+ WebString playerId,
+ const InspectorPlayerErrors& errors) {
+ const auto& player = players_.find(playerId);
+ DCHECK_NE(player, players_.end());
+ player->value->errors.AppendRange(errors.begin(), errors.end());
+
+ Vector<InspectorPlayerError> vector =
+ Iter2Vector<InspectorPlayerError>(errors);
+ probe::PlayerErrorsRaised(GetSupplementable(), playerId, vector);
+}
+
void MediaInspectorContextImpl::NotifyPlayerEvents(
WebString playerId,
- InspectorPlayerEvents events) {
- const auto& player_search = players_.find(playerId);
- if (player_search == players_.end())
- DCHECK(false);
- Vector<InspectorPlayerEvent> to_send;
- to_send.ReserveCapacity(events.size());
- for (const auto& event : events) {
- player_search->value->events.emplace_back(event);
- to_send.push_back(event);
- }
- probe::PlayerEventsAdded(GetSupplementable(), playerId, to_send);
+ const InspectorPlayerEvents& events) {
+ const auto& player = players_.find(playerId);
+ DCHECK_NE(player, players_.end());
+ player->value->events.AppendRange(events.begin(), events.end());
+
+ Vector<InspectorPlayerEvent> vector =
+ Iter2Vector<InspectorPlayerEvent>(events);
+ probe::PlayerEventsAdded(GetSupplementable(), playerId, vector);
}
void MediaInspectorContextImpl::SetPlayerProperties(
WebString playerId,
- InspectorPlayerProperties props) {
- const auto& player_search = players_.find(playerId);
- if (player_search == players_.end())
- DCHECK(false);
- Vector<InspectorPlayerProperty> to_send;
- to_send.ReserveCapacity(props.size());
- for (const auto& property : props) {
- to_send.push_back(property);
- player_search->value->properties.insert(property.name, property);
- }
- probe::PlayerPropertiesChanged(GetSupplementable(), playerId, to_send);
+ const InspectorPlayerProperties& props) {
+ const auto& player = players_.find(playerId);
+ DCHECK_NE(player, players_.end());
+ for (const auto& property : props)
+ player->value->properties.insert(property.name, property);
+
+ Vector<InspectorPlayerProperty> vector =
+ Iter2Vector<InspectorPlayerProperty>(props);
+ probe::PlayerPropertiesChanged(GetSupplementable(), playerId, vector);
+}
+
+void MediaInspectorContextImpl::NotifyPlayerMessages(
+ WebString playerId,
+ const InspectorPlayerMessages& messages) {
+ const auto& player = players_.find(playerId);
+ DCHECK_NE(player, players_.end());
+ player->value->messages.AppendRange(messages.begin(), messages.end());
+
+ Vector<InspectorPlayerMessage> vector =
+ Iter2Vector<InspectorPlayerMessage>(messages);
+ probe::PlayerMessagesLogged(GetSupplementable(), playerId, vector);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/inspector/inspector_media_context_impl.h b/chromium/third_party/blink/renderer/core/inspector/inspector_media_context_impl.h
index 4b6c3eee2ac..04cb0d2c7cc 100644
--- a/chromium/third_party/blink/renderer/core/inspector/inspector_media_context_impl.h
+++ b/chromium/third_party/blink/renderer/core/inspector/inspector_media_context_impl.h
@@ -5,61 +5,55 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_INSPECTOR_INSPECTOR_MEDIA_CONTEXT_IMPL_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_INSPECTOR_INSPECTOR_MEDIA_CONTEXT_IMPL_H_
-#include <map>
-#include <memory>
-#include <string>
-#include <utility>
-#include <vector>
-
#include "third_party/blink/public/web/web_media_inspector.h"
#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/platform/supplementable.h"
+#include "third_party/blink/renderer/platform/wtf/hash_map.h"
+#include "third_party/blink/renderer/platform/wtf/text/string_hash.h"
namespace blink {
-class Document;
-class HTMLMediaElement;
+class LocalDOMWindow;
struct MediaPlayer final : public GarbageCollected<MediaPlayer> {
void Trace(Visitor*) {}
WebString player_id;
- InspectorPlayerEvents events;
+ Vector<InspectorPlayerError> errors;
+ Vector<InspectorPlayerEvent> events;
+ Vector<InspectorPlayerMessage> messages;
HashMap<String, InspectorPlayerProperty> properties;
};
class CORE_EXPORT MediaInspectorContextImpl final
: public GarbageCollected<MediaInspectorContextImpl>,
- public Supplement<LocalFrame>,
+ public Supplement<LocalDOMWindow>,
public MediaInspectorContext {
USING_GARBAGE_COLLECTED_MIXIN(MediaInspectorContextImpl);
public:
static const char kSupplementName[];
- static void ProvideToLocalFrame(LocalFrame&);
- // Different ways of getting the singleton instance of
- // MediaInspectorContextImpl depending on what things are easily in scope
- // caller side.
- static MediaInspectorContextImpl* FromLocalFrame(LocalFrame*);
- static MediaInspectorContextImpl* FromDocument(const Document&);
- static MediaInspectorContextImpl* FromHtmlMediaElement(
- const HTMLMediaElement&);
+ static MediaInspectorContextImpl* From(LocalDOMWindow&);
- explicit MediaInspectorContextImpl(LocalFrame&);
+ explicit MediaInspectorContextImpl(LocalDOMWindow&);
// MediaInspectorContext methods.
WebString CreatePlayer() override;
- void NotifyPlayerEvents(WebString, InspectorPlayerEvents) override;
- void SetPlayerProperties(WebString, InspectorPlayerProperties) override;
+ void NotifyPlayerErrors(WebString playerId,
+ const InspectorPlayerErrors&) override;
+ void NotifyPlayerEvents(WebString playerId,
+ const InspectorPlayerEvents&) override;
+ void NotifyPlayerMessages(WebString playerId,
+ const InspectorPlayerMessages&) override;
+ void SetPlayerProperties(WebString playerId,
+ const InspectorPlayerProperties&) override;
// GarbageCollected methods.
void Trace(Visitor*) override;
- Vector<WebString> GetAllPlayerIds();
- std::pair<Vector<InspectorPlayerProperty>, Vector<InspectorPlayerEvent>>
- GetPropertiesAndEvents(const WebString&);
+ Vector<WebString> AllPlayerIds();
+ const MediaPlayer& MediaPlayerFromId(const WebString&);
private:
HeapHashMap<String, Member<MediaPlayer>> players_;
diff --git a/chromium/third_party/blink/renderer/core/inspector/inspector_network_agent.cc b/chromium/third_party/blink/renderer/core/inspector/inspector_network_agent.cc
index 79887e2fc68..fd21ad09a6e 100644
--- a/chromium/third_party/blink/renderer/core/inspector/inspector_network_agent.cc
+++ b/chromium/third_party/blink/renderer/core/inspector/inspector_network_agent.cc
@@ -749,7 +749,12 @@ void InspectorNetworkAgent::DidBlockRequest(
const FetchInitiatorInfo& initiator_info,
ResourceRequestBlockedReason reason,
ResourceType resource_type) {
- uint64_t identifier = CreateUniqueIdentifier();
+ uint64_t identifier = request.InspectorId();
+ if (identifier == 0UL) {
+ NOTREACHED();
+ // Defensively create a valid identifier.
+ identifier = CreateUniqueIdentifier();
+ }
InspectorPageAgent::ResourceType type =
InspectorPageAgent::ToResourceType(resource_type);
@@ -783,6 +788,7 @@ void InspectorNetworkAgent::WillSendRequestInternal(
const ResourceResponse& redirect_response,
const FetchInitiatorInfo& initiator_info,
InspectorPageAgent::ResourceType type) {
+ CHECK_EQ(identifier, request.InspectorId());
String loader_id = IdentifiersFactory::LoaderId(loader);
String request_id = IdentifiersFactory::RequestId(loader, identifier);
NetworkResourcesData::ResourceData const* data =
@@ -880,6 +886,19 @@ void InspectorNetworkAgent::WillSendNavigationRequest(
InspectorPageAgent::kDocumentResource);
}
+// This method was pulled out of PrepareRequest(), because we want to be able
+// to create DevTools issues before the PrepareRequest() call. We need these
+// IDs to be set, to properly create a DevTools issue.
+void InspectorNetworkAgent::SetDevToolsIds(ResourceRequest& request) {
+ request.SetDevToolsToken(devtools_token_);
+
+ // The loader parameter is for generating a browser generated ID for a browser
+ // initiated request. We pass it null here because we are reporting a renderer
+ // generated ID for a renderer initiated request.
+ request.SetDevToolsId(IdentifiersFactory::RequestId(/* loader */ nullptr,
+ request.InspectorId()));
+}
+
void InspectorNetworkAgent::PrepareRequest(
DocumentLoader* loader,
ResourceRequest& request,
@@ -893,7 +912,7 @@ void InspectorNetworkAgent::PrepareRequest(
for (const WTF::String& key : extra_request_headers_.Keys()) {
const WTF::String& value = extra_request_headers_.Get(key);
AtomicString header_name = AtomicString(key);
- // When overriding referer, also override referrer policy
+ // When overriding referrer, also override referrer policy
// for this request to assure the request will be allowed.
// TODO: Should we store the referrer header somewhere other than
// |extra_request_headers_|?
@@ -908,8 +927,6 @@ void InspectorNetworkAgent::PrepareRequest(
request.SetReportRawHeaders(true);
- request.SetDevToolsToken(devtools_token_);
-
if (cache_disabled_.Get()) {
if (LoadsFromCacheOnly(request) &&
request.GetRequestContext() != mojom::RequestContextType::INTERNAL) {
@@ -921,12 +938,6 @@ void InspectorNetworkAgent::PrepareRequest(
}
if (bypass_service_worker_.Get())
request.SetSkipServiceWorker(true);
-
- // The loader parameter is for generating a browser generated ID for a browser
- // initiated request. We pass it null here because we are reporting a renderer
- // generated ID for a renderer initiated request.
- request.SetDevToolsId(IdentifiersFactory::RequestId(/* loader */ nullptr,
- request.InspectorId()));
}
void InspectorNetworkAgent::WillSendRequest(
@@ -1195,31 +1206,48 @@ InspectorNetworkAgent::BuildInitiatorObject(
Document* document,
const FetchInitiatorInfo& initiator_info,
int max_async_depth) {
- if (!initiator_info.imported_module_referrer.IsEmpty()) {
+ if (initiator_info.is_imported_module && !initiator_info.referrer.IsEmpty()) {
std::unique_ptr<protocol::Network::Initiator> initiator_object =
protocol::Network::Initiator::create()
.setType(protocol::Network::Initiator::TypeEnum::Script)
.build();
- initiator_object->setUrl(initiator_info.imported_module_referrer);
+ initiator_object->setUrl(initiator_info.referrer);
initiator_object->setLineNumber(
initiator_info.position.line_.ZeroBasedInt());
return initiator_object;
}
- std::unique_ptr<v8_inspector::protocol::Runtime::API::StackTrace>
- current_stack_trace =
- SourceLocation::Capture(document ? document->GetExecutionContext()
- : nullptr)
- ->BuildInspectorObject(max_async_depth);
- if (current_stack_trace) {
+ bool was_requested_by_stylesheet =
+ initiator_info.name == fetch_initiator_type_names::kCSS ||
+ initiator_info.name == fetch_initiator_type_names::kUacss;
+ if (was_requested_by_stylesheet && !initiator_info.referrer.IsEmpty()) {
std::unique_ptr<protocol::Network::Initiator> initiator_object =
protocol::Network::Initiator::create()
- .setType(protocol::Network::Initiator::TypeEnum::Script)
+ .setType(protocol::Network::Initiator::TypeEnum::Parser)
.build();
- initiator_object->setStack(std::move(current_stack_trace));
+ initiator_object->setUrl(initiator_info.referrer);
return initiator_object;
}
+ // We skip stack checking for stylesheet-initiated requests as it may
+ // represent the cause of a style recalculation rather than the actual
+ // resources themselves. See crbug.com/918196.
+ if (!was_requested_by_stylesheet) {
+ std::unique_ptr<v8_inspector::protocol::Runtime::API::StackTrace>
+ current_stack_trace =
+ SourceLocation::Capture(document ? document->GetExecutionContext()
+ : nullptr)
+ ->BuildInspectorObject(max_async_depth);
+ if (current_stack_trace) {
+ std::unique_ptr<protocol::Network::Initiator> initiator_object =
+ protocol::Network::Initiator::create()
+ .setType(protocol::Network::Initiator::TypeEnum::Script)
+ .build();
+ initiator_object->setStack(std::move(current_stack_trace));
+ return initiator_object;
+ }
+ }
+
while (document && !document->GetScriptableDocumentParser())
document = document->LocalOwner() ? document->LocalOwner()->ownerDocument()
: nullptr;
diff --git a/chromium/third_party/blink/renderer/core/inspector/inspector_network_agent.h b/chromium/third_party/blink/renderer/core/inspector/inspector_network_agent.h
index 9217ce02aae..e6c46fe40a8 100644
--- a/chromium/third_party/blink/renderer/core/inspector/inspector_network_agent.h
+++ b/chromium/third_party/blink/renderer/core/inspector/inspector_network_agent.h
@@ -192,6 +192,7 @@ class CORE_EXPORT InspectorNetworkAgent final
const char* payload,
size_t payload_length);
void DidReceiveWebSocketMessageError(uint64_t identifier, const String&);
+ void SetDevToolsIds(ResourceRequest& request);
// Called from frontend
protocol::Response enable(Maybe<int> total_buffer_size,
diff --git a/chromium/third_party/blink/renderer/core/inspector/inspector_overlay_agent.cc b/chromium/third_party/blink/renderer/core/inspector/inspector_overlay_agent.cc
index ab44f6ddbd3..ffe39fd95a3 100644
--- a/chromium/third_party/blink/renderer/core/inspector/inspector_overlay_agent.cc
+++ b/chromium/third_party/blink/renderer/core/inspector/inspector_overlay_agent.cc
@@ -126,7 +126,7 @@ int InspectTool::GetDataResourceId() {
bool InspectTool::HandleInputEvent(LocalFrameView* frame_view,
const WebInputEvent& input_event,
bool* swallow_next_mouse_up) {
- if (input_event.GetType() == WebInputEvent::kGestureTap) {
+ if (input_event.GetType() == WebInputEvent::Type::kGestureTap) {
// We only have a use for gesture tap.
WebGestureEvent transformed_event = TransformWebGestureEvent(
frame_view, static_cast<const WebGestureEvent&>(input_event));
@@ -155,13 +155,13 @@ bool InspectTool::HandleInputEvent(LocalFrameView* frame_view,
bool InspectTool::HandleMouseEvent(const WebMouseEvent& mouse_event,
bool* swallow_next_mouse_up) {
- if (mouse_event.GetType() == WebInputEvent::kMouseMove)
+ if (mouse_event.GetType() == WebInputEvent::Type::kMouseMove)
return HandleMouseMove(mouse_event);
- if (mouse_event.GetType() == WebInputEvent::kMouseDown)
+ if (mouse_event.GetType() == WebInputEvent::Type::kMouseDown)
return HandleMouseDown(mouse_event, swallow_next_mouse_up);
- if (mouse_event.GetType() == WebInputEvent::kMouseUp)
+ if (mouse_event.GetType() == WebInputEvent::Type::kMouseUp)
return HandleMouseUp(mouse_event);
return false;
@@ -196,6 +196,10 @@ bool InspectTool::ForwardEventsToOverlay() {
return true;
}
+bool InspectTool::HideOnMouseMove() {
+ return false;
+}
+
bool InspectTool::HideOnHideHighlight() {
return false;
}
@@ -204,6 +208,34 @@ void InspectTool::Trace(Visitor* visitor) {
visitor->Trace(overlay_);
}
+// Hinge -----------------------------------------------------------------------
+
+Hinge::Hinge(FloatQuad quad,
+ Color content_color,
+ Color outline_color,
+ InspectorOverlayAgent* overlay)
+ : quad_(quad),
+ content_color_(content_color),
+ outline_color_(outline_color),
+ overlay_(overlay) {}
+
+// static
+int Hinge::GetDataResourceId() {
+ // TODO (soxia): In the future, we should make the hinge working properly
+ // with tools using different resources.
+ return IDR_INSPECT_TOOL_HIGHLIGHT_HTML;
+}
+
+void Hinge::Trace(Visitor* visitor) {
+ visitor->Trace(overlay_);
+}
+
+void Hinge::Draw(float scale) {
+ InspectorHighlight highlight(scale);
+ highlight.AppendQuad(quad_, content_color_, outline_color_);
+ overlay_->EvaluateInOverlay("drawHighlight", highlight.AsProtocolValue());
+}
+
// InspectorOverlayAgent -------------------------------------------------------
class InspectorOverlayAgent::InspectorPageOverlayDelegate final
@@ -226,7 +258,7 @@ class InspectorOverlayAgent::InspectorPageOverlayDelegate final
void PaintFrameOverlay(const FrameOverlay& frame_overlay,
GraphicsContext& graphics_context,
const IntSize&) const override {
- if (!overlay_->inspect_tool_)
+ if (!overlay_->IsVisible())
return;
overlay_->PaintOverlayPage();
@@ -329,7 +361,6 @@ InspectorOverlayAgent::InspectorOverlayAgent(
v8_session_(v8_session),
dom_agent_(dom_agent),
swallow_next_mouse_up_(false),
- swallow_next_escape_up_(false),
backend_node_id_to_inspect_(0),
enabled_(&agent_state_, false),
show_ad_highlights_(&agent_state_, false),
@@ -356,6 +387,7 @@ void InspectorOverlayAgent::Trace(Visitor* visitor) {
visitor->Trace(overlay_host_);
visitor->Trace(dom_agent_);
visitor->Trace(inspect_tool_);
+ visitor->Trace(hinge_);
InspectorBaseAgent::Trace(visitor);
}
@@ -592,6 +624,48 @@ Response InspectorOverlayAgent::highlightQuad(
return Response::Success();
}
+Response InspectorOverlayAgent::setShowHinge(
+ protocol::Maybe<protocol::Overlay::HingeConfig> tool_config) {
+ // Hide the hinge when called without a configuration.
+ if (!tool_config.isJust()) {
+ hinge_ = nullptr;
+ if (!inspect_tool_)
+ DisableFrameOverlay();
+ ScheduleUpdate();
+ return Response::Success();
+ }
+
+ // Create a hinge
+ protocol::Overlay::HingeConfig* config = tool_config.fromJust();
+ protocol::DOM::Rect* rect = config->getRect();
+ int x = rect->getX();
+ int y = rect->getY();
+ int width = rect->getWidth();
+ int height = rect->getHeight();
+ if (x < 0 || y < 0 || width < 0 || height < 0)
+ return Response::InvalidParams("Invalid hinge rectangle.");
+
+ // Use default color if a content color is not provided.
+ Color content_color =
+ config->hasContentColor()
+ ? InspectorDOMAgent::ParseColor(config->getContentColor(nullptr))
+ : Color(38, 38, 38);
+ // outlineColor uses a kTransparent default from ParseColor if not provided.
+ Color outline_color =
+ InspectorDOMAgent::ParseColor(config->getOutlineColor(nullptr));
+
+ DCHECK(frame_impl_->GetFrameView() && GetFrame());
+
+ LoadFrameForTool(Hinge::GetDataResourceId());
+ EnsureEnableFrameOverlay();
+ FloatQuad quad(FloatRect(x, y, width, height));
+ hinge_ =
+ MakeGarbageCollected<Hinge>(quad, content_color, outline_color, this);
+ ScheduleUpdate();
+
+ return Response::Success();
+}
+
Response InspectorOverlayAgent::highlightNode(
std::unique_ptr<protocol::Overlay::HighlightConfig>
highlight_inspector_object,
@@ -645,6 +719,7 @@ Response InspectorOverlayAgent::highlightFrame(
Response InspectorOverlayAgent::hideHighlight() {
if (inspect_tool_ && inspect_tool_->HideOnHideHighlight())
PickTheRightTool();
+
return Response::Success();
}
@@ -652,6 +727,7 @@ Response InspectorOverlayAgent::getHighlightObjectForTest(
int node_id,
Maybe<bool> include_distance,
Maybe<bool> include_style,
+ Maybe<String> colorFormat,
std::unique_ptr<protocol::DictionaryValue>* result) {
Node* node = nullptr;
Response response = dom_agent_->AssertNode(node_id, node);
@@ -669,6 +745,18 @@ Response InspectorOverlayAgent::getHighlightObjectForTest(
InspectorHighlightConfig config = InspectorHighlight::DefaultConfig();
config.show_styles = include_style.fromMaybe(false);
+
+ String format = colorFormat.fromMaybe("hex");
+
+ namespace ColorFormatEnum = protocol::Overlay::ColorFormatEnum;
+ if (format == ColorFormatEnum::Hsl) {
+ config.color_format = ColorFormat::HSL;
+ } else if (format == ColorFormatEnum::Rgb) {
+ config.color_format = ColorFormat::RGB;
+ } else {
+ config.color_format = ColorFormat::HEX;
+ }
+
InspectorHighlight highlight(node, config, InspectorHighlightContrastInfo(),
true /* append_element_info */,
include_distance.fromMaybe(false),
@@ -711,22 +799,12 @@ void InspectorOverlayAgent::DispatchBufferedTouchEvents() {
WebInputEventResult InspectorOverlayAgent::HandleInputEvent(
const WebInputEvent& input_event) {
- if (input_event.GetType() == WebInputEvent::kMouseUp &&
+ if (input_event.GetType() == WebInputEvent::Type::kMouseUp &&
swallow_next_mouse_up_) {
swallow_next_mouse_up_ = false;
return WebInputEventResult::kHandledSuppressed;
}
- if (input_event.GetType() == WebInputEvent::kKeyUp &&
- swallow_next_escape_up_) {
- const auto& keyboard_event =
- static_cast<const WebKeyboardEvent&>(input_event);
- if (keyboard_event.windows_key_code == VKEY_ESCAPE) {
- swallow_next_escape_up_ = false;
- return WebInputEventResult::kHandledSuppressed;
- }
- }
-
LocalFrame* frame = GetFrame();
if (!frame || !frame->View() || !frame->ContentLayoutObject() ||
!inspect_tool_)
@@ -749,41 +827,41 @@ WebInputEventResult InspectorOverlayAgent::HandleInputEvent(
}
// Exit tool upon unhandled Esc.
- if (input_event.GetType() == WebInputEvent::kRawKeyDown) {
+ if (input_event.GetType() == WebInputEvent::Type::kRawKeyDown) {
const WebKeyboardEvent& keyboard_event =
static_cast<const WebKeyboardEvent&>(input_event);
if (keyboard_event.windows_key_code == VKEY_ESCAPE) {
GetFrontend()->inspectModeCanceled();
- swallow_next_escape_up_ = true;
- return WebInputEventResult::kHandledSuppressed;
+ return WebInputEventResult::kNotHandled;
}
}
+ if (input_event.GetType() == WebInputEvent::Type::kMouseMove &&
+ inspect_tool_->HideOnMouseMove()) {
+ PickTheRightTool();
+ }
+
return WebInputEventResult::kNotHandled;
}
WebInputEventResult InspectorOverlayAgent::HandleInputEventInOverlay(
const WebInputEvent& input_event) {
- if (input_event.GetType() == WebInputEvent::kGestureTap) {
+ if (input_event.GetType() == WebInputEvent::Type::kGestureTap) {
return OverlayMainFrame()->GetEventHandler().HandleGestureEvent(
static_cast<const WebGestureEvent&>(input_event));
}
if (WebInputEvent::IsMouseEventType(input_event.GetType())) {
WebMouseEvent mouse_event = static_cast<const WebMouseEvent&>(input_event);
- if (mouse_event.GetType() == WebInputEvent::kMouseMove) {
+ if (mouse_event.GetType() == WebInputEvent::Type::kMouseMove) {
return OverlayMainFrame()->GetEventHandler().HandleMouseMoveEvent(
- mouse_event,
- TransformWebMouseEventVector(frame_impl_->GetFrameView(),
- WebVector<const WebInputEvent*>()),
- TransformWebMouseEventVector(frame_impl_->GetFrameView(),
- WebVector<const WebInputEvent*>()));
+ mouse_event, {}, {});
}
- if (mouse_event.GetType() == WebInputEvent::kMouseDown) {
+ if (mouse_event.GetType() == WebInputEvent::Type::kMouseDown) {
return OverlayMainFrame()->GetEventHandler().HandleMousePressEvent(
mouse_event);
}
- if (mouse_event.GetType() == WebInputEvent::kMouseUp) {
+ if (mouse_event.GetType() == WebInputEvent::Type::kMouseUp) {
return OverlayMainFrame()->GetEventHandler().HandleMouseReleaseEvent(
mouse_event);
}
@@ -801,7 +879,7 @@ WebInputEventResult InspectorOverlayAgent::HandleInputEventInOverlay(
static_cast<const WebKeyboardEvent&>(input_event));
}
- if (input_event.GetType() == WebInputEvent::kMouseWheel) {
+ if (input_event.GetType() == WebInputEvent::Type::kMouseWheel) {
return OverlayMainFrame()->GetEventHandler().HandleWheelEvent(
static_cast<const WebMouseWheelEvent&>(input_event));
}
@@ -810,7 +888,7 @@ WebInputEventResult InspectorOverlayAgent::HandleInputEventInOverlay(
}
void InspectorOverlayAgent::ScheduleUpdate() {
- if (inspect_tool_) {
+ if (IsVisible()) {
GetFrame()->GetPage()->GetChromeClient().ScheduleAnimation(
GetFrame()->View());
}
@@ -841,8 +919,10 @@ void InspectorOverlayAgent::PaintOverlayPage() {
Reset(viewport_size);
- DCHECK(inspect_tool_);
- inspect_tool_->Draw(WindowToViewportScale());
+ if (inspect_tool_)
+ inspect_tool_->Draw(WindowToViewportScale());
+ if (hinge_)
+ hinge_->Draw(WindowToViewportScale());
OverlayMainFrame()->View()->UpdateAllLifecyclePhases(
DocumentUpdateReason::kInspector);
@@ -865,10 +945,20 @@ float InspectorOverlayAgent::WindowToViewportScale() const {
1.0f);
}
-void InspectorOverlayAgent::EnsureOverlayPageCreated() {
- if (overlay_page_)
+void InspectorOverlayAgent::LoadFrameForTool(int data_resource_id) {
+ if (frame_resource_name_ == data_resource_id)
return;
+ frame_resource_name_ = data_resource_id;
+
+ if (overlay_page_) {
+ overlay_page_->WillBeDestroyed();
+ overlay_page_.Clear();
+ overlay_chrome_client_.Clear();
+ overlay_host_->ClearDelegate();
+ overlay_host_.Clear();
+ }
+
ScriptForbiddenScope::AllowUserAgentScript allow_script;
Page::PageClients page_clients;
@@ -905,23 +995,8 @@ void InspectorOverlayAgent::EnsureOverlayPageCreated() {
DEFINE_STATIC_LOCAL(Persistent<LocalFrameClient>, dummy_local_frame_client,
(MakeGarbageCollected<EmptyLocalFrameClient>()));
auto* frame = MakeGarbageCollected<LocalFrame>(
- dummy_local_frame_client, *overlay_page_, nullptr, nullptr, nullptr);
- frame->SetView(MakeGarbageCollected<LocalFrameView>(*frame));
- frame->Init();
- frame->View()->SetCanHaveScrollbars(false);
- frame->View()->SetBaseBackgroundColor(Color::kTransparent);
-}
-
-void InspectorOverlayAgent::LoadFrameForTool() {
- if (frame_resource_name_ == inspect_tool_->GetDataResourceId())
- return;
-
- frame_resource_name_ = inspect_tool_->GetDataResourceId();
-
- DEFINE_STATIC_LOCAL(Persistent<LocalFrameClient>, dummy_local_frame_client,
- (MakeGarbageCollected<EmptyLocalFrameClient>()));
- auto* frame = MakeGarbageCollected<LocalFrame>(
- dummy_local_frame_client, *overlay_page_, nullptr, nullptr, nullptr);
+ dummy_local_frame_client, *overlay_page_, nullptr,
+ base::UnguessableToken::Create(), nullptr, nullptr);
frame->SetView(MakeGarbageCollected<LocalFrameView>(*frame));
frame->Init();
frame->View()->SetCanHaveScrollbars(false);
@@ -1161,9 +1236,31 @@ void InspectorOverlayAgent::PickTheRightTool() {
inspect_tool = MakeGarbageCollected<PausedInDebuggerTool>(
v8_session_, paused_in_debugger_message_.Get());
}
+
SetInspectTool(inspect_tool);
}
+void InspectorOverlayAgent::DisableFrameOverlay() {
+ if (IsVisible() || !frame_overlay_)
+ return;
+
+ frame_overlay_.reset();
+ auto& client = GetFrame()->GetPage()->GetChromeClient();
+ client.SetCursorOverridden(false);
+ client.SetCursor(PointerCursor(), GetFrame());
+
+ if (auto* frame_view = frame_impl_->GetFrameView())
+ frame_view->SetPaintArtifactCompositorNeedsUpdate();
+}
+
+void InspectorOverlayAgent::EnsureEnableFrameOverlay() {
+ if (frame_overlay_)
+ return;
+
+ frame_overlay_ = std::make_unique<FrameOverlay>(
+ GetFrame(), std::make_unique<InspectorPageOverlayDelegate>(*this));
+}
+
void InspectorOverlayAgent::SetInspectTool(InspectTool* inspect_tool) {
LocalFrameView* view = frame_impl_->GetFrameView();
LocalFrame* frame = GetFrame();
@@ -1172,22 +1269,16 @@ void InspectorOverlayAgent::SetInspectTool(InspectTool* inspect_tool) {
if (inspect_tool_)
inspect_tool_->Dispose();
- inspect_tool_ = inspect_tool;
- if (inspect_tool_) {
- EnsureOverlayPageCreated();
- LoadFrameForTool();
- if (!frame_overlay_) {
- frame_overlay_ = std::make_unique<FrameOverlay>(
- GetFrame(), std::make_unique<InspectorPageOverlayDelegate>(*this));
- }
- inspect_tool_->Init(this, GetFrontend());
- } else if (frame_overlay_) {
- frame_overlay_.reset();
- auto& client = GetFrame()->GetPage()->GetChromeClient();
- client.SetCursorOverridden(false);
- client.SetCursor(PointerCursor(), GetFrame());
- if (auto* frame_view = frame_impl_->GetFrameView())
- frame_view->SetPaintArtifactCompositorNeedsUpdate();
+
+ if (inspect_tool) {
+ inspect_tool_ = inspect_tool;
+ LoadFrameForTool(inspect_tool->GetDataResourceId());
+ EnsureEnableFrameOverlay();
+ inspect_tool->Init(this, GetFrontend());
+ } else {
+ inspect_tool_ = nullptr;
+ if (!hinge_)
+ DisableFrameOverlay();
}
ScheduleUpdate();
}
@@ -1201,11 +1292,49 @@ Response InspectorOverlayAgent::HighlightConfigFromInspectorObject(
}
protocol::Overlay::HighlightConfig* config =
highlight_inspector_object.fromJust();
+
+ namespace ColorFormatEnum = protocol::Overlay::ColorFormatEnum;
+
+ String format = config->getColorFormat("hex");
+
+ if (format != ColorFormatEnum::Rgb && format != ColorFormatEnum::Hex &&
+ format != ColorFormatEnum::Hsl) {
+ return Response::InvalidParams("Unknown color format");
+ }
+
*out_config = InspectorOverlayAgent::ToHighlightConfig(config);
return Response::Success();
}
// static
+std::unique_ptr<InspectorGridHighlightConfig>
+InspectorOverlayAgent::ToGridHighlightConfig(
+ protocol::Overlay::GridHighlightConfig* config) {
+ if (!config) {
+ return nullptr;
+ }
+ std::unique_ptr<InspectorGridHighlightConfig> highlight_config =
+ std::make_unique<InspectorGridHighlightConfig>();
+ highlight_config->show_grid_extension_lines =
+ config->getShowGridExtensionLines(false);
+ highlight_config->grid_border_dash = config->getGridBorderDash(false);
+ highlight_config->cell_border_dash = config->getCellBorderDash(false);
+ highlight_config->grid_color =
+ InspectorDOMAgent::ParseColor(config->getGridBorderColor(nullptr));
+ highlight_config->cell_color =
+ InspectorDOMAgent::ParseColor(config->getCellBorderColor(nullptr));
+ highlight_config->row_gap_color =
+ InspectorDOMAgent::ParseColor(config->getRowGapColor(nullptr));
+ highlight_config->column_gap_color =
+ InspectorDOMAgent::ParseColor(config->getColumnGapColor(nullptr));
+ highlight_config->row_hatch_color =
+ InspectorDOMAgent::ParseColor(config->getRowHatchColor(nullptr));
+ highlight_config->column_hatch_color =
+ InspectorDOMAgent::ParseColor(config->getColumnHatchColor(nullptr));
+ return highlight_config;
+}
+
+// static
std::unique_ptr<InspectorHighlightConfig>
InspectorOverlayAgent::ToHighlightConfig(
protocol::Overlay::HighlightConfig* config) {
@@ -1231,6 +1360,22 @@ InspectorOverlayAgent::ToHighlightConfig(
InspectorDOMAgent::ParseColor(config->getShapeMarginColor(nullptr));
highlight_config->css_grid =
InspectorDOMAgent::ParseColor(config->getCssGridColor(nullptr));
+
+ namespace ColorFormatEnum = protocol::Overlay::ColorFormatEnum;
+
+ String format = config->getColorFormat("hex");
+
+ if (format == ColorFormatEnum::Hsl) {
+ highlight_config->color_format = ColorFormat::HSL;
+ } else if (format == ColorFormatEnum::Rgb) {
+ highlight_config->color_format = ColorFormat::RGB;
+ } else {
+ highlight_config->color_format = ColorFormat::HEX;
+ }
+
+ highlight_config->grid_highlight_config =
+ InspectorOverlayAgent::ToGridHighlightConfig(
+ config->getGridHighlightConfig(nullptr));
return highlight_config;
}
diff --git a/chromium/third_party/blink/renderer/core/inspector/inspector_overlay_agent.h b/chromium/third_party/blink/renderer/core/inspector/inspector_overlay_agent.h
index a81f6463f17..4a2b9d455c9 100644
--- a/chromium/third_party/blink/renderer/core/inspector/inspector_overlay_agent.h
+++ b/chromium/third_party/blink/renderer/core/inspector/inspector_overlay_agent.h
@@ -75,6 +75,7 @@ using OverlayFrontend = protocol::Overlay::Metainfo::FrontendClass;
class CORE_EXPORT InspectTool : public GarbageCollected<InspectTool> {
public:
virtual ~InspectTool() = default;
+
void Init(InspectorOverlayAgent* overlay, OverlayFrontend* frontend);
virtual int GetDataResourceId();
virtual bool HandleInputEvent(LocalFrameView* frame_view,
@@ -95,19 +96,42 @@ class CORE_EXPORT InspectTool : public GarbageCollected<InspectTool> {
virtual void Trace(Visitor* visitor);
virtual void Dispose() {}
virtual bool HideOnHideHighlight();
+ virtual bool HideOnMouseMove();
protected:
+ InspectTool() = default;
virtual void DoInit() {}
Member<InspectorOverlayAgent> overlay_;
OverlayFrontend* frontend_ = nullptr;
};
+class CORE_EXPORT Hinge final : public GarbageCollected<Hinge> {
+ public:
+ Hinge(FloatQuad quad,
+ Color color,
+ Color outline_color,
+ InspectorOverlayAgent* overlay);
+ ~Hinge() = default;
+ static int GetDataResourceId();
+ void Draw(float scale);
+ void Trace(Visitor* visitor);
+
+ private:
+ FloatQuad quad_;
+ Color content_color_;
+ Color outline_color_;
+ Member<InspectorOverlayAgent> overlay_;
+ DISALLOW_COPY_AND_ASSIGN(Hinge);
+};
+
class CORE_EXPORT InspectorOverlayAgent final
: public InspectorBaseAgent<protocol::Overlay::Metainfo>,
public InspectorOverlayHost::Delegate {
USING_GARBAGE_COLLECTED_MIXIN(InspectorOverlayAgent);
public:
+ static std::unique_ptr<InspectorGridHighlightConfig> ToGridHighlightConfig(
+ protocol::Overlay::GridHighlightConfig*);
static std::unique_ptr<InspectorHighlightConfig> ToHighlightConfig(
protocol::Overlay::HighlightConfig*);
InspectorOverlayAgent(WebLocalFrameImpl*,
@@ -159,7 +183,10 @@ class CORE_EXPORT InspectorOverlayAgent final
int node_id,
protocol::Maybe<bool> include_distance,
protocol::Maybe<bool> include_style,
+ protocol::Maybe<String> color_format,
std::unique_ptr<protocol::DictionaryValue>* highlight) override;
+ protocol::Response setShowHinge(
+ protocol::Maybe<protocol::Overlay::HingeConfig> hinge_config) override;
// InspectorBaseAgent overrides.
void Restore() override;
@@ -194,7 +221,6 @@ class CORE_EXPORT InspectorOverlayAgent final
bool IsEmpty();
- void EnsureOverlayPageCreated();
LocalFrame* OverlayMainFrame();
void Reset(const IntSize& viewport_size);
void OnResizeTimer(TimerBase*);
@@ -202,17 +228,19 @@ class CORE_EXPORT InspectorOverlayAgent final
protocol::Response CompositingEnabled();
+ bool IsVisible() const { return inspect_tool_ || hinge_; }
bool InSomeInspectMode();
-
void SetNeedsUnbufferedInput(bool unbuffered);
void PickTheRightTool();
+ // Set or clear a mode tool, or add a highlight tool
void SetInspectTool(InspectTool* inspect_tool);
- void LoadFrameForTool();
+ void LoadFrameForTool(int data_resource_id);
+ void EnsureEnableFrameOverlay();
+ void DisableFrameOverlay();
protocol::Response HighlightConfigFromInspectorObject(
protocol::Maybe<protocol::Overlay::HighlightConfig>
highlight_inspector_object,
std::unique_ptr<InspectorHighlightConfig>*);
-
Member<WebLocalFrameImpl> frame_impl_;
Member<InspectedFrames> inspected_frames_;
Member<Page> overlay_page_;
@@ -226,8 +254,8 @@ class CORE_EXPORT InspectorOverlayAgent final
Member<InspectorDOMAgent> dom_agent_;
std::unique_ptr<FrameOverlay> frame_overlay_;
Member<InspectTool> inspect_tool_;
+ Member<Hinge> hinge_;
bool swallow_next_mouse_up_;
- bool swallow_next_escape_up_;
DOMNodeId backend_node_id_to_inspect_;
InspectorAgentState::Boolean enabled_;
InspectorAgentState::Boolean show_ad_highlights_;
diff --git a/chromium/third_party/blink/renderer/core/inspector/inspector_page_agent.cc b/chromium/third_party/blink/renderer/core/inspector/inspector_page_agent.cc
index 1ff765e6e0e..4f79e404321 100644
--- a/chromium/third_party/blink/renderer/core/inspector/inspector_page_agent.cc
+++ b/chromium/third_party/blink/renderer/core/inspector/inspector_page_agent.cc
@@ -116,6 +116,25 @@ String ClientNavigationReasonToProtocol(ClientNavigationReason reason) {
return ReasonEnum::Reload;
}
+String NavigationPolicyToProtocol(NavigationPolicy policy) {
+ namespace DispositionEnum = protocol::Page::ClientNavigationDispositionEnum;
+ switch (policy) {
+ case kNavigationPolicyDownload:
+ return DispositionEnum::Download;
+ case kNavigationPolicyCurrentTab:
+ return DispositionEnum::CurrentTab;
+ case kNavigationPolicyNewBackgroundTab:
+ return DispositionEnum::NewTab;
+ case kNavigationPolicyNewForegroundTab:
+ return DispositionEnum::NewTab;
+ case kNavigationPolicyNewWindow:
+ return DispositionEnum::NewWindow;
+ case kNavigationPolicyNewPopup:
+ return DispositionEnum::NewWindow;
+ }
+ return DispositionEnum::CurrentTab;
+}
+
Resource* CachedResource(LocalFrame* frame,
const KURL& url,
InspectorResourceContentLoader* loader) {
@@ -944,13 +963,14 @@ void InspectorPageAgent::FrameStoppedLoading(LocalFrame* frame) {
GetFrontend()->flush();
}
-void InspectorPageAgent::FrameRequestedNavigation(
- Frame* target_frame,
- const KURL& url,
- ClientNavigationReason reason) {
+void InspectorPageAgent::FrameRequestedNavigation(Frame* target_frame,
+ const KURL& url,
+ ClientNavigationReason reason,
+ NavigationPolicy policy) {
GetFrontend()->frameRequestedNavigation(
IdentifiersFactory::FrameId(target_frame),
- ClientNavigationReasonToProtocol(reason), url.GetString());
+ ClientNavigationReasonToProtocol(reason), url.GetString(),
+ NavigationPolicyToProtocol(policy));
GetFrontend()->flush();
}
diff --git a/chromium/third_party/blink/renderer/core/inspector/inspector_page_agent.h b/chromium/third_party/blink/renderer/core/inspector/inspector_page_agent.h
index fa1e022ce6b..33272e49144 100644
--- a/chromium/third_party/blink/renderer/core/inspector/inspector_page_agent.h
+++ b/chromium/third_party/blink/renderer/core/inspector/inspector_page_agent.h
@@ -181,7 +181,8 @@ class CORE_EXPORT InspectorPageAgent final
void FrameStoppedLoading(LocalFrame*);
void FrameRequestedNavigation(Frame* target_frame,
const KURL&,
- ClientNavigationReason);
+ ClientNavigationReason,
+ NavigationPolicy);
void FrameScheduledNavigation(LocalFrame*,
const KURL&,
base::TimeDelta delay,
diff --git a/chromium/third_party/blink/renderer/core/inspector/inspector_resource_content_loader.cc b/chromium/third_party/blink/renderer/core/inspector/inspector_resource_content_loader.cc
index 1a72eca769a..10a6e6b3c17 100644
--- a/chromium/third_party/blink/renderer/core/inspector/inspector_resource_content_loader.cc
+++ b/chromium/third_party/blink/renderer/core/inspector/inspector_resource_content_loader.cc
@@ -98,10 +98,7 @@ void InspectorResourceContentLoader::Start() {
// context document for getting origin and ResourceFetcher to use the
// main Document's origin, while using the element document for
// CompleteURL() to use imported Documents' base URLs.
- if (!document->ContextDocument()) {
- continue;
- }
- fetcher = document->ContextDocument()->Fetcher();
+ fetcher = document->GetExecutionContext()->Fetcher();
}
if (!resource_request.Url().GetString().IsEmpty()) {
urls_to_fetch.insert(resource_request.Url().GetString());
diff --git a/chromium/third_party/blink/renderer/core/inspector/inspector_style_sheet.cc b/chromium/third_party/blink/renderer/core/inspector/inspector_style_sheet.cc
index 7769a1aa17f..ce12579c49d 100644
--- a/chromium/third_party/blink/renderer/core/inspector/inspector_style_sheet.cc
+++ b/chromium/third_party/blink/renderer/core/inspector/inspector_style_sheet.cc
@@ -997,7 +997,7 @@ String InspectorStyleSheet::FinalURL() {
bool InspectorStyleSheet::SetText(const String& text,
ExceptionState& exception_state) {
InnerSetText(text, true);
- page_style_sheet_->SetText(text, true /* allow_import_rules */, nullptr);
+ page_style_sheet_->SetText(text, CSSImportRules::kAllow);
OnStyleSheetTextChanged();
return true;
}
diff --git a/chromium/third_party/blink/renderer/core/inspector/legacy_dom_snapshot_agent.cc b/chromium/third_party/blink/renderer/core/inspector/legacy_dom_snapshot_agent.cc
index 8970aaf5070..e39da971aaf 100644
--- a/chromium/third_party/blink/renderer/core/inspector/legacy_dom_snapshot_agent.cc
+++ b/chromium/third_party/blink/renderer/core/inspector/legacy_dom_snapshot_agent.cc
@@ -27,6 +27,7 @@
#include "third_party/blink/renderer/core/html/html_link_element.h"
#include "third_party/blink/renderer/core/html/html_template_element.h"
#include "third_party/blink/renderer/core/input_type_names.h"
+#include "third_party/blink/renderer/core/inspector/dom_traversal_utils.h"
#include "third_party/blink/renderer/core/inspector/identifiers_factory.h"
#include "third_party/blink/renderer/core/inspector/inspector_dom_agent.h"
#include "third_party/blink/renderer/core/inspector/inspector_dom_debugger_agent.h"
@@ -303,16 +304,16 @@ LegacyDOMSnapshotAgent::VisitContainerChildren(
bool include_user_agent_shadow_tree) {
auto children = std::make_unique<protocol::Array<int>>();
- if (!InspectorDOMSnapshotAgent::HasChildren(*container,
- include_user_agent_shadow_tree))
+ if (!blink::dom_traversal_utils::HasChildren(*container,
+ include_user_agent_shadow_tree))
return nullptr;
- Node* child = InspectorDOMSnapshotAgent::FirstChild(
+ Node* child = blink::dom_traversal_utils::FirstChild(
*container, include_user_agent_shadow_tree);
while (child) {
children->emplace_back(VisitNode(child, include_event_listeners,
include_user_agent_shadow_tree));
- child = InspectorDOMSnapshotAgent::NextSibling(
+ child = blink::dom_traversal_utils::NextSibling(
*child, include_user_agent_shadow_tree);
}
diff --git a/chromium/third_party/blink/renderer/core/inspector/network_resources_data.cc b/chromium/third_party/blink/renderer/core/inspector/network_resources_data.cc
index d9753c22e96..fbbb16aa534 100644
--- a/chromium/third_party/blink/renderer/core/inspector/network_resources_data.cc
+++ b/chromium/third_party/blink/renderer/core/inspector/network_resources_data.cc
@@ -124,7 +124,7 @@ void NetworkResourcesData::ResourceData::SetResource(
}
void NetworkResourcesData::ResourceData::ProcessCustomWeakness(
- const WeakCallbackInfo& info) {
+ const LivenessBroker& info) {
if (!cached_resource_ || info.IsHeapObjectAlive(cached_resource_))
return;
diff --git a/chromium/third_party/blink/renderer/core/inspector/network_resources_data.h b/chromium/third_party/blink/renderer/core/inspector/network_resources_data.h
index 1368d3ad52e..2346a511a4f 100644
--- a/chromium/third_party/blink/renderer/core/inspector/network_resources_data.h
+++ b/chromium/third_party/blink/renderer/core/inspector/network_resources_data.h
@@ -167,7 +167,7 @@ class NetworkResourcesData final
uint64_t DataLength() const;
void AppendData(const char* data, size_t data_length);
size_t DecodeDataToContent();
- void ProcessCustomWeakness(const WeakCallbackInfo&);
+ void ProcessCustomWeakness(const LivenessBroker&);
Member<NetworkResourcesData> network_resources_data_;
String request_id_;
@@ -188,7 +188,10 @@ class NetworkResourcesData final
int64_t pending_encoded_data_length_;
scoped_refptr<SharedBuffer> buffer_;
+
+ // We use UntracedMember<> here to do custom weak processing.
UntracedMember<const Resource> cached_resource_;
+
scoped_refptr<BlobDataHandle> downloaded_file_blob_;
Vector<AtomicString> certificate_;
scoped_refptr<EncodedFormData> post_data_;
diff --git a/chromium/third_party/blink/renderer/core/inspector/thread_debugger.cc b/chromium/third_party/blink/renderer/core/inspector/thread_debugger.cc
index ba97400cb64..bcc4cf90adb 100644
--- a/chromium/third_party/blink/renderer/core/inspector/thread_debugger.cc
+++ b/chromium/third_party/blink/renderer/core/inspector/thread_debugger.cc
@@ -456,15 +456,15 @@ void ThreadDebugger::GetEventListenersCallback(
void ThreadDebugger::consoleTime(const v8_inspector::StringView& title) {
// TODO(dgozman): we can save on a copy here if trace macro would take a
// pointer with length.
- TRACE_EVENT_COPY_ASYNC_BEGIN0("blink.console",
- ToCoreString(title).Utf8().c_str(), this);
+ TRACE_EVENT_COPY_NESTABLE_ASYNC_BEGIN0(
+ "blink.console", ToCoreString(title).Utf8().c_str(), this);
}
void ThreadDebugger::consoleTimeEnd(const v8_inspector::StringView& title) {
// TODO(dgozman): we can save on a copy here if trace macro would take a
// pointer with length.
- TRACE_EVENT_COPY_ASYNC_END0("blink.console",
- ToCoreString(title).Utf8().c_str(), this);
+ TRACE_EVENT_COPY_NESTABLE_ASYNC_END0(
+ "blink.console", ToCoreString(title).Utf8().c_str(), this);
}
void ThreadDebugger::consoleTimeStamp(const v8_inspector::StringView& title) {
diff --git a/chromium/third_party/blink/renderer/core/inspector/worker_inspector_controller.cc b/chromium/third_party/blink/renderer/core/inspector/worker_inspector_controller.cc
index 27331049b52..e9e2fe1c23e 100644
--- a/chromium/third_party/blink/renderer/core/inspector/worker_inspector_controller.cc
+++ b/chromium/third_party/blink/renderer/core/inspector/worker_inspector_controller.cc
@@ -33,6 +33,7 @@
#include "base/single_thread_task_runner.h"
#include "third_party/blink/renderer/core/core_probe_sink.h"
#include "third_party/blink/renderer/core/inspector/devtools_session.h"
+#include "third_party/blink/renderer/core/inspector/inspector_audits_agent.h"
#include "third_party/blink/renderer/core/inspector/inspector_emulation_agent.h"
#include "third_party/blink/renderer/core/inspector/inspector_log_agent.h"
#include "third_party/blink/renderer/core/inspector/inspector_network_agent.h"
@@ -110,9 +111,12 @@ void WorkerInspectorController::AttachSession(DevToolsSession* session,
session->Append(MakeGarbageCollected<InspectorLogAgent>(
thread_->GetConsoleMessageStorage(), nullptr, session->V8Session()));
if (auto* scope = DynamicTo<WorkerGlobalScope>(thread_->GlobalScope())) {
- session->Append(MakeGarbageCollected<InspectorNetworkAgent>(
- inspected_frames_.Get(), scope, session->V8Session()));
+ auto* network_agent = MakeGarbageCollected<InspectorNetworkAgent>(
+ inspected_frames_.Get(), scope, session->V8Session());
+ session->Append(network_agent);
session->Append(MakeGarbageCollected<InspectorEmulationAgent>(nullptr));
+ session->Append(MakeGarbageCollected<InspectorAuditsAgent>(
+ network_agent, thread_->GetInspectorIssueStorage()));
}
++session_count_;
}
diff --git a/chromium/third_party/blink/renderer/core/intersection_observer/intersection_geometry.cc b/chromium/third_party/blink/renderer/core/intersection_observer/intersection_geometry.cc
index 586abe8f69a..eef6e1da665 100644
--- a/chromium/third_party/blink/renderer/core/intersection_observer/intersection_geometry.cc
+++ b/chromium/third_party/blink/renderer/core/intersection_observer/intersection_geometry.cc
@@ -480,11 +480,16 @@ bool IntersectionGeometry::ClipToRoot(const LayoutObject* root,
// done yet.
LocalFrame* local_root_frame = root->GetDocument().GetFrame();
IntRect clip_rect(local_root_frame->RemoteViewportIntersection());
- // Map clip_rect from the coordinate system of the local root frame to
- // the coordinate system of the remote main frame.
- clip_rect.MoveBy(IntPoint(local_root_frame->RemoteViewportOffset()));
- does_intersect &=
- intersection_rect.InclusiveIntersect(PhysicalRect(clip_rect));
+ if (clip_rect.IsEmpty()) {
+ intersection_rect = PhysicalRect();
+ does_intersect = false;
+ } else {
+ // Map clip_rect from the coordinate system of the local root frame to
+ // the coordinate system of the remote main frame.
+ clip_rect.MoveBy(IntPoint(local_root_frame->RemoteViewportOffset()));
+ does_intersect &=
+ intersection_rect.InclusiveIntersect(PhysicalRect(clip_rect));
+ }
}
}
diff --git a/chromium/third_party/blink/renderer/core/intersection_observer/intersection_observer.cc b/chromium/third_party/blink/renderer/core/intersection_observer/intersection_observer.cc
index c2a12af4581..ad5235457b6 100644
--- a/chromium/third_party/blink/renderer/core/intersection_observer/intersection_observer.cc
+++ b/chromium/third_party/blink/renderer/core/intersection_observer/intersection_observer.cc
@@ -293,7 +293,7 @@ IntersectionObserver::IntersectionObserver(
}
}
-void IntersectionObserver::ProcessCustomWeakness(const WeakCallbackInfo& info) {
+void IntersectionObserver::ProcessCustomWeakness(const LivenessBroker& info) {
// For explicit-root observers, if the root element disappears for any reason,
// any remaining obsevations must be dismantled.
if (root() && !info.IsHeapObjectAlive(root()))
@@ -314,10 +314,6 @@ void IntersectionObserver::observe(Element* target,
if (!target || root() == target)
return;
- LocalFrame* target_frame = target->GetDocument().GetFrame();
- if (!target_frame)
- return;
-
if (target->EnsureIntersectionObserverData().GetObservationFor(*this))
return;
@@ -335,7 +331,7 @@ void IntersectionObserver::observe(Element* target,
target->GetDocument()
.EnsureIntersectionObserverController()
.AddTrackedObservation(*observation);
- if (LocalFrameView* frame_view = target_frame->View()) {
+ if (LocalFrameView* frame_view = target->GetDocument().View()) {
// The IntersectionObsever spec requires that at least one observation
// be recorded after observe() is called, even if the frame is throttled.
frame_view->SetIntersectionObservationState(LocalFrameView::kRequired);
diff --git a/chromium/third_party/blink/renderer/core/intersection_observer/intersection_observer.h b/chromium/third_party/blink/renderer/core/intersection_observer/intersection_observer.h
index 5f6e44ff84e..f1747a98120 100644
--- a/chromium/third_party/blink/renderer/core/intersection_observer/intersection_observer.h
+++ b/chromium/third_party/blink/renderer/core/intersection_observer/intersection_observer.h
@@ -165,10 +165,13 @@ class CORE_EXPORT IntersectionObserver final
static void SetThrottleDelayEnabledForTesting(bool);
private:
- void ProcessCustomWeakness(const WeakCallbackInfo&);
+ void ProcessCustomWeakness(const LivenessBroker&);
const Member<IntersectionObserverDelegate> delegate_;
+
+ // We use UntracedMember<> here to do custom weak processing.
UntracedMember<Node> root_;
+
HeapLinkedHashSet<WeakMember<IntersectionObservation>> observations_;
Vector<float> thresholds_;
DOMHighResTimeStamp delay_;
diff --git a/chromium/third_party/blink/renderer/core/intersection_observer/intersection_observer_entry.idl b/chromium/third_party/blink/renderer/core/intersection_observer/intersection_observer_entry.idl
index ec82d8618d0..475284d1e29 100644
--- a/chromium/third_party/blink/renderer/core/intersection_observer/intersection_observer_entry.idl
+++ b/chromium/third_party/blink/renderer/core/intersection_observer/intersection_observer_entry.idl
@@ -4,7 +4,9 @@
// https://wicg.github.io/IntersectionObserver/#intersection-observer-entry
-interface IntersectionObserverEntry {
+[
+ Exposed=Window
+] interface IntersectionObserverEntry {
readonly attribute DOMHighResTimeStamp time;
// TODO(szager): |rootBounds| should not be nullable.
readonly attribute DOMRectReadOnly? rootBounds;
diff --git a/chromium/third_party/blink/renderer/core/intersection_observer/intersection_observer_test.cc b/chromium/third_party/blink/renderer/core/intersection_observer/intersection_observer_test.cc
index fd30925e0fa..0928877b684 100644
--- a/chromium/third_party/blink/renderer/core/intersection_observer/intersection_observer_test.cc
+++ b/chromium/third_party/blink/renderer/core/intersection_observer/intersection_observer_test.cc
@@ -580,9 +580,7 @@ TEST_F(IntersectionObserverTest, TrackedRootBookkeeping) {
// only thing keeping the observer alive.
test::RunPendingTasks();
observer_delegate->Clear();
- V8GCController::CollectAllGarbageForTesting(
- v8::Isolate::GetCurrent(),
- v8::EmbedderHeapTracer::EmbedderStackState::kEmpty);
+ ThreadState::Current()->CollectAllGarbageForTesting();
EXPECT_FALSE(root_data->IsEmpty());
EXPECT_FALSE(target_data->IsEmpty());
EXPECT_EQ(controller.GetTrackedObserverCountForTesting(), 1u);
@@ -598,9 +596,7 @@ TEST_F(IntersectionObserverTest, TrackedRootBookkeeping) {
// queued, so flush it out.
test::RunPendingTasks();
observer_delegate->Clear();
- V8GCController::CollectAllGarbageForTesting(
- v8::Isolate::GetCurrent(),
- v8::EmbedderHeapTracer::EmbedderStackState::kEmpty);
+ ThreadState::Current()->CollectAllGarbageForTesting();
Compositor().BeginFrame();
EXPECT_EQ(controller.GetTrackedObserverCountForTesting(), 0u);
EXPECT_EQ(controller.GetTrackedObservationCountForTesting(), 0u);
@@ -608,9 +604,7 @@ TEST_F(IntersectionObserverTest, TrackedRootBookkeeping) {
// Removing the last reference to the observer should allow it to be dropeed
// from the root's ElementIntersectionObserverData.
observer = nullptr;
- V8GCController::CollectAllGarbageForTesting(
- v8::Isolate::GetCurrent(),
- v8::EmbedderHeapTracer::EmbedderStackState::kEmpty);
+ ThreadState::Current()->CollectAllGarbageForTesting();
EXPECT_TRUE(root_data->IsEmpty());
target = GetDocument().getElementById("target2");
@@ -631,9 +625,7 @@ TEST_F(IntersectionObserverTest, TrackedRootBookkeeping) {
// Removing the target from the tree is not enough to disconnect the
// observation.
EXPECT_FALSE(target_data->IsEmpty());
- V8GCController::CollectAllGarbageForTesting(
- v8::Isolate::GetCurrent(),
- v8::EmbedderHeapTracer::EmbedderStackState::kEmpty);
+ ThreadState::Current()->CollectAllGarbageForTesting();
EXPECT_TRUE(target_data->IsEmpty());
EXPECT_EQ(controller.GetTrackedObserverCountForTesting(), 0u);
EXPECT_EQ(controller.GetTrackedObservationCountForTesting(), 0u);
diff --git a/chromium/third_party/blink/renderer/core/invisible_dom/BUILD.gn b/chromium/third_party/blink/renderer/core/invisible_dom/BUILD.gn
deleted file mode 100644
index 86acb9d76d3..00000000000
--- a/chromium/third_party/blink/renderer/core/invisible_dom/BUILD.gn
+++ /dev/null
@@ -1,14 +0,0 @@
-# Copyright 2018 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import("//third_party/blink/renderer/core/core.gni")
-
-blink_core_sources("invisible_dom") {
- sources = [
- "activate_invisible_event.cc",
- "activate_invisible_event.h",
- "invisible_dom.cc",
- "invisible_dom.h",
- ]
-}
diff --git a/chromium/third_party/blink/renderer/core/invisible_dom/OWNERS b/chromium/third_party/blink/renderer/core/invisible_dom/OWNERS
deleted file mode 100644
index 3d44e4e4af2..00000000000
--- a/chromium/third_party/blink/renderer/core/invisible_dom/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-rakina@chromium.org
-
-# TEAM: dom-dev@chromium.org
-# COMPONENT: Blink>DOM
diff --git a/chromium/third_party/blink/renderer/core/invisible_dom/activate_invisible_event.cc b/chromium/third_party/blink/renderer/core/invisible_dom/activate_invisible_event.cc
deleted file mode 100644
index 8450a0e09ee..00000000000
--- a/chromium/third_party/blink/renderer/core/invisible_dom/activate_invisible_event.cc
+++ /dev/null
@@ -1,29 +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/core/invisible_dom/activate_invisible_event.h"
-
-#include "third_party/blink/renderer/core/dom/element.h"
-#include "third_party/blink/renderer/core/dom/events/event_dispatcher.h"
-#include "third_party/blink/renderer/core/event_interface_names.h"
-
-namespace blink {
-
-const AtomicString& ActivateInvisibleEvent::InterfaceName() const {
- return event_interface_names::kActivateInvisibleEvent;
-}
-
-ActivateInvisibleEvent::ActivateInvisibleEvent(Element* activated_element)
- : Event(event_type_names::kActivateinvisible,
- Bubbles::kYes,
- Cancelable::kYes,
- ComposedMode::kScoped),
- activated_element_(activated_element) {}
-
-void ActivateInvisibleEvent::Trace(Visitor* visitor) {
- visitor->Trace(activated_element_);
- Event::Trace(visitor);
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/invisible_dom/activate_invisible_event.h b/chromium/third_party/blink/renderer/core/invisible_dom/activate_invisible_event.h
deleted file mode 100644
index baac9010eb7..00000000000
--- a/chromium/third_party/blink/renderer/core/invisible_dom/activate_invisible_event.h
+++ /dev/null
@@ -1,36 +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_CORE_INVISIBLE_DOM_ACTIVATE_INVISIBLE_EVENT_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_INVISIBLE_DOM_ACTIVATE_INVISIBLE_EVENT_H_
-
-#include "third_party/blink/renderer/core/dom/events/event.h"
-
-namespace blink {
-
-class Element;
-
-class ActivateInvisibleEvent : public Event {
- DEFINE_WRAPPERTYPEINFO();
-
- public:
- explicit ActivateInvisibleEvent(Element* activated_element);
-
- Element* activatedElement() const { return activated_element_.Get(); }
-
- void SetActivatedElement(Element* activated_element) {
- activated_element_ = activated_element;
- }
-
- const AtomicString& InterfaceName() const override;
-
- void Trace(Visitor*) override;
-
- private:
- Member<Element> activated_element_;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_CORE_INVISIBLE_DOM_ACTIVATE_INVISIBLE_EVENT_H_
diff --git a/chromium/third_party/blink/renderer/core/invisible_dom/activate_invisible_event.idl b/chromium/third_party/blink/renderer/core/invisible_dom/activate_invisible_event.idl
deleted file mode 100644
index 4ee6aaba60e..00000000000
--- a/chromium/third_party/blink/renderer/core/invisible_dom/activate_invisible_event.idl
+++ /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.
-
-// Explainer at https://goo.gl/mJUNB5
-
-[
- RuntimeEnabled=InvisibleDOM
-] interface ActivateInvisibleEvent : Event {
- readonly attribute Element? activatedElement;
-};
diff --git a/chromium/third_party/blink/renderer/core/invisible_dom/invisible_dom.cc b/chromium/third_party/blink/renderer/core/invisible_dom/invisible_dom.cc
deleted file mode 100644
index 2114664a489..00000000000
--- a/chromium/third_party/blink/renderer/core/invisible_dom/invisible_dom.cc
+++ /dev/null
@@ -1,63 +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/core/invisible_dom/invisible_dom.h"
-
-#include "third_party/blink/renderer/core/dom/element.h"
-#include "third_party/blink/renderer/core/dom/flat_tree_traversal.h"
-#include "third_party/blink/renderer/core/dom/node.h"
-
-namespace blink {
-bool InvisibleDOM::IsInsideInvisibleSubtree(const Node& node) {
- if (!RuntimeEnabledFeatures::InvisibleDOMEnabled())
- return false;
- if (!node.CanParticipateInFlatTree())
- return false;
- for (Node& ancestor : FlatTreeTraversal::InclusiveAncestorsOf(node)) {
- auto* element = DynamicTo<Element>(ancestor);
- if (element && element->HasInvisibleAttribute()) {
- return true;
- }
- }
- return false;
-}
-
-Element* InvisibleDOM::InvisibleRoot(const Node& node) {
- if (!RuntimeEnabledFeatures::InvisibleDOMEnabled())
- return nullptr;
- Element* root = nullptr;
- for (Node& ancestor : FlatTreeTraversal::InclusiveAncestorsOf(node)) {
- auto* element = DynamicTo<Element>(ancestor);
- if (element && element->HasInvisibleAttribute()) {
- root = element;
- }
- }
- return root;
-}
-
-bool InvisibleDOM::ActivateRangeIfNeeded(
- const EphemeralRangeInFlatTree& range) {
- if (!RuntimeEnabledFeatures::InvisibleDOMEnabled())
- return false;
- if (range.IsNull() || range.IsCollapsed())
- return false;
- HeapVector<Member<Element>> elements_to_activate;
- for (Node& node : range.Nodes()) {
- if (!InvisibleDOM::IsInsideInvisibleSubtree(node))
- continue;
- for (Node& ancestor_node : FlatTreeTraversal::AncestorsOf(node)) {
- auto* element = DynamicTo<Element>(ancestor_node);
- if (element) {
- elements_to_activate.push_back(element);
- break;
- }
- }
- }
- for (Element* element : elements_to_activate) {
- element->DispatchActivateInvisibleEventIfNeeded();
- }
- return !elements_to_activate.IsEmpty();
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/invisible_dom/invisible_dom.h b/chromium/third_party/blink/renderer/core/invisible_dom/invisible_dom.h
deleted file mode 100644
index ece89ccd185..00000000000
--- a/chromium/third_party/blink/renderer/core/invisible_dom/invisible_dom.h
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_INVISIBLE_DOM_INVISIBLE_DOM_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_INVISIBLE_DOM_INVISIBLE_DOM_H_
-
-#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/core/editing/ephemeral_range.h"
-#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
-
-namespace blink {
-
-class Node;
-class Element;
-
-class CORE_EXPORT InvisibleDOM {
- STATIC_ONLY(InvisibleDOM);
-
- public:
- static bool IsInsideInvisibleSubtree(const Node& node);
-
- // Highest inclusive ancestor that has the invisible attribute.
- // Will always return non-null value if IsInsideInvisibleSubtree() is true.
- static Element* InvisibleRoot(const Node&);
-
- // Activates all the nodes within |range|. Returns true if at least one
- // node gets activated.
- static bool ActivateRangeIfNeeded(const EphemeralRangeInFlatTree& range);
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_CORE_INVISIBLE_DOM_INVISIBLE_DOM_H_
diff --git a/chromium/third_party/blink/renderer/core/layout/BUILD.gn b/chromium/third_party/blink/renderer/core/layout/BUILD.gn
index cb2f84ebd46..0f7341938a0 100644
--- a/chromium/third_party/blink/renderer/core/layout/BUILD.gn
+++ b/chromium/third_party/blink/renderer/core/layout/BUILD.gn
@@ -308,6 +308,12 @@ blink_core_sources("layout") {
"ng/exclusions/ng_layout_opportunity.h",
"ng/exclusions/ng_line_layout_opportunity.h",
"ng/exclusions/ng_shape_exclusions.h",
+ "ng/flex/layout_ng_flexible_box.cc",
+ "ng/flex/layout_ng_flexible_box.h",
+ "ng/flex/ng_flex_child_iterator.cc",
+ "ng/flex/ng_flex_child_iterator.h",
+ "ng/flex/ng_flex_layout_algorithm.cc",
+ "ng/flex/ng_flex_layout_algorithm.h",
"ng/geometry/ng_bfc_offset.cc",
"ng/geometry/ng_bfc_offset.h",
"ng/geometry/ng_bfc_rect.h",
@@ -329,8 +335,6 @@ blink_core_sources("layout") {
"ng/inline/ng_caret_position.h",
"ng/inline/ng_caret_rect.cc",
"ng/inline/ng_caret_rect.h",
- "ng/inline/ng_dirty_lines.cc",
- "ng/inline/ng_dirty_lines.h",
"ng/inline/ng_fragment_item.cc",
"ng/inline/ng_fragment_item.h",
"ng/inline/ng_fragment_items.cc",
@@ -386,6 +390,7 @@ blink_core_sources("layout") {
"ng/inline/ng_text_fragment_builder.cc",
"ng/inline/ng_text_fragment_builder.h",
"ng/inline/ng_text_offset.h",
+ "ng/inline/ng_text_type.h",
"ng/layout_box_utils.cc",
"ng/layout_box_utils.h",
"ng/layout_ng_block_flow.cc",
@@ -394,16 +399,20 @@ blink_core_sources("layout") {
"ng/layout_ng_block_flow_mixin.h",
"ng/layout_ng_fieldset.cc",
"ng/layout_ng_fieldset.h",
- "ng/layout_ng_flexible_box.cc",
- "ng/layout_ng_flexible_box.h",
+ "ng/layout_ng_grid.cc",
+ "ng/layout_ng_grid.h",
"ng/layout_ng_mixin.cc",
"ng/layout_ng_mixin.h",
"ng/layout_ng_progress.cc",
"ng/layout_ng_progress.h",
- "ng/layout_ng_table_caption.cc",
- "ng/layout_ng_table_caption.h",
- "ng/layout_ng_table_cell.cc",
- "ng/layout_ng_table_cell.h",
+ "ng/layout_ng_ruby_as_block.cc",
+ "ng/layout_ng_ruby_as_block.h",
+ "ng/layout_ng_ruby_base.cc",
+ "ng/layout_ng_ruby_base.h",
+ "ng/layout_ng_ruby_run.cc",
+ "ng/layout_ng_ruby_run.h",
+ "ng/layout_ng_ruby_text.cc",
+ "ng/layout_ng_ruby_text.h",
"ng/legacy_layout_tree_walking.h",
"ng/list/layout_ng_inside_list_marker.cc",
"ng/list/layout_ng_inside_list_marker.h",
@@ -425,8 +434,12 @@ blink_core_sources("layout") {
"ng/mathml/ng_math_layout_utils.h",
"ng/mathml/ng_math_row_layout_algorithm.cc",
"ng/mathml/ng_math_row_layout_algorithm.h",
+ "ng/mathml/ng_math_scripts_layout_algorithm.cc",
+ "ng/mathml/ng_math_scripts_layout_algorithm.h",
"ng/mathml/ng_math_space_layout_algorithm.cc",
"ng/mathml/ng_math_space_layout_algorithm.h",
+ "ng/mathml/ng_math_under_over_layout_algorithm.cc",
+ "ng/mathml/ng_math_under_over_layout_algorithm.h",
"ng/ng_absolute_utils.cc",
"ng/ng_absolute_utils.h",
"ng/ng_block_break_token.cc",
@@ -457,10 +470,6 @@ blink_core_sources("layout") {
"ng/ng_early_break.h",
"ng/ng_fieldset_layout_algorithm.cc",
"ng/ng_fieldset_layout_algorithm.h",
- "ng/ng_flex_child_iterator.cc",
- "ng/ng_flex_child_iterator.h",
- "ng/ng_flex_layout_algorithm.cc",
- "ng/ng_flex_layout_algorithm.h",
"ng/ng_floats_utils.cc",
"ng/ng_floats_utils.h",
"ng/ng_fragment.h",
@@ -469,6 +478,8 @@ blink_core_sources("layout") {
"ng/ng_fragment_child_iterator.h",
"ng/ng_fragmentation_utils.cc",
"ng/ng_fragmentation_utils.h",
+ "ng/ng_grid_layout_algorithm.cc",
+ "ng/ng_grid_layout_algorithm.h",
"ng/ng_ink_overflow.cc",
"ng/ng_ink_overflow.h",
"ng/ng_layout_algorithm.h",
@@ -506,9 +517,23 @@ blink_core_sources("layout") {
"ng/ng_text_decoration_offset.h",
"ng/ng_unpositioned_float.h",
"ng/table/interface_casting.h",
+ "ng/table/layout_ng_table.cc",
+ "ng/table/layout_ng_table.h",
+ "ng/table/layout_ng_table_caption.cc",
+ "ng/table/layout_ng_table_caption.h",
+ "ng/table/layout_ng_table_cell.cc",
+ "ng/table/layout_ng_table_cell.h",
"ng/table/layout_ng_table_cell_interface.h",
+ "ng/table/layout_ng_table_cell_legacy.cc",
+ "ng/table/layout_ng_table_cell_legacy.h",
+ "ng/table/layout_ng_table_column.cc",
+ "ng/table/layout_ng_table_column.h",
"ng/table/layout_ng_table_interface.h",
+ "ng/table/layout_ng_table_row.cc",
+ "ng/table/layout_ng_table_row.h",
"ng/table/layout_ng_table_row_interface.h",
+ "ng/table/layout_ng_table_section.cc",
+ "ng/table/layout_ng_table_section.h",
"ng/table/layout_ng_table_section_interface.h",
"order_iterator.cc",
"order_iterator.h",
diff --git a/chromium/third_party/blink/renderer/core/layout/box_layout_extra_input.h b/chromium/third_party/blink/renderer/core/layout/box_layout_extra_input.h
index 02ee264bf07..0fd51ae4091 100644
--- a/chromium/third_party/blink/renderer/core/layout/box_layout_extra_input.h
+++ b/chromium/third_party/blink/renderer/core/layout/box_layout_extra_input.h
@@ -29,6 +29,10 @@ struct BoxLayoutExtraInput {
// one instead.
base::Optional<LayoutUnit> override_block_size;
+ // If the |override_block_size| should be treated as definite for the
+ // purposes of percent block-size resolution.
+ bool is_override_block_size_definite = true;
+
// Available inline size. https://drafts.csswg.org/css-sizing/#available
LayoutUnit available_inline_size;
diff --git a/chromium/third_party/blink/renderer/core/layout/flexible_box_algorithm.cc b/chromium/third_party/blink/renderer/core/layout/flexible_box_algorithm.cc
index ebc3d542dff..91792d6bfff 100644
--- a/chromium/third_party/blink/renderer/core/layout/flexible_box_algorithm.cc
+++ b/chromium/third_party/blink/renderer/core/layout/flexible_box_algorithm.cc
@@ -34,6 +34,7 @@
#include "third_party/blink/renderer/core/layout/layout_flexible_box.h"
#include "third_party/blink/renderer/core/layout/min_max_sizes.h"
#include "third_party/blink/renderer/core/layout/ng/ng_box_fragment.h"
+#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
namespace blink {
namespace {
@@ -480,7 +481,9 @@ void FlexLine::ComputeLineItemsPosition(LayoutUnit main_axis_start_offset,
LayoutUnit total_item_size;
for (size_t i = 0; i < line_items.size(); ++i)
total_item_size += line_items[i].FlexedMarginBoxSize();
- remaining_free_space = container_main_inner_size - total_item_size;
+ remaining_free_space =
+ container_main_inner_size - total_item_size -
+ (line_items.size() - 1) * algorithm->gap_between_items_;
const StyleContentAlignmentData justify_content =
FlexLayoutAlgorithm::ResolvedJustifyContent(*algorithm->Style());
@@ -562,7 +565,9 @@ void FlexLine::ComputeLineItemsPosition(LayoutUnit main_axis_start_offset,
LayoutUnit space_between =
FlexLayoutAlgorithm::ContentDistributionSpaceBetweenChildren(
available_free_space, justify_content, line_items.size());
- main_axis_offset += space_between;
+ main_axis_offset += space_between + algorithm->gap_between_items_;
+ // The gap is included in the intrinsic content block size, so don't add
+ // it to sum_justify_adjustments.
sum_justify_adjustments += space_between;
}
}
@@ -575,11 +580,71 @@ void FlexLine::ComputeLineItemsPosition(LayoutUnit main_axis_start_offset,
cross_axis_offset += max_child_cross_axis_extent;
}
+// static
+LayoutUnit FlexLayoutAlgorithm::GapBetweenItems(
+ const ComputedStyle& style,
+ LogicalSize percent_resolution_sizes) {
+ if (!RuntimeEnabledFeatures::FlexGapsEnabled())
+ return LayoutUnit();
+ DCHECK_GE(percent_resolution_sizes.inline_size, 0);
+ if (IsColumnFlow(style)) {
+ if (LIKELY(style.RowGap().IsNormal()))
+ return LayoutUnit();
+ return MinimumValueForLength(
+ style.RowGap().GetLength(),
+ percent_resolution_sizes.block_size.ClampNegativeToZero());
+ }
+ if (LIKELY(style.ColumnGap().IsNormal()))
+ return LayoutUnit();
+ return MinimumValueForLength(style.ColumnGap().GetLength(),
+ percent_resolution_sizes.inline_size);
+}
+
+// static
+LayoutUnit FlexLayoutAlgorithm::GapBetweenLines(
+ const ComputedStyle& style,
+ LogicalSize percent_resolution_sizes) {
+ if (!RuntimeEnabledFeatures::FlexGapsEnabled())
+ return LayoutUnit();
+ DCHECK_GE(percent_resolution_sizes.inline_size, 0);
+ if (!IsColumnFlow(style)) {
+ if (LIKELY(style.RowGap().IsNormal()))
+ return LayoutUnit();
+ return MinimumValueForLength(
+ style.RowGap().GetLength(),
+ percent_resolution_sizes.block_size.ClampNegativeToZero());
+ }
+ if (LIKELY(style.ColumnGap().IsNormal()))
+ return LayoutUnit();
+ return MinimumValueForLength(style.ColumnGap().GetLength(),
+ percent_resolution_sizes.inline_size);
+}
+
FlexLayoutAlgorithm::FlexLayoutAlgorithm(const ComputedStyle* style,
- LayoutUnit line_break_length)
- : style_(style),
+ LayoutUnit line_break_length,
+ LogicalSize percent_resolution_sizes,
+ Document* document)
+ : gap_between_items_(GapBetweenItems(*style, percent_resolution_sizes)),
+ gap_between_lines_(GapBetweenLines(*style, percent_resolution_sizes)),
+ style_(style),
line_break_length_(line_break_length),
- next_item_index_(0) {}
+ next_item_index_(0) {
+ DCHECK_GE(gap_between_items_, 0);
+ DCHECK_GE(gap_between_lines_, 0);
+ const auto& row_gap = style->RowGap();
+ const auto& column_gap = style->ColumnGap();
+ if (!row_gap.IsNormal() || !column_gap.IsNormal()) {
+ UseCounter::Count(document, WebFeature::kFlexGapSpecified);
+ if (gap_between_items_ || gap_between_lines_)
+ UseCounter::Count(document, WebFeature::kFlexGapPositive);
+ }
+
+ if (!row_gap.IsNormal() && row_gap.GetLength().IsPercentOrCalc()) {
+ UseCounter::Count(document, WebFeature::kFlexRowGapPercent);
+ if (percent_resolution_sizes.block_size == LayoutUnit(-1))
+ UseCounter::Count(document, WebFeature::kFlexRowGapPercentIndefinite);
+ }
+}
FlexLine* FlexLayoutAlgorithm::ComputeNextFlexLine(
LayoutUnit container_logical_width) {
@@ -603,15 +668,24 @@ FlexLine* FlexLayoutAlgorithm::ComputeNextFlexLine(
break;
}
line_has_in_flow_item = true;
- sum_flex_base_size += flex_item.FlexBaseMarginBoxSize();
+ sum_flex_base_size +=
+ flex_item.FlexBaseMarginBoxSize() + gap_between_items_;
total_flex_grow += flex_item.style.ResolvedFlexGrow(StyleRef());
const float flex_shrink = flex_item.style.ResolvedFlexShrink(StyleRef());
total_flex_shrink += flex_shrink;
total_weighted_flex_shrink +=
flex_shrink * flex_item.flex_base_content_size;
- sum_hypothetical_main_size += flex_item.HypotheticalMainAxisMarginBoxSize();
+ sum_hypothetical_main_size +=
+ flex_item.HypotheticalMainAxisMarginBoxSize() + gap_between_items_;
flex_item.line_number = flex_lines_.size();
}
+ if (line_has_in_flow_item) {
+ // We added a gap after every item but there shouldn't be one after the last
+ // item, so subtract it here.
+ // Note: the two sums here can be negative because of negative margins.
+ sum_hypothetical_main_size -= gap_between_items_;
+ sum_flex_base_size -= gap_between_items_;
+ }
DCHECK(next_item_index_ > start_index ||
next_item_index_ == all_items_.size());
@@ -630,7 +704,12 @@ bool FlexLayoutAlgorithm::IsHorizontalFlow() const {
}
bool FlexLayoutAlgorithm::IsColumnFlow() const {
- return StyleRef().ResolvedIsColumnFlexDirection();
+ return IsColumnFlow(*style_);
+}
+
+// static
+bool FlexLayoutAlgorithm::IsColumnFlow(const ComputedStyle& style) {
+ return style.ResolvedIsColumnFlexDirection();
}
// static
@@ -666,9 +745,12 @@ bool FlexLayoutAlgorithm::ShouldApplyMinSizeAutoForChild(
// css-flexbox section 4.5
const Length& min = IsHorizontalFlow() ? child.StyleRef().MinWidth()
: child.StyleRef().MinHeight();
- // TODO(dgrogan): min.IsIntrinsic should also get past this check when in the
- // item's block direction.
- if (!min.IsAuto())
+ bool main_axis_is_childs_block_axis =
+ IsHorizontalFlow() != child.StyleRef().IsHorizontalWritingMode();
+ bool intrinsic_in_childs_block_axis =
+ main_axis_is_childs_block_axis &&
+ (min.IsMinContent() || min.IsMaxContent() || min.IsFitContent());
+ if (!min.IsAuto() && !intrinsic_in_childs_block_axis)
return false;
// webkit-box treats min-size: auto as 0.
@@ -699,16 +781,20 @@ LayoutUnit FlexLayoutAlgorithm::IntrinsicContentBlockSize() const {
const FlexLine& last_line = flex_lines_.back();
// Subtract the first line's offset to remove border/padding
return last_line.cross_axis_offset + last_line.cross_axis_extent -
- flex_lines_.front().cross_axis_offset;
+ flex_lines_.front().cross_axis_offset +
+ (flex_lines_.size() - 1) * gap_between_lines_;
}
void FlexLayoutAlgorithm::AlignFlexLines(LayoutUnit cross_axis_content_extent) {
const StyleContentAlignmentData align_content = ResolvedAlignContent(*style_);
- if (align_content.GetPosition() == ContentPosition::kFlexStart)
+ if (align_content.GetPosition() == ContentPosition::kFlexStart &&
+ gap_between_lines_ == 0) {
return;
+ }
if (flex_lines_.IsEmpty() || !IsMultiline())
return;
- LayoutUnit available_cross_axis_space = cross_axis_content_extent;
+ LayoutUnit available_cross_axis_space =
+ cross_axis_content_extent - (flex_lines_.size() - 1) * gap_between_lines_;
for (const FlexLine& line : flex_lines_)
available_cross_axis_space -= line.cross_axis_extent;
@@ -729,8 +815,10 @@ void FlexLayoutAlgorithm::AlignFlexLines(LayoutUnit cross_axis_content_extent) {
static_cast<unsigned>(flex_lines_.size());
}
- line_offset += ContentDistributionSpaceBetweenChildren(
- available_cross_axis_space, align_content, flex_lines_.size());
+ line_offset +=
+ ContentDistributionSpaceBetweenChildren(
+ available_cross_axis_space, align_content, flex_lines_.size()) +
+ gap_between_lines_;
}
}
diff --git a/chromium/third_party/blink/renderer/core/layout/flexible_box_algorithm.h b/chromium/third_party/blink/renderer/core/layout/flexible_box_algorithm.h
index 19ccd4575f2..6e0a4c255e4 100644
--- a/chromium/third_party/blink/renderer/core/layout/flexible_box_algorithm.h
+++ b/chromium/third_party/blink/renderer/core/layout/flexible_box_algorithm.h
@@ -116,6 +116,7 @@ class FlexItem {
// - |min_max_main_sizes| is the resolved min and max size properties in the
// main axis direction (not intrinsic widths). It does not include
// border/padding.
+ // |min_max_cross_sizes| does include cross_axis_border_padding.
FlexItem(const FlexLayoutAlgorithm*,
LayoutBox*,
const ComputedStyle& style,
@@ -359,7 +360,10 @@ class FlexLayoutAlgorithm {
DISALLOW_NEW();
public:
- FlexLayoutAlgorithm(const ComputedStyle*, LayoutUnit line_break_length);
+ FlexLayoutAlgorithm(const ComputedStyle*,
+ LayoutUnit line_break_length,
+ LogicalSize percent_resolution_sizes,
+ Document*);
template <typename... Args>
FlexItem& emplace_back(Args&&... args) {
@@ -381,6 +385,7 @@ class FlexLayoutAlgorithm {
bool IsColumnFlow() const;
bool IsMultiline() const { return style_->FlexWrap() != EFlexWrap::kNowrap; }
static bool IsHorizontalFlow(const ComputedStyle&);
+ static bool IsColumnFlow(const ComputedStyle&);
bool IsLeftToRightFlow() const;
TransformedWritingMode GetTransformedWritingMode() const;
@@ -429,6 +434,13 @@ class FlexLayoutAlgorithm {
LayoutUnit border_scrollbar_padding_before);
bool IsNGFlexBox() const;
+ static LayoutUnit GapBetweenItems(const ComputedStyle& style,
+ LogicalSize percent_resolution_sizes);
+ static LayoutUnit GapBetweenLines(const ComputedStyle& style,
+ LogicalSize percent_resolution_sizes);
+ const LayoutUnit gap_between_items_;
+ const LayoutUnit gap_between_lines_;
+
private:
EOverflow MainAxisOverflowForChild(const LayoutBox& child) const;
diff --git a/chromium/third_party/blink/renderer/core/layout/grid_track_sizing_algorithm.cc b/chromium/third_party/blink/renderer/core/layout/grid_track_sizing_algorithm.cc
index 9ac29ea0ea3..16d8d1e7d2c 100644
--- a/chromium/third_party/blink/renderer/core/layout/grid_track_sizing_algorithm.cc
+++ b/chromium/third_party/blink/renderer/core/layout/grid_track_sizing_algorithm.cc
@@ -941,8 +941,6 @@ GridTrackSize GridTrackSizingAlgorithm::CalculateGridTrackSize(
GridLength min_track_breadth = track_size.MinTrackBreadth();
GridLength max_track_breadth = track_size.MaxTrackBreadth();
- if (strategy_->IsComputingSizeContainment())
- return GridTrackSize(min_track_breadth, max_track_breadth);
// If the logical width/height of the grid container is indefinite, percentage
// values are treated as <auto>.
@@ -971,11 +969,14 @@ GridTrackSize GridTrackSizingAlgorithm::CalculateGridTrackSize(
LayoutUnit GridTrackSizingAlgorithm::InitialBaseSize(
const GridTrackSize& track_size) const {
const GridLength& grid_length = track_size.MinTrackBreadth();
- if (grid_length.IsFlex())
- return LayoutUnit();
+
+ // TODO(obrufau): https://github.com/w3c/csswg-drafts/issues/2611 may allow
+ // flexible lengths to be used as min track sizing functions.
+ DCHECK(!grid_length.IsFlex());
const Length& track_length = grid_length.length();
if (track_length.IsSpecified()) {
+ DCHECK(!grid_length.HasPercentage() || AvailableSpace());
return ValueForLength(track_length,
AvailableSpace().value_or(LayoutUnit()));
}
@@ -994,6 +995,7 @@ LayoutUnit GridTrackSizingAlgorithm::InitialGrowthLimit(
const Length& track_length = grid_length.length();
if (track_length.IsSpecified()) {
+ DCHECK(!grid_length.HasPercentage() || AvailableSpace());
return ValueForLength(track_length,
AvailableSpace().value_or(LayoutUnit()));
}
diff --git a/chromium/third_party/blink/renderer/core/layout/hit_testing_test.cc b/chromium/third_party/blink/renderer/core/layout/hit_testing_test.cc
index 8927df5bbd2..76f912f9095 100644
--- a/chromium/third_party/blink/renderer/core/layout/hit_testing_test.cc
+++ b/chromium/third_party/blink/renderer/core/layout/hit_testing_test.cc
@@ -3,11 +3,72 @@
// found in the LICENSE file.
#include "third_party/blink/renderer/core/css/css_property_names.h"
+#include "third_party/blink/renderer/core/editing/text_affinity.h"
#include "third_party/blink/renderer/core/testing/core_unit_test_helper.h"
namespace blink {
-class HitTestingTest : public RenderingTest {};
+class HitTestingTest : public RenderingTest {
+ protected:
+ bool LayoutNGEnabled() const {
+ return RuntimeEnabledFeatures::LayoutNGEnabled();
+ }
+
+ PositionWithAffinity HitTest(const PhysicalOffset offset) {
+ const HitTestRequest hit_request(HitTestRequest::kActive);
+ const HitTestLocation hit_location(offset);
+ HitTestResult hit_result(hit_request, hit_location);
+ if (!GetLayoutView().HitTest(hit_location, hit_result))
+ return PositionWithAffinity();
+ // Simulate |PositionWithAffinityOfHitTestResult()| in
+ // "selection_controller.cc"
+ LayoutObject* const layout_object =
+ hit_result.InnerPossiblyPseudoNode()->GetLayoutObject();
+ if (!layout_object)
+ return PositionWithAffinity();
+ return layout_object->PositionForPoint(hit_result.LocalPoint());
+ }
+};
+
+// http://crbug.com/1043471
+TEST_F(HitTestingTest, PseudoElementAfter) {
+ LoadAhem();
+ InsertStyleElement(
+ "body { margin: 0px; font: 10px/10px Ahem; }"
+ "#cd::after { content: 'XYZ'; margin-left: 100px; }");
+ SetBodyInnerHTML("<div id=ab>ab<span id=cd>cd</span></div>");
+ const auto& text_ab = *To<Text>(GetElementById("ab")->firstChild());
+ const auto& text_cd = *To<Text>(GetElementById("cd")->lastChild());
+
+ EXPECT_EQ(PositionWithAffinity(Position(text_ab, 0)),
+ HitTest(PhysicalOffset(5, 5)));
+ // Because of hit testing at "b", position should be |kDownstream|.
+ EXPECT_EQ(PositionWithAffinity(Position(text_ab, 1),
+ LayoutNGEnabled() ? TextAffinity::kDownstream
+ : TextAffinity::kUpstream),
+ HitTest(PhysicalOffset(15, 5)));
+ EXPECT_EQ(PositionWithAffinity(Position(text_cd, 0)),
+ HitTest(PhysicalOffset(25, 5)));
+ // Because of hit testing at "d", position should be |kDownstream|.
+ EXPECT_EQ(PositionWithAffinity(Position(text_cd, 1),
+ LayoutNGEnabled() ? TextAffinity::kDownstream
+ : TextAffinity::kUpstream),
+ HitTest(PhysicalOffset(35, 5)));
+ // Because of hit testing at right of <span cd>, result position should be
+ // |kUpstream|.
+ EXPECT_EQ(PositionWithAffinity(Position(text_cd, 2),
+ LayoutNGEnabled() ? TextAffinity::kUpstream
+ : TextAffinity::kDownstream),
+ HitTest(PhysicalOffset(45, 5)));
+ EXPECT_EQ(PositionWithAffinity(Position(text_cd, 2),
+ LayoutNGEnabled() ? TextAffinity::kUpstream
+ : TextAffinity::kDownstream),
+ HitTest(PhysicalOffset(55, 5)));
+ EXPECT_EQ(PositionWithAffinity(Position(text_cd, 2),
+ LayoutNGEnabled() ? TextAffinity::kUpstream
+ : TextAffinity::kDownstream),
+ HitTest(PhysicalOffset(65, 5)));
+}
TEST_F(HitTestingTest, OcclusionHitTest) {
SetBodyInnerHTML(R"HTML(
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_block.cc b/chromium/third_party/blink/renderer/core/layout/layout_block.cc
index c17f2501e74..4e97d89ff2f 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_block.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_block.cc
@@ -30,6 +30,7 @@
#include "base/memory/ptr_util.h"
#include "third_party/blink/renderer/core/css/style_engine.h"
+#include "third_party/blink/renderer/core/display_lock/display_lock_utilities.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/element.h"
#include "third_party/blink/renderer/core/editing/drag_caret.h"
@@ -42,6 +43,7 @@
#include "third_party/blink/renderer/core/html_names.h"
#include "third_party/blink/renderer/core/layout/api/line_layout_box.h"
#include "third_party/blink/renderer/core/layout/api/line_layout_item.h"
+#include "third_party/blink/renderer/core/layout/box_layout_extra_input.h"
#include "third_party/blink/renderer/core/layout/hit_test_location.h"
#include "third_party/blink/renderer/core/layout/hit_test_result.h"
#include "third_party/blink/renderer/core/layout/layout_analyzer.h"
@@ -111,6 +113,9 @@ LayoutBlock::LayoutBlock(ContainerNode* node)
has_percent_height_descendants_(false),
pagination_state_changed_(false),
is_legacy_initiated_out_of_flow_layout_(false) {
+ if (node)
+ GetDocument().IncLayoutBlockCounter();
+
// LayoutBlockFlow calls setChildrenInline(true).
// By default, subclasses do not have inline children.
}
@@ -431,7 +436,10 @@ void LayoutBlock::UpdateBlockLayout(bool) {
}
void LayoutBlock::AddVisualOverflowFromChildren() {
- if (LayoutBlockedByDisplayLock(DisplayLockLifecycleTarget::kChildren))
+ // It is an error to call this function on a LayoutBlock that it itself inside
+ // a display-locked subtree.
+ DCHECK(!DisplayLockUtilities::LockedAncestorPreventingPrePaint(*this));
+ if (PrePaintBlockedByDisplayLock(DisplayLockLifecycleTarget::kChildren))
return;
if (ChildrenInline())
@@ -887,12 +895,13 @@ void LayoutBlock::LayoutPositionedObject(LayoutBox* positioned_object,
LayoutObject* parent = positioned_object->Parent();
bool layout_changed = false;
- // TODO(dgrogan): The NG flexbox implementation doesn't have an analogous
- // method yet, so abspos children of NG flexboxes that have a legacy
- // containing block will not be positioned correctly.
- if (parent->IsFlexibleBox() &&
- ToLayoutFlexibleBox(parent)->SetStaticPositionForPositionedLayout(
- *positioned_object)) {
+ if ((parent->IsLayoutNGFlexibleBox() &&
+ !positioned_object->IsLayoutNGMixin() &&
+ LayoutFlexibleBox::SetStaticPositionForChildInFlexNGContainer(
+ *positioned_object, To<LayoutBlock>(parent))) ||
+ (parent->IsFlexibleBox() &&
+ ToLayoutFlexibleBox(parent)->SetStaticPositionForPositionedLayout(
+ *positioned_object))) {
// The static position of an abspos child of a flexbox depends on its size
// (for example, they can be centered). So we may have to reposition the
// item after layout.
@@ -1103,6 +1112,16 @@ void LayoutBlock::AddPercentHeightDescendant(LayoutBox* descendant) {
}
descendant->SetPercentHeightContainer(this);
+ // Mark our containing block chain as potentially having a percent height
+ // descendant.
+ LayoutBlock* cb = descendant->ContainingBlock();
+ while (cb) {
+ cb->SetMaybeHasPercentHeightDescendant();
+ if (cb == this)
+ break;
+ cb = cb->ContainingBlock();
+ }
+
if (!g_percent_height_descendants_map)
g_percent_height_descendants_map = new TrackedDescendantsMap;
TrackedLayoutBoxListHashSet* descendant_set =
@@ -2111,8 +2130,10 @@ bool LayoutBlock::RecalcChildLayoutOverflow() {
void LayoutBlock::RecalcChildVisualOverflow() {
DCHECK(!IsTable());
-
- if (PaintBlockedByDisplayLock(DisplayLockLifecycleTarget::kChildren))
+ // It is an error to call this function on a LayoutBlock that it itself inside
+ // a display-locked subtree.
+ DCHECK(!DisplayLockUtilities::LockedAncestorPreventingPrePaint(*this));
+ if (PrePaintBlockedByDisplayLock(DisplayLockLifecycleTarget::kChildren))
return;
if (ChildrenInline()) {
@@ -2275,6 +2296,8 @@ LayoutUnit LayoutBlock::AvailableLogicalHeightForPercentageComputation() const {
const LayoutFlexibleBox* flex_box = ToLayoutFlexibleBox(Parent());
if (flex_box->UseOverrideLogicalHeightForPerentageResolution(*this))
stretched_flex_height = OverrideContentLogicalHeight();
+ } else if (HasOverrideLogicalHeight() && IsOverrideLogicalHeightDefinite()) {
+ stretched_flex_height = OverrideContentLogicalHeight();
}
if (stretched_flex_height != LayoutUnit(-1)) {
available_height = stretched_flex_height;
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_block_flow.cc b/chromium/third_party/blink/renderer/core/layout/layout_block_flow.cc
index b0d5df85710..6214dce7169 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_block_flow.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_block_flow.cc
@@ -64,6 +64,7 @@
#include "third_party/blink/renderer/core/layout/ng/ng_unpositioned_float.h"
#include "third_party/blink/renderer/core/layout/shapes/shape_outside_info.h"
#include "third_party/blink/renderer/core/layout/text_autosizer.h"
+#include "third_party/blink/renderer/core/page/named_pages_mapper.h"
#include "third_party/blink/renderer/core/paint/block_flow_paint_invalidator.h"
#include "third_party/blink/renderer/core/paint/ng/ng_paint_fragment.h"
#include "third_party/blink/renderer/core/paint/paint_layer.h"
@@ -879,8 +880,15 @@ void LayoutBlockFlow::InsertForcedBreakBeforeChildIfNeeded(
LayoutUnit pagination_strut = new_logical_top - old_logical_top;
child.SetPaginationStrut(pagination_strut);
if (is_named_page_break) {
- // This was a forced break because of named pages.
+ // This was a forced break because of named pages. We now need to store
+ // the page number where this happened, so that we can apply the right
+ // descriptors (size, margins, page-orientation, etc.) when printing the
+ // page.
layout_info.SetChildPageName(child.StyleRef().Page());
+ if (NamedPagesMapper* mapper = View()->GetNamedPagesMapper()) {
+ mapper->AddNamedPage(child.StyleRef().Page(),
+ CurrentPageNumber(new_logical_top));
+ }
}
}
}
@@ -4316,7 +4324,10 @@ void LayoutBlockFlow::CreateOrDestroyMultiColumnFlowThreadIfNeeded(
// Fieldsets look for a legend special child (layoutSpecialExcludedChild()).
// We currently only support one special child per layout object, and the
// flow thread would make for a second one.
- if (IsFieldset())
+ // For LayoutNG, the multi-column display type will be applied to the
+ // anonymous content box. Thus, the flow thread should be added to the
+ // anonymous content box instead of the fieldset itself.
+ if (IsFieldsetIncludingNG())
return;
// Form controls are replaced content, and are therefore not supposed to
@@ -4330,8 +4341,8 @@ void LayoutBlockFlow::CreateOrDestroyMultiColumnFlowThreadIfNeeded(
if (IsLayoutNGCustom())
return;
- LayoutMultiColumnFlowThread* flow_thread =
- LayoutMultiColumnFlowThread::CreateAnonymous(GetDocument(), StyleRef());
+ auto* flow_thread = LayoutMultiColumnFlowThread::CreateAnonymous(
+ GetDocument(), StyleRef(), !CanTraversePhysicalFragments());
AddChild(flow_thread);
pagination_state_changed_ = true;
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_block_flow_line.cc b/chromium/third_party/blink/renderer/core/layout/layout_block_flow_line.cc
index 96f21e1d24c..dc9f0999a5f 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_block_flow_line.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_block_flow_line.cc
@@ -2404,7 +2404,8 @@ void LayoutBlockFlow::AddVisualOverflowFromInlineChildren() {
}
} else if (const NGPhysicalBoxFragment* fragment = CurrentFragment()) {
if (const NGFragmentItems* items = fragment->Items()) {
- for (NGInlineCursor cursor(*items); cursor; cursor.MoveToNextSibling()) {
+ for (NGInlineCursor cursor(*items); cursor;
+ cursor.MoveToNextSkippingChildren()) {
const NGFragmentItem* child = cursor.CurrentItem();
DCHECK(child);
if (child->HasSelfPaintingLayer())
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_box.cc b/chromium/third_party/blink/renderer/core/layout/layout_box.cc
index d10c1623fc7..c0cc36526af 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_box.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_box.cc
@@ -210,8 +210,8 @@ LayoutUnit MenuListIntrinsicInlineSize(const HTMLSelectElement& select,
LayoutTheme& theme = LayoutTheme::GetTheme();
int paddings = theme.PopupInternalPaddingStart(style) +
theme.PopupInternalPaddingEnd(box.GetFrame(), style);
- return std::max(static_cast<int>(ceilf(max_option_width)),
- LayoutTheme::GetTheme().MinimumMenuListSize(style)) +
+ return std::max(LayoutUnit(ceilf(max_option_width)),
+ LayoutUnit(theme.MinimumMenuListSize(style))) +
LayoutUnit(paddings);
}
@@ -270,7 +270,8 @@ PaintLayerType LayoutBox::LayerTypeRequired() const {
// since position:static elements that are not flex-items get their z-index
// coerced to auto.
if (IsPositioned() || CreatesGroup() || HasTransformRelatedProperty() ||
- HasHiddenBackface() || HasReflection() || StyleRef().SpecifiesColumns() ||
+ HasHiddenBackface() || HasReflection() ||
+ (StyleRef().SpecifiesColumns() && !CanTraversePhysicalFragments()) ||
StyleRef().IsStackingContext() ||
StyleRef().ShouldCompositeForCurrentAnimations() ||
IsEffectiveRootScroller())
@@ -296,8 +297,15 @@ void LayoutBox::WillBeDestroyed() {
ShapeOutsideInfo::RemoveInfo(*this);
if (!DocumentBeingDestroyed()) {
- if (NGPaintFragment* first_inline_fragment = FirstInlineFragment())
- first_inline_fragment->LayoutObjectWillBeDestroyed();
+ if (!RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()) {
+ if (NGPaintFragment* first_inline_fragment = FirstInlineFragment())
+ first_inline_fragment->LayoutObjectWillBeDestroyed();
+ } else if (FirstInlineFragmentItemIndex()) {
+ NGFragmentItems::LayoutObjectWillBeDestroyed(*this);
+ ClearFirstInlineFragmentItemIndex();
+ }
+ if (measure_result_)
+ measure_result_->PhysicalFragment().LayoutObjectWillBeDestroyed();
for (auto result : layout_results_)
result->PhysicalFragment().LayoutObjectWillBeDestroyed();
}
@@ -886,6 +894,11 @@ void LayoutBox::UpdateAfterLayout() {
// Legacy, then NG again, NG won't use a stale layout result.
if (IsOutOfFlowPositioned() && !IsLayoutNGObject())
ClearLayoutResults();
+
+ Document& document = GetDocument();
+ document.IncLayoutCallsCounter();
+ if (IsLayoutNGObject())
+ document.IncLayoutCallsCounterNG();
}
bool LayoutBox::HasOverrideIntrinsicContentWidth() const {
@@ -1121,13 +1134,10 @@ PhysicalRect LayoutBox::PhysicalBackgroundRect(
switch (background_box) {
case EFillBox::kBorder:
return PhysicalBorderBoxRect();
- break;
case EFillBox::kPadding:
return PhysicalPaddingBoxRect();
- break;
case EFillBox::kContent:
return PhysicalContentBoxRect();
- break;
default:
break;
}
@@ -1519,6 +1529,10 @@ LayoutUnit LayoutBox::OverrideLogicalHeight() const {
return rare_data_->override_logical_height_;
}
+bool LayoutBox::IsOverrideLogicalHeightDefinite() const {
+ return extra_input_ && extra_input_->is_override_block_size_definite;
+}
+
bool LayoutBox::HasOverrideLogicalHeight() const {
if (extra_input_ && extra_input_->override_block_size)
return true;
@@ -2468,17 +2482,12 @@ bool LayoutBox::HasInlineFragments() const {
return inline_box_wrapper_;
if (!RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled())
return first_paint_fragment_;
- // TODO(yosin): We should use |first_fragment_item_index_|.
- NGInlineCursor cursor;
- cursor.MoveTo(*this);
- return cursor;
+ return first_fragment_item_index_;
}
void LayoutBox::SetFirstInlineFragment(NGPaintFragment* fragment) {
CHECK(IsInLayoutNGInlineFormattingContext()) << *this;
- // TODO(yosin): Once we remove |NGPaintFragment|, we should get rid of
- // |!fragment|.
- DCHECK(!fragment || !RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled());
+ DCHECK(!RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled());
first_paint_fragment_ = fragment;
}
@@ -2492,17 +2501,26 @@ void LayoutBox::SetFirstInlineFragmentItemIndex(wtf_size_t index) {
CHECK(IsInLayoutNGInlineFormattingContext()) << *this;
DCHECK(RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled());
DCHECK_NE(index, 0u);
- // TDOO(yosin): Once we update all |LayoutObject::FirstInlineFragment()|,
- // we should enable below.
- // first_fragment_item_index_ = index;
+ first_fragment_item_index_ = index;
}
void LayoutBox::InLayoutNGInlineFormattingContextWillChange(bool new_value) {
- DeleteLineBoxWrapper();
+ if (IsInLayoutNGInlineFormattingContext()) {
+ if (!RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()) {
+ SetFirstInlineFragment(nullptr);
+ } else {
+ ClearFirstInlineFragmentItemIndex();
+ }
+ } else {
+ DeleteLineBoxWrapper();
+ }
// Because |first_paint_fragment_| and |inline_box_wrapper_| are union, when
// one is deleted, the other should be initialized to nullptr.
- DCHECK(new_value ? !first_paint_fragment_ : !inline_box_wrapper_);
+ DCHECK(new_value ? (RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()
+ ? !first_fragment_item_index_
+ : !first_paint_fragment_)
+ : !inline_box_wrapper_);
}
void LayoutBox::SetCachedLayoutResult(
@@ -2512,10 +2530,18 @@ void LayoutBox::SetCachedLayoutResult(
if (result->GetConstraintSpaceForCaching().CacheSlot() ==
NGCacheSlot::kMeasure) {
+ // We don't early return here, when setting the "measure" result we also
+ // set the "layout" result.
if (measure_result_)
InvalidateItems(*measure_result_);
measure_result_ = result;
- // When setting the "measure" result we also set the "layout" result.
+ } else {
+ // We have a "layout" result, and we may need to clear the old "measure"
+ // result if we needed non-simplified layout.
+ if (measure_result_ && NeedsLayout() && !NeedsSimplifiedLayoutOnly()) {
+ InvalidateItems(*measure_result_);
+ measure_result_ = nullptr;
+ }
}
AddLayoutResult(std::move(result), 0);
@@ -2524,9 +2550,50 @@ void LayoutBox::SetCachedLayoutResult(
void LayoutBox::AddLayoutResult(scoped_refptr<const NGLayoutResult> result,
wtf_size_t index) {
DCHECK_EQ(result->Status(), NGLayoutResult::kSuccess);
- if (index != WTF::kNotFound)
- ShrinkLayoutResults(index);
+ if (index != WTF::kNotFound && layout_results_.size() > index) {
+ if (layout_results_.size() > index + 1)
+ ShrinkLayoutResults(index + 1);
+ ReplaceLayoutResult(std::move(result), index);
+ return;
+ }
+ const auto& fragment = To<NGPhysicalBoxFragment>(result->PhysicalFragment());
layout_results_.push_back(std::move(result));
+ // If this is the last fragment for the node, and its node establishes an
+ // inline formatting context, we have some finalization to do.
+ if (!fragment.BreakToken() && fragment.Items())
+ NGFragmentItems::FinalizeAfterLayout(layout_results_);
+}
+
+void LayoutBox::ReplaceLayoutResult(scoped_refptr<const NGLayoutResult> result,
+ wtf_size_t index) {
+ DCHECK_LE(index, layout_results_.size());
+ const NGLayoutResult* old_result = layout_results_[index].get();
+ if (old_result == result.get())
+ return;
+ const auto& fragment = To<NGPhysicalBoxFragment>(result->PhysicalFragment());
+ bool got_new_fragment = &old_result->PhysicalFragment() != &fragment;
+ if (got_new_fragment) {
+ // Clear associations with the LayoutObjects and the items in the *first*
+ // box fragment. We only ever associate LayoutObjects with the items in the
+ // first box fragment, but this doesn't take place until we have added all
+ // the fragments for the node. Therefore we need to clean up this now,
+ // regardless of which index we're at. This means that we're potentially
+ // doing duplicate work here (for each fragment we replace), but only if
+ // we're split into multiple box fragments.
+ // TODO(layout-dev): Make this work for multiple box fragments (block
+ // fragmentation).
+ if (To<NGPhysicalBoxFragment>(layout_results_[0]->PhysicalFragment())
+ .HasItems()) {
+ if (!index)
+ InvalidateItems(*old_result);
+ NGFragmentItems::ClearAssociatedFragments(this);
+ }
+ }
+ layout_results_[index] = std::move(result);
+ // If this is the last fragment for the node, and its node establishes an
+ // inline formatting context, we have some finalization to do.
+ if (!fragment.BreakToken() && fragment.Items() && (index || got_new_fragment))
+ NGFragmentItems::FinalizeAfterLayout(layout_results_);
}
void LayoutBox::ClearLayoutResults() {
@@ -2542,6 +2609,12 @@ void LayoutBox::ShrinkLayoutResults(wtf_size_t results_to_keep) {
// Invalidate if inline |DisplayItemClient|s will be destroyed.
for (wtf_size_t i = results_to_keep; i < layout_results_.size(); i++)
InvalidateItems(*layout_results_[i]);
+ if (results_to_keep == 0 && !layout_results_.IsEmpty()) {
+ if (To<NGPhysicalBoxFragment>(layout_results_[0]->PhysicalFragment())
+ .HasItems()) {
+ NGFragmentItems::ClearAssociatedFragments(this);
+ }
+ }
layout_results_.Shrink(results_to_keep);
}
@@ -2551,8 +2624,13 @@ void LayoutBox::InvalidateItems(const NGLayoutResult& result) {
To<NGPhysicalBoxFragment>(result.PhysicalFragment());
if (!box_fragment.HasItems())
return;
-
- DCHECK_EQ(this, box_fragment.GetLayoutObject());
+#if DCHECK_IS_ON()
+ // Column fragments are not really associated with a layout object.
+ if (IsLayoutFlowThread())
+ DCHECK(box_fragment.IsColumnBox());
+ else
+ DCHECK_EQ(this, box_fragment.GetLayoutObject());
+#endif
ObjectPaintInvalidator(*this).SlowSetPaintingLayerNeedsRepaint();
}
@@ -2563,6 +2641,7 @@ const NGLayoutResult* LayoutBox::GetCachedLayoutResult() const {
const NGLayoutResult* result = layout_results_[0].get();
if (result->IsSingleUse())
return nullptr;
+ DCHECK(result->PhysicalFragment().IsAlive());
DCHECK_EQ(layout_results_.size(), 1u);
return result;
}
@@ -2585,11 +2664,12 @@ scoped_refptr<const NGLayoutResult> LayoutBox::CachedLayoutResult(
NGLayoutCacheStatus* out_cache_status) {
*out_cache_status = NGLayoutCacheStatus::kNeedsLayout;
- const NGLayoutResult* cached_layout_result =
+ const bool use_layout_cache_slot =
new_space.CacheSlot() == NGCacheSlot::kLayout &&
- !layout_results_.IsEmpty()
- ? GetCachedLayoutResult()
- : GetCachedMeasureResult();
+ !layout_results_.IsEmpty();
+ const NGLayoutResult* cached_layout_result = use_layout_cache_slot
+ ? GetCachedLayoutResult()
+ : GetCachedMeasureResult();
if (!cached_layout_result)
return nullptr;
@@ -2613,35 +2693,59 @@ scoped_refptr<const NGLayoutResult> LayoutBox::CachedLayoutResult(
!LayoutBlockedByDisplayLock(DisplayLockLifecycleTarget::kChildren) &&
(PosChildNeedsLayout() || NormalChildNeedsLayout());
+ const NGPhysicalBoxFragment& physical_fragment =
+ To<NGPhysicalBoxFragment>(cached_layout_result->PhysicalFragment());
if (SelfNeedsLayoutForStyle() || child_needs_layout_unless_locked ||
NeedsSimplifiedNormalFlowLayout() ||
(NeedsPositionedMovementLayout() &&
!NeedsPositionedMovementLayoutOnly())) {
- // Check if we only need "simplified" layout. We don't abort yet, as we
- // need to check if other things (like floats) will require us to perform a
- // full layout.
- //
- // We don't regenerate any lineboxes during our "simplified" layout pass.
- // If something needs "simplified" layout within a linebox, (e.g. an
- // atomic-inline) we miss the cache.
- if (NeedsSimplifiedLayoutOnly() &&
- (!ChildrenInline() || !NeedsSimplifiedNormalFlowLayout()))
+ if (!ChildrenInline()) {
+ // Check if we only need "simplified" layout. We don't abort yet, as we
+ // need to check if other things (like floats) will require us to perform
+ // a full layout.
+ if (!NeedsSimplifiedLayoutOnly())
+ return nullptr;
+
cache_status = NGLayoutCacheStatus::kNeedsSimplifiedLayout;
- else
- return nullptr;
- }
+ } else if (!NeedsSimplifiedLayoutOnly() ||
+ NeedsSimplifiedNormalFlowLayout()) {
+ // We don't regenerate any lineboxes during our "simplified" layout pass.
+ // If something needs "simplified" layout within a linebox, (e.g. an
+ // atomic-inline) we miss the cache.
- const NGPhysicalContainerFragment& physical_fragment =
- cached_layout_result->PhysicalFragment();
+ if (!RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled())
+ return nullptr;
- DCHECK(!physical_fragment.BreakToken());
+ // Check if some of line boxes are reusable.
- // If we have an orthogonal flow root descendant, we don't attempt to cache
- // our layout result. This is because the initial containing block size may
- // have changed, having a high likelihood of changing the size of the
- // orthogonal flow root.
- if (physical_fragment.HasOrthogonalFlowRoots())
- return nullptr;
+ // Only for the layout cache slot. Measure has several special
+ // optimizations that makes reusing lines complicated.
+ if (!use_layout_cache_slot)
+ return nullptr;
+
+ if (SelfNeedsLayout())
+ return nullptr;
+
+ if (!physical_fragment.HasItems())
+ return nullptr;
+
+ // Propagating OOF needs re-layout.
+ if (physical_fragment.HasOutOfFlowPositionedDescendants())
+ return nullptr;
+
+ // Any floats might need to move, causing lines to wrap differently,
+ // needing re-layout, either in cached result or in new constraint space.
+ if (!cached_layout_result->ExclusionSpace().IsEmpty() ||
+ new_space.HasFloats())
+ return nullptr;
+
+ cache_status = NGLayoutCacheStatus::kCanReuseLines;
+ } else {
+ cache_status = NGLayoutCacheStatus::kNeedsSimplifiedLayout;
+ }
+ }
+
+ DCHECK(!physical_fragment.BreakToken());
NGBlockNode node(this);
NGLayoutCacheStatus size_cache_status = CalculateSizeBasedLayoutCacheStatus(
@@ -2707,7 +2811,8 @@ scoped_refptr<const NGLayoutResult> LayoutBox::CachedLayoutResult(
// sibling.
// The "simplified" layout algorithm doesn't have the required logic to
// shift any added exclusions within the output exclusion space.
- if (cache_status == NGLayoutCacheStatus::kNeedsSimplifiedLayout)
+ if (cache_status == NGLayoutCacheStatus::kNeedsSimplifiedLayout ||
+ cache_status == NGLayoutCacheStatus::kCanReuseLines)
return nullptr;
DCHECK_EQ(cache_status, NGLayoutCacheStatus::kHit);
@@ -2721,7 +2826,8 @@ scoped_refptr<const NGLayoutResult> LayoutBox::CachedLayoutResult(
// We've performed all of the cache checks at this point. If we need
// "simplified" layout then abort now.
*out_cache_status = cache_status;
- if (*out_cache_status == NGLayoutCacheStatus::kNeedsSimplifiedLayout)
+ if (cache_status == NGLayoutCacheStatus::kNeedsSimplifiedLayout ||
+ cache_status == NGLayoutCacheStatus::kCanReuseLines)
return cached_layout_result;
physical_fragment.CheckType();
@@ -4180,9 +4286,12 @@ bool LayoutBox::LogicalHeightComputesAsNone(SizeType size_type) const {
return true;
if (logical_height.IsPercentOrCalc() &&
- HasOverrideContainingBlockContentLogicalHeight() &&
- OverrideContainingBlockContentLogicalHeight() == kIndefiniteSize)
- return true;
+ HasOverrideContainingBlockContentLogicalHeight()) {
+ if (OverrideContainingBlockContentLogicalHeight() == kIndefiniteSize)
+ return true;
+ else if (!GetDocument().InQuirksMode())
+ return false;
+ }
// CustomLayout items can resolve their percentages against an available or
// percentage size override.
@@ -4356,9 +4465,15 @@ LayoutUnit LayoutBox::AvailableLogicalHeightUsing(
const LayoutFlexibleBox& flex_box = ToLayoutFlexibleBox(*Parent());
if (flex_box.UseOverrideLogicalHeightForPerentageResolution(*this))
return OverrideContentLogicalHeight();
- } else if (GetCachedLayoutResult()) {
+ } else if (HasOverrideContainingBlockContentLogicalWidth() &&
+ IsOrthogonalWritingModeRoot()) {
+ return OverrideContainingBlockContentLogicalWidth();
+ } else if (HasOverrideLogicalHeight() &&
+ IsOverrideLogicalHeightDefinite()) {
+ return OverrideContentLogicalHeight();
+ } else if (const auto* previous_result = GetCachedLayoutResult()) {
const NGConstraintSpace& space =
- GetCachedLayoutResult()->GetConstraintSpaceForCaching();
+ previous_result->GetConstraintSpaceForCaching();
if (space.IsFixedBlockSize() && !space.IsFixedBlockSizeIndefinite())
return space.AvailableSize().block_size;
}
@@ -6399,6 +6514,11 @@ LayoutUnit LayoutBox::PageRemainingLogicalHeightForOffset(
return remaining_height - footer_height;
}
+int LayoutBox::CurrentPageNumber(LayoutUnit child_logical_top) const {
+ LayoutUnit offset = OffsetFromLogicalTopOfFirstPage() + child_logical_top;
+ return (offset / View()->PageLogicalHeight()).Floor();
+}
+
bool LayoutBox::CrossesPageBoundary(LayoutUnit offset,
LayoutUnit logical_height) const {
if (!IsPageLogicalHeightKnown())
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_box.h b/chromium/third_party/blink/renderer/core/layout/layout_box.h
index a9484751df2..963867ebfdd 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_box.h
+++ b/chromium/third_party/blink/renderer/core/layout/layout_box.h
@@ -789,6 +789,9 @@ class CORE_EXPORT LayoutBox : public LayoutBoxModelObject {
void SetBoxLayoutExtraInput(const BoxLayoutExtraInput* input) {
extra_input_ = input;
}
+ const BoxLayoutExtraInput* GetBoxLayoutExtraInput() const {
+ return extra_input_;
+ }
void UpdateLayout() override;
void Paint(const PaintInfo&) const override;
@@ -814,6 +817,7 @@ class CORE_EXPORT LayoutBox : public LayoutBoxModelObject {
LayoutUnit OverrideLogicalHeight() const;
LayoutUnit OverrideLogicalWidth() const;
+ bool IsOverrideLogicalHeightDefinite() const;
bool HasOverrideLogicalHeight() const;
bool HasOverrideLogicalWidth() const;
void SetOverrideLogicalHeight(LayoutUnit);
@@ -926,6 +930,8 @@ class CORE_EXPORT LayoutBox : public LayoutBoxModelObject {
LayoutUnit PageRemainingLogicalHeightForOffset(LayoutUnit,
PageBoundaryRule) const;
+ int CurrentPageNumber(LayoutUnit child_logical_top) const;
+
bool CrossesPageBoundary(LayoutUnit offset, LayoutUnit logical_height) const;
// Calculate the strut to insert in order fit content of size
@@ -969,6 +975,8 @@ class CORE_EXPORT LayoutBox : public LayoutBoxModelObject {
// Store one layout result (with its physical fragment) at the specified
// index, and delete all entries following it.
void AddLayoutResult(scoped_refptr<const NGLayoutResult>, wtf_size_t index);
+ void ReplaceLayoutResult(scoped_refptr<const NGLayoutResult>,
+ wtf_size_t index);
void ShrinkLayoutResults(wtf_size_t results_to_keep);
void ClearLayoutResults();
@@ -1618,12 +1626,18 @@ class CORE_EXPORT LayoutBox : public LayoutBoxModelObject {
//
// Also clears the "dirty" flag for the intrinsic logical widths.
void SetIntrinsicLogicalWidthsFromNG(
- const MinMaxSizes& sizes,
- LayoutUnit intrinsic_logical_widths_percentage_resolution_block_size) {
- intrinsic_logical_widths_ = sizes;
+ LayoutUnit intrinsic_logical_widths_percentage_resolution_block_size,
+ bool depends_on_percentage_block_size,
+ bool child_depends_on_percentage_block_size,
+ const MinMaxSizes* sizes) {
intrinsic_logical_widths_percentage_resolution_block_size_ =
intrinsic_logical_widths_percentage_resolution_block_size;
-
+ SetIntrinsicLogicalWidthsDependsOnPercentageBlockSize(
+ depends_on_percentage_block_size);
+ SetIntrinsicLogicalWidthsChildDependsOnPercentageBlockSize(
+ child_depends_on_percentage_block_size);
+ if (sizes)
+ intrinsic_logical_widths_ = *sizes;
ClearIntrinsicLogicalWidthsDirty();
}
@@ -2001,11 +2015,10 @@ inline void LayoutBox::SetInlineBoxWrapper(InlineBox* box_wrapper) {
inline NGPaintFragment* LayoutBox::FirstInlineFragment() const {
if (!IsInLayoutNGInlineFormattingContext())
return nullptr;
- // TODO(yosin): Once we replace all usage of |FirstInlineFragment()| to
- // |NGInlineCursor|, we should change this to |DCHECK()|.
- if (RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled())
- return nullptr;
- return first_paint_fragment_;
+ if (!RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled())
+ return first_paint_fragment_;
+ NOTREACHED();
+ return nullptr;
}
inline wtf_size_t LayoutBox::FirstInlineFragmentItemIndex() const {
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_box_model_object.cc b/chromium/third_party/blink/renderer/core/layout/layout_box_model_object.cc
index e3b20800d32..42a4f5d5b50 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_box_model_object.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_box_model_object.cc
@@ -96,9 +96,18 @@ bool LayoutBoxModelObject::UsesCompositedScrolling() const {
Layer()->GetScrollableArea()->UsesCompositedScrolling();
}
+static bool HasInsetBoxShadow(const ComputedStyle& style) {
+ if (!style.BoxShadow())
+ return false;
+ for (const ShadowData& shadow : style.BoxShadow()->Shadows()) {
+ if (shadow.Style() == kInset)
+ return true;
+ }
+ return false;
+}
+
BackgroundPaintLocation
-LayoutBoxModelObject::ComputeBackgroundPaintLocationIfComposited(
- uint32_t* main_thread_scrolling_reasons) const {
+LayoutBoxModelObject::ComputeBackgroundPaintLocationIfComposited() const {
bool may_have_scrolling_layers_without_scrolling = IsA<LayoutView>(this);
const auto* scrollable_area = GetScrollableArea();
bool scrolls_overflow = scrollable_area && scrollable_area->ScrollsOverflow();
@@ -113,6 +122,16 @@ LayoutBoxModelObject::ComputeBackgroundPaintLocationIfComposited(
return kBackgroundPaintInScrollingContents;
}
+ // TODO(flackr): When we correctly clip the scrolling contents layer we can
+ // paint locally equivalent backgrounds into it. https://crbug.com/645957
+ if (HasClip())
+ return kBackgroundPaintInGraphicsLayer;
+
+ // Inset box shadow is painted in the scrolling area above the background, and
+ // it doesn't scroll, so the background can only be painted in the main layer.
+ if (HasInsetBoxShadow(StyleRef()))
+ return kBackgroundPaintInGraphicsLayer;
+
// TODO(flackr): Detect opaque custom scrollbars which would cover up a
// border-box background.
bool has_custom_scrollbars =
@@ -122,25 +141,10 @@ LayoutBoxModelObject::ComputeBackgroundPaintLocationIfComposited(
(scrollable_area->VerticalScrollbar() &&
scrollable_area->VerticalScrollbar()->IsCustomScrollbar()));
- // TODO(flackr): When we correctly clip the scrolling contents layer we can
- // paint locally equivalent backgrounds into it. https://crbug.com/645957
- if (HasClip())
- return kBackgroundPaintInGraphicsLayer;
-
- // TODO(flackr): Remove this when box shadows are still painted correctly when
- // painting into the composited scrolling contents layer.
- // https://crbug.com/646464
- if (StyleRef().BoxShadow()) {
- if (main_thread_scrolling_reasons) {
- *main_thread_scrolling_reasons |=
- cc::MainThreadScrollingReason::kHasBoxShadowFromNonRootLayer;
- }
- return kBackgroundPaintInGraphicsLayer;
- }
-
// Assume optimistically that the background can be painted in the scrolling
// contents until we find otherwise.
BackgroundPaintLocation paint_location = kBackgroundPaintInScrollingContents;
+
const FillLayer* layer = &(StyleRef().BackgroundLayers());
for (; layer; layer = layer->Next()) {
if (layer->Attachment() == EFillAttachment::kLocal)
@@ -209,9 +213,13 @@ void LayoutBoxModelObject::WillBeDestroyed() {
// 0 during destruction.
if (LocalFrame* frame = GetFrame()) {
if (LocalFrameView* frame_view = frame->View()) {
- if (StyleRef().HasViewportConstrainedPosition() ||
- StyleRef().HasStickyConstrainedPosition())
- frame_view->RemoveViewportConstrainedObject(*this);
+ if (StyleRef().HasViewportConstrainedPosition()) {
+ frame_view->RemoveViewportConstrainedObject(
+ *this, LocalFrameView::ViewportConstrainedType::kFixed);
+ } else if (StyleRef().HasStickyConstrainedPosition()) {
+ frame_view->RemoveViewportConstrainedObject(
+ *this, LocalFrameView::ViewportConstrainedType::kSticky);
+ }
}
}
}
@@ -261,6 +269,8 @@ DISABLE_CFI_PERF
void LayoutBoxModelObject::StyleDidChange(StyleDifference diff,
const ComputedStyle* old_style) {
bool had_transform_related_property = HasTransformRelatedProperty();
+ bool had_filter_inducing_property = HasFilterInducingProperty();
+ bool had_non_initial_backdrop_filter = HasNonInitialBackdropFilter();
bool had_layer = HasLayer();
bool layer_was_self_painting = had_layer && Layer()->IsSelfPaintingLayer();
bool was_horizontal_writing_mode = IsHorizontalWritingMode();
@@ -314,7 +324,8 @@ void LayoutBoxModelObject::StyleDidChange(StyleDifference diff,
Layer()->RemoveOnlyThisLayerAfterStyleChange(old_style);
if (EverHadLayout())
SetChildNeedsLayout();
- if (had_transform_related_property) {
+ if (had_transform_related_property || had_filter_inducing_property ||
+ had_non_initial_backdrop_filter) {
SetNeedsLayoutAndIntrinsicWidthsRecalcAndFullPaintInvalidation(
layout_invalidation_reason::kStyleChange);
}
@@ -335,9 +346,12 @@ void LayoutBoxModelObject::StyleDidChange(StyleDifference diff,
AddSubtreePaintPropertyUpdateReason(
SubtreePaintPropertyUpdateReason::kContainerChainMayChange);
} else if (had_layer == HasLayer() &&
- had_transform_related_property != HasTransformRelatedProperty()) {
- // This affects whether to create transform node. Note that if the
- // HasLayer() value changed, then all of this was already set in
+ (had_transform_related_property != HasTransformRelatedProperty() ||
+ had_filter_inducing_property != HasFilterInducingProperty() ||
+ had_non_initial_backdrop_filter !=
+ HasNonInitialBackdropFilter())) {
+ // This affects whether to create transform, filter, or effect nodes. Note
+ // that if the HasLayer() value changed, then all of this was already set in
// CreateLayerAfterStyleChange() or DestroyLayer().
SetNeedsPaintPropertyUpdate();
if (Layer())
@@ -435,7 +449,8 @@ void LayoutBoxModelObject::StyleDidChange(StyleDifference diff,
} else {
// This may get re-added to viewport constrained objects if the object
// went from sticky to fixed.
- frame_view->RemoveViewportConstrainedObject(*this);
+ frame_view->RemoveViewportConstrainedObject(
+ *this, LocalFrameView::ViewportConstrainedType::kSticky);
// Remove sticky constraints for this layer.
if (Layer()) {
@@ -454,10 +469,13 @@ void LayoutBoxModelObject::StyleDidChange(StyleDifference diff,
}
if (new_style_is_viewport_constained != old_style_is_viewport_constrained) {
- if (new_style_is_viewport_constained && Layer())
- frame_view->AddViewportConstrainedObject(*this);
- else
- frame_view->RemoveViewportConstrainedObject(*this);
+ if (new_style_is_viewport_constained && Layer()) {
+ frame_view->AddViewportConstrainedObject(
+ *this, LocalFrameView::ViewportConstrainedType::kFixed);
+ } else {
+ frame_view->RemoveViewportConstrainedObject(
+ *this, LocalFrameView::ViewportConstrainedType::kFixed);
+ }
}
}
@@ -702,6 +720,13 @@ bool LayoutBoxModelObject::HasAutoHeightOrContainingBlockWithAutoHeight(
if (flex_box.UseOverrideLogicalHeightForPerentageResolution(*this_box))
return false;
} else if (this_box->GetCachedLayoutResult()) {
+ // TODO(dgrogan): We won't get here when laying out the FlexNG item and
+ // its descendant(s) for the first time because the item (|this_box|)
+ // doesn't have anything in its cache. That seems bad because this method
+ // returns true even when the item has a fixed definite height. There
+ // doesn't seem to be an easy way to check the flex item's definiteness
+ // here because the flex item's LayoutObject doesn't have a
+ // BoxLayoutExtraInput that we could add a flag to.
const NGConstraintSpace& space =
this_box->GetCachedLayoutResult()->GetConstraintSpaceForCaching();
if (space.IsFixedBlockSize() && !space.IsFixedBlockSizeIndefinite())
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_box_model_object.h b/chromium/third_party/blink/renderer/core/layout/layout_box_model_object.h
index dd19932660c..2e33f628434 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_box_model_object.h
+++ b/chromium/third_party/blink/renderer/core/layout/layout_box_model_object.h
@@ -187,12 +187,7 @@ class CORE_EXPORT LayoutBoxModelObject : public LayoutObject {
// Returns which layers backgrounds should be painted into for a overflow
// scrolling box if it uses composited scrolling.
- // TODO(yigu): PaintLayerScrollableArea::ComputeNeedsCompositedScrolling
- // calls this method to obtain main thread scrolling reasons due to
- // background paint location. Once the cases get handled on compositor the
- // parameter "reasons" could be removed.
- BackgroundPaintLocation ComputeBackgroundPaintLocationIfComposited(
- uint32_t* main_thread_scrolling_reasons = nullptr) const;
+ BackgroundPaintLocation ComputeBackgroundPaintLocationIfComposited() const;
// These return the CSS computed padding values.
LayoutUnit ComputedCSSPaddingTop() const {
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_box_model_object_test.cc b/chromium/third_party/blink/renderer/core/layout/layout_box_model_object_test.cc
index 990362b2148..a34bab16c6e 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_box_model_object_test.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_box_model_object_test.cc
@@ -1173,6 +1173,136 @@ TEST_F(LayoutBoxModelObjectTest, BackfaceVisibilityChange) {
EXPECT_FALSE(target_layer->SelfNeedsRepaint());
}
+TEST_F(LayoutBoxModelObjectTest, ChangingFilterWithWillChange) {
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ #target {
+ width: 100px;
+ height: 100px;
+ will-change: filter;
+ }
+ </style>
+ <div id="target"></div>
+ )HTML");
+
+ // Adding a filter should not need to check for paint invalidation because
+ // will-change: filter is present.
+ auto* target = GetDocument().getElementById("target");
+ target->setAttribute(html_names::kStyleAttr, "filter: grayscale(1)");
+ GetDocument().UpdateStyleAndLayoutTree();
+ EXPECT_FALSE(target->GetLayoutObject()->ShouldCheckForPaintInvalidation());
+ UpdateAllLifecyclePhasesForTest();
+ EXPECT_FALSE(target->GetLayoutObject()->ShouldCheckForPaintInvalidation());
+
+ // Removing a filter should not need to check for paint invalidation because
+ // will-change: filter is present.
+ target->removeAttribute(html_names::kStyleAttr);
+ GetDocument().UpdateStyleAndLayoutTree();
+ EXPECT_FALSE(target->GetLayoutObject()->ShouldCheckForPaintInvalidation());
+ UpdateAllLifecyclePhasesForTest();
+ EXPECT_FALSE(target->GetLayoutObject()->ShouldCheckForPaintInvalidation());
+}
+
+TEST_F(LayoutBoxModelObjectTest, ChangingWillChangeFilter) {
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ .willChange {
+ will-change: filter;
+ }
+ #filter {
+ width: 100px;
+ height: 100px;
+ }
+ </style>
+ <div id="target"></div>
+ )HTML");
+
+ // Adding will-change: filter should check for paint invalidation and create
+ // a PaintLayer.
+ auto* target = GetDocument().getElementById("target");
+ target->classList().Add("willChange");
+ GetDocument().UpdateStyleAndLayoutTree();
+ EXPECT_TRUE(target->GetLayoutObject()->ShouldCheckForPaintInvalidation());
+ EXPECT_TRUE(ToLayoutBoxModelObject(target->GetLayoutObject())->Layer());
+
+ // A lifecycle update should clear dirty bits.
+ UpdateAllLifecyclePhasesForTest();
+ EXPECT_FALSE(target->GetLayoutObject()->ShouldCheckForPaintInvalidation());
+ EXPECT_TRUE(ToLayoutBoxModelObject(target->GetLayoutObject())->Layer());
+
+ // Removing will-change: filter should check for paint invalidation and remove
+ // the PaintLayer.
+ target->classList().Remove("willChange");
+ GetDocument().UpdateStyleAndLayoutTree();
+ EXPECT_TRUE(target->GetLayoutObject()->ShouldCheckForPaintInvalidation());
+ EXPECT_FALSE(ToLayoutBoxModelObject(target->GetLayoutObject())->Layer());
+}
+
+TEST_F(LayoutBoxModelObjectTest, ChangingBackdropFilterWithWillChange) {
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ #target {
+ width: 100px;
+ height: 100px;
+ will-change: backdrop-filter;
+ }
+ </style>
+ <div id="target"></div>
+ )HTML");
+
+ // Adding a backdrop-filter should not need to check for paint invalidation
+ // because will-change: backdrop-filter is present.
+ auto* target = GetDocument().getElementById("target");
+ target->setAttribute(html_names::kStyleAttr, "backdrop-filter: grayscale(1)");
+ GetDocument().UpdateStyleAndLayoutTree();
+ EXPECT_FALSE(target->GetLayoutObject()->ShouldCheckForPaintInvalidation());
+ UpdateAllLifecyclePhasesForTest();
+ EXPECT_FALSE(target->GetLayoutObject()->ShouldCheckForPaintInvalidation());
+
+ // Removing a backdrop-filter should not need to check for paint invalidation
+ // because will-change: backdrop-filter is present.
+ target->removeAttribute(html_names::kStyleAttr);
+ GetDocument().UpdateStyleAndLayoutTree();
+ EXPECT_FALSE(target->GetLayoutObject()->ShouldCheckForPaintInvalidation());
+ UpdateAllLifecyclePhasesForTest();
+ EXPECT_FALSE(target->GetLayoutObject()->ShouldCheckForPaintInvalidation());
+}
+
+TEST_F(LayoutBoxModelObjectTest, ChangingWillChangeBackdropFilter) {
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ .willChange {
+ will-change: backdrop-filter;
+ }
+ #filter {
+ width: 100px;
+ height: 100px;
+ }
+ </style>
+ <div id="target"></div>
+ )HTML");
+
+ // Adding will-change: backdrop-filter should check for paint invalidation and
+ // create a PaintLayer.
+ auto* target = GetDocument().getElementById("target");
+ target->classList().Add("willChange");
+ GetDocument().UpdateStyleAndLayoutTree();
+ EXPECT_TRUE(target->GetLayoutObject()->ShouldCheckForPaintInvalidation());
+ EXPECT_TRUE(ToLayoutBoxModelObject(target->GetLayoutObject())->Layer());
+
+ // A lifecycle update should clear dirty bits.
+ UpdateAllLifecyclePhasesForTest();
+ EXPECT_FALSE(target->GetLayoutObject()->ShouldCheckForPaintInvalidation());
+ EXPECT_TRUE(ToLayoutBoxModelObject(target->GetLayoutObject())->Layer());
+
+ // Removing will-change: backdrop-filter should check for paint invalidation
+ // and remove the PaintLayer.
+ target->classList().Remove("willChange");
+ GetDocument().UpdateStyleAndLayoutTree();
+ EXPECT_TRUE(target->GetLayoutObject()->ShouldCheckForPaintInvalidation());
+ EXPECT_FALSE(ToLayoutBoxModelObject(target->GetLayoutObject())->Layer());
+}
+
TEST_F(LayoutBoxModelObjectTest, UpdateStackingContextForOption) {
// We do not create LayoutObject for option elements inside multiple selects
// on platforms where DelegatesMenuListRendering() returns true like Android.
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_button.cc b/chromium/third_party/blink/renderer/core/layout/layout_button.cc
index 28d3a96c0a5..29ddba1ca7b 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_button.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_button.cc
@@ -20,6 +20,8 @@
#include "third_party/blink/renderer/core/layout/layout_button.h"
+#include "third_party/blink/renderer/core/frame/web_feature.h"
+
namespace blink {
LayoutButton::LayoutButton(Element* element)
@@ -94,8 +96,12 @@ LayoutUnit LayoutButton::BaselinePosition(
return MarginRight() + Size().Width() - BorderLeft() - PaddingLeft() -
VerticalScrollbarWidth();
}
- return LayoutFlexibleBox::BaselinePosition(baseline, first_line, direction,
- line_position_mode);
+ LayoutUnit result_baseline = LayoutFlexibleBox::BaselinePosition(
+ baseline, first_line, direction, line_position_mode);
+ LayoutUnit correct_baseline = LayoutBlock::InlineBlockBaseline(direction);
+ if (correct_baseline != result_baseline)
+ UseCounter::Count(GetDocument(), WebFeature::kWrongBaselineOfButtonElement);
+ return result_baseline;
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_custom_scrollbar_part.cc b/chromium/third_party/blink/renderer/core/layout/layout_custom_scrollbar_part.cc
index e44c69567e7..2b76e6100ae 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_custom_scrollbar_part.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_custom_scrollbar_part.cc
@@ -232,6 +232,33 @@ void LayoutCustomScrollbarPart::StyleDidChange(StyleDifference diff,
SetFloating(false);
if (old_style && (diff.NeedsPaintInvalidation() || diff.NeedsLayout()))
SetNeedsPaintInvalidation();
+
+ RecordPercentLengthStats();
+}
+
+void LayoutCustomScrollbarPart::RecordPercentLengthStats() const {
+ if (!scrollbar_)
+ return;
+
+ auto feature = part_ == kScrollbarBGPart
+ ? WebFeature::kCustomScrollbarPercentThickness
+ : WebFeature::kCustomScrollbarPartPercentLength;
+ // The orientation that the width css property has effect for the part.
+ auto width_orientation =
+ part_ == kScrollbarBGPart ? kVerticalScrollbar : kHorizontalScrollbar;
+
+ // "==" below tests both direct percent length and percent used in calculated
+ // length.
+ if (scrollbar_->Orientation() == width_orientation) {
+ if (ComputeScrollbarWidth(0, Style()) ==
+ ComputeScrollbarWidth(LayoutUnit::NearlyMax().ToInt(), Style()))
+ return;
+ } else if (ComputeScrollbarHeight(0, Style()) ==
+ ComputeScrollbarHeight(LayoutUnit::NearlyMax().ToInt(), Style())) {
+ return;
+ }
+
+ UseCounter::Count(GetDocument(), feature);
}
void LayoutCustomScrollbarPart::ImageChanged(WrappedImagePtr image,
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_custom_scrollbar_part.h b/chromium/third_party/blink/renderer/core/layout/layout_custom_scrollbar_part.h
index dd1f0caf2cd..0832faddd20 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_custom_scrollbar_part.h
+++ b/chromium/third_party/blink/renderer/core/layout/layout_custom_scrollbar_part.h
@@ -105,6 +105,8 @@ class LayoutCustomScrollbarPart final : public LayoutBlock {
bool AllowsOverflowClip() const override { return false; }
+ void RecordPercentLengthStats() const;
+
UntracedMember<ScrollableArea> scrollable_area_;
UntracedMember<CustomScrollbar> scrollbar_;
ScrollbarPart part_;
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_details_marker.h b/chromium/third_party/blink/renderer/core/layout/layout_details_marker.h
index a2efcbffdfa..e39df8edb3a 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_details_marker.h
+++ b/chromium/third_party/blink/renderer/core/layout/layout_details_marker.h
@@ -33,6 +33,8 @@ class LayoutDetailsMarker final : public LayoutBlockFlow {
Orientation GetOrientation() const;
+ bool CreatesNewFormattingContext() const override { return true; }
+
const char* GetName() const override { return "LayoutDetailsMarker"; }
private:
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_fieldset.cc b/chromium/third_party/blink/renderer/core/layout/layout_fieldset.cc
index 7fba1ae5141..9110d093b72 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_fieldset.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_fieldset.cc
@@ -150,6 +150,10 @@ LayoutBox* LayoutFieldset::FindInFlowLegend(const LayoutBlock& fieldset) {
parent = To<LayoutBlock>(fieldset.FirstChild());
if (!parent)
return nullptr;
+ // If the anonymous fieldset wrapper is a multi-column, the rendered
+ // legend will be found inside the multi-column flow thread.
+ if (parent->FirstChild() && parent->FirstChild()->IsLayoutFlowThread())
+ parent = To<LayoutBlock>(parent->FirstChild());
}
}
for (LayoutObject* legend = parent->FirstChild(); legend;
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_flexible_box.cc b/chromium/third_party/blink/renderer/core/layout/layout_flexible_box.cc
index 0e51f4ec744..379e91b8265 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_flexible_box.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_flexible_box.cc
@@ -105,10 +105,12 @@ MinMaxSizes LayoutFlexibleBox::ComputeIntrinsicLogicalWidths() const {
// https://bugs.webkit.org/show_bug.cgi?id=116117 and
// https://crbug.com/240765.
float previous_max_content_flex_fraction = -1;
+ int number_of_items = 0;
for (LayoutBox* child = FirstChildBox(); child;
child = child->NextSiblingBox()) {
if (child->IsOutOfFlowPositioned())
continue;
+ number_of_items++;
LayoutUnit margin = MarginIntrinsicLogicalWidthForChild(*child);
@@ -143,6 +145,19 @@ MinMaxSizes LayoutFlexibleBox::ComputeIntrinsicLogicalWidths() const {
max_preferred_logical_width, child, previous_max_content_flex_fraction);
}
+ if (!IsColumnFlow() && number_of_items > 0) {
+ LayoutUnit gap_inline_size =
+ (number_of_items - 1) *
+ FlexLayoutAlgorithm::GapBetweenItems(
+ StyleRef(),
+ LogicalSize{ContentLogicalWidth(),
+ AvailableLogicalHeightForPercentageComputation()});
+ child_sizes.max_size += gap_inline_size;
+ if (!IsMultiline()) {
+ child_sizes.min_size += gap_inline_size;
+ }
+ }
+
child_sizes.max_size = std::max(child_sizes.min_size, child_sizes.max_size);
// Due to negative margins, it is possible that we calculated a negative
@@ -949,7 +964,11 @@ void LayoutFlexibleBox::LayoutFlexItems(bool relayout_children,
ChildLayoutType layout_type =
relayout_children ? kForceLayout : kLayoutIfNeeded;
const LayoutUnit line_break_length = MainAxisContentExtent(LayoutUnit::Max());
- FlexLayoutAlgorithm flex_algorithm(Style(), line_break_length);
+ FlexLayoutAlgorithm flex_algorithm(
+ Style(), line_break_length,
+ LogicalSize{ContentLogicalWidth(),
+ AvailableLogicalHeightForPercentageComputation()},
+ &GetDocument());
order_iterator_.First();
for (LayoutBox* child = order_iterator_.CurrentChild(); child;
child = order_iterator_.Next()) {
@@ -1000,7 +1019,11 @@ void LayoutFlexibleBox::LayoutFlexItems(bool relayout_children,
if (Size().Height() < min_height)
SetLogicalHeight(min_height);
}
-
+ if (!IsColumnFlow()) {
+ SetLogicalHeight(LogicalHeight() +
+ flex_algorithm.gap_between_lines_ *
+ (flex_algorithm.FlexLines().size() - 1));
+ }
UpdateLogicalHeight();
if (!HasOverrideLogicalHeight() && IsColumnFlow()) {
SetIntrinsicContentLogicalHeight(
@@ -1245,31 +1268,112 @@ void LayoutFlexibleBox::SetOverrideMainAxisContentSizeForChild(FlexItem& item) {
}
}
+namespace {
+
+LayoutUnit MainAxisStaticPositionCommon(const LayoutBox& child,
+ LayoutBox* parent,
+ LayoutUnit available_space) {
+ LayoutUnit offset = FlexLayoutAlgorithm::InitialContentPositionOffset(
+ parent->StyleRef(), available_space,
+ FlexLayoutAlgorithm::ResolvedJustifyContent(parent->StyleRef()), 1);
+ if (parent->StyleRef().ResolvedIsRowReverseFlexDirection() ||
+ parent->StyleRef().ResolvedIsColumnReverseFlexDirection())
+ offset = available_space - offset;
+ return offset;
+}
+
+LayoutUnit StaticMainAxisPositionForNGPositionedChild(const LayoutBox& child,
+ LayoutBox* parent) {
+ const LayoutUnit available_space =
+ FlexLayoutAlgorithm::IsHorizontalFlow(parent->StyleRef())
+ ? parent->ContentWidth() - child.Size().Width()
+ : parent->ContentHeight() - child.Size().Height();
+ return MainAxisStaticPositionCommon(child, parent, available_space);
+}
+
+LayoutUnit CrossAxisStaticPositionCommon(const LayoutBox& child,
+ LayoutBox* parent,
+ LayoutUnit available_space) {
+ return FlexItem::AlignmentOffset(
+ available_space,
+ FlexLayoutAlgorithm::AlignmentForChild(parent->StyleRef(),
+ child.StyleRef()),
+ LayoutUnit(), LayoutUnit(),
+ parent->StyleRef().FlexWrap() == EFlexWrap::kWrapReverse,
+ parent->StyleRef().IsDeprecatedWebkitBox());
+}
+
+LayoutUnit StaticCrossAxisPositionForNGPositionedChild(const LayoutBox& child,
+ LayoutBox* parent) {
+ const LayoutUnit available_space =
+ FlexLayoutAlgorithm::IsHorizontalFlow(parent->StyleRef())
+ ? parent->ContentHeight() - child.Size().Height()
+ : parent->ContentWidth() - child.Size().Width();
+ return CrossAxisStaticPositionCommon(child, parent, available_space);
+}
+
+LayoutUnit StaticInlinePositionForNGPositionedChild(const LayoutBox& child,
+ LayoutBlock* parent) {
+ const LayoutUnit start_offset = parent->StartOffsetForContent();
+ if (parent->StyleRef().IsDeprecatedWebkitBox())
+ return start_offset;
+ return start_offset +
+ (parent->StyleRef().ResolvedIsColumnFlexDirection()
+ ? StaticCrossAxisPositionForNGPositionedChild(child, parent)
+ : StaticMainAxisPositionForNGPositionedChild(child, parent));
+}
+
+LayoutUnit StaticBlockPositionForNGPositionedChild(const LayoutBox& child,
+ LayoutBlock* parent) {
+ return parent->BorderAndPaddingBefore() +
+ (parent->StyleRef().ResolvedIsColumnFlexDirection()
+ ? StaticMainAxisPositionForNGPositionedChild(child, parent)
+ : StaticCrossAxisPositionForNGPositionedChild(child, parent));
+}
+
+} // namespace
+
+bool LayoutFlexibleBox::SetStaticPositionForChildInFlexNGContainer(
+ LayoutBox& child,
+ LayoutBlock* parent) {
+ const ComputedStyle& style = parent->StyleRef();
+ bool position_changed = false;
+ PaintLayer* child_layer = child.Layer();
+ if (child.StyleRef().HasStaticInlinePosition(
+ style.IsHorizontalWritingMode())) {
+ LayoutUnit inline_position =
+ StaticInlinePositionForNGPositionedChild(child, parent);
+ if (child_layer->StaticInlinePosition() != inline_position) {
+ child_layer->SetStaticInlinePosition(inline_position);
+ position_changed = true;
+ }
+ }
+ if (child.StyleRef().HasStaticBlockPosition(
+ style.IsHorizontalWritingMode())) {
+ LayoutUnit block_position =
+ StaticBlockPositionForNGPositionedChild(child, parent);
+ if (child_layer->StaticBlockPosition() != block_position) {
+ child_layer->SetStaticBlockPosition(block_position);
+ position_changed = true;
+ }
+ }
+ return position_changed;
+}
+
LayoutUnit LayoutFlexibleBox::StaticMainAxisPositionForPositionedChild(
const LayoutBox& child) {
const LayoutUnit available_space =
MainAxisContentExtent(ContentLogicalHeight()) -
MainAxisExtentForChild(child);
- LayoutUnit offset = FlexLayoutAlgorithm::InitialContentPositionOffset(
- StyleRef(), available_space,
- FlexLayoutAlgorithm::ResolvedJustifyContent(StyleRef()), 1);
- if (StyleRef().ResolvedIsRowReverseFlexDirection() ||
- StyleRef().ResolvedIsColumnReverseFlexDirection())
- offset = available_space - offset;
- return offset;
+ return MainAxisStaticPositionCommon(child, this, available_space);
}
LayoutUnit LayoutFlexibleBox::StaticCrossAxisPositionForPositionedChild(
const LayoutBox& child) {
LayoutUnit available_space =
CrossAxisContentExtent() - CrossAxisExtentForChild(child);
- return FlexItem::AlignmentOffset(
- available_space,
- FlexLayoutAlgorithm::AlignmentForChild(StyleRef(), child.StyleRef()),
- LayoutUnit(), LayoutUnit(),
- StyleRef().FlexWrap() == EFlexWrap::kWrapReverse,
- StyleRef().IsDeprecatedWebkitBox());
+ return CrossAxisStaticPositionCommon(child, this, available_space);
}
LayoutUnit LayoutFlexibleBox::StaticInlinePositionForPositionedChild(
@@ -1536,8 +1640,10 @@ void LayoutFlexibleBox::AlignFlexLines(FlexLayoutAlgorithm& algorithm) {
Vector<FlexLine>& line_contexts = algorithm.FlexLines();
const StyleContentAlignmentData align_content =
FlexLayoutAlgorithm::ResolvedAlignContent(StyleRef());
- if (align_content.GetPosition() == ContentPosition::kFlexStart)
+ if (align_content.GetPosition() == ContentPosition::kFlexStart &&
+ algorithm.gap_between_lines_ == 0) {
return;
+ }
if (IsMultiline() && !line_contexts.IsEmpty()) {
UseCounter::Count(GetDocument(),
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_flexible_box.h b/chromium/third_party/blink/renderer/core/layout/layout_flexible_box.h
index 3b3d34ea1ca..493d739bb4e 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_flexible_box.h
+++ b/chromium/third_party/blink/renderer/core/layout/layout_flexible_box.h
@@ -98,6 +98,8 @@ class CORE_EXPORT LayoutFlexibleBox : public LayoutBlock {
// Returns true if the position changed. In that case, the child will have to
// be laid out again.
bool SetStaticPositionForPositionedLayout(LayoutBox& child);
+ static bool SetStaticPositionForChildInFlexNGContainer(LayoutBox& child,
+ LayoutBlock* parent);
LayoutUnit CrossAxisContentExtent() const;
protected:
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_flexible_box_test.cc b/chromium/third_party/blink/renderer/core/layout/layout_flexible_box_test.cc
index 07853d0ae57..ffd365643b8 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_flexible_box_test.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_flexible_box_test.cc
@@ -509,4 +509,62 @@ TEST_P(LayoutFlexibleBoxTest, ResizedFlexChildRequiresVisualOverflowRecalc) {
PhysicalRect(0, 0, 105, 960));
}
+TEST_P(LayoutFlexibleBoxTest, PercentDefiniteGapUseCounter) {
+ SetBodyInnerHTML(CommonStyle() + R"HTML(
+ <div id="flex-box" style="gap: 20%;"></div>
+ )HTML");
+ RunDocumentLifecycle();
+
+ EXPECT_TRUE(GetDocument().IsUseCounted(WebFeature::kFlexGapPositive));
+ EXPECT_TRUE(GetDocument().IsUseCounted(WebFeature::kFlexGapSpecified));
+ EXPECT_TRUE(GetDocument().IsUseCounted(WebFeature::kFlexRowGapPercent));
+ EXPECT_FALSE(
+ GetDocument().IsUseCounted(WebFeature::kFlexRowGapPercentIndefinite));
+}
+
+TEST_P(LayoutFlexibleBoxTest, PercentIndefiniteGapUseCounter) {
+ SetBodyInnerHTML(CommonStyle() + R"HTML(
+ <div style="display: flex; row-gap: 20%;"></div>
+ )HTML");
+ RunDocumentLifecycle();
+
+ EXPECT_FALSE(GetDocument().IsUseCounted(WebFeature::kFlexGapPositive));
+ EXPECT_TRUE(GetDocument().IsUseCounted(WebFeature::kFlexGapSpecified));
+ EXPECT_TRUE(GetDocument().IsUseCounted(WebFeature::kFlexRowGapPercent));
+ EXPECT_TRUE(
+ GetDocument().IsUseCounted(WebFeature::kFlexRowGapPercentIndefinite));
+}
+
+TEST_P(LayoutFlexibleBoxTest, ZeroGapUseCounter) {
+ SetBodyInnerHTML(CommonStyle() + R"HTML(
+ <div style="display: flex; gap: 0;"></div>
+ )HTML");
+ RunDocumentLifecycle();
+
+ EXPECT_FALSE(GetDocument().IsUseCounted(WebFeature::kFlexGapPositive));
+ EXPECT_TRUE(GetDocument().IsUseCounted(WebFeature::kFlexGapSpecified));
+ EXPECT_FALSE(GetDocument().IsUseCounted(WebFeature::kFlexRowGapPercent));
+ EXPECT_FALSE(
+ GetDocument().IsUseCounted(WebFeature::kFlexRowGapPercentIndefinite));
+}
+
+TEST_P(LayoutFlexibleBoxTest, NormalGapUseCounter) {
+ // 'normal' is the initial value. It resolves to non-zero for multi-col but 0
+ // for flex.
+ SetBodyInnerHTML(CommonStyle() + R"HTML(
+ <div style="display: flex; gap: normal"></div>
+ <div style="display: flex; gap: auto"></div>
+ <div style="display: flex; gap: initial"></div>
+ <div style="display: flex; gap: -10px"></div>
+ <div style="display: flex; gap: 1hz"></div>
+ )HTML");
+ RunDocumentLifecycle();
+
+ EXPECT_FALSE(GetDocument().IsUseCounted(WebFeature::kFlexGapPositive));
+ EXPECT_FALSE(GetDocument().IsUseCounted(WebFeature::kFlexGapSpecified));
+ EXPECT_FALSE(GetDocument().IsUseCounted(WebFeature::kFlexRowGapPercent));
+ EXPECT_FALSE(
+ GetDocument().IsUseCounted(WebFeature::kFlexRowGapPercentIndefinite));
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_flow_thread.cc b/chromium/third_party/blink/renderer/core/layout/layout_flow_thread.cc
index 118511adc7a..0fbfc5b24d9 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_flow_thread.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_flow_thread.cc
@@ -34,10 +34,11 @@
namespace blink {
-LayoutFlowThread::LayoutFlowThread()
+LayoutFlowThread::LayoutFlowThread(bool needs_paint_layer)
: LayoutBlockFlow(nullptr),
column_sets_invalidated_(false),
- page_logical_size_changed_(false) {}
+ page_logical_size_changed_(false),
+ needs_paint_layer_(needs_paint_layer) {}
LayoutFlowThread* LayoutFlowThread::LocateFlowThreadContainingBlockOf(
const LayoutObject& descendant,
@@ -115,6 +116,15 @@ void LayoutFlowThread::UpdateLayout() {
page_logical_size_changed_ = false;
}
+PaintLayerType LayoutFlowThread::LayerTypeRequired() const {
+ if (!needs_paint_layer_)
+ return kNoPaintLayer;
+ // Always create a Layer for the LayoutFlowThread so that we can easily avoid
+ // drawing the children directly. We need this for legacy painting (but not
+ // for NG).
+ return kNormalPaintLayer;
+}
+
void LayoutFlowThread::ComputeLogicalHeight(
LayoutUnit,
LayoutUnit logical_top,
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_flow_thread.h b/chromium/third_party/blink/renderer/core/layout/layout_flow_thread.h
index d43f6eb612d..3ffeb2935eb 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_flow_thread.h
+++ b/chromium/third_party/blink/renderer/core/layout/layout_flow_thread.h
@@ -65,7 +65,7 @@ class MultiColumnLayoutState {
// LayoutMultiColumnSet will actually be a viewPort of the LayoutFlowThread.
class CORE_EXPORT LayoutFlowThread : public LayoutBlockFlow {
public:
- LayoutFlowThread();
+ explicit LayoutFlowThread(bool needs_paint_layer);
~LayoutFlowThread() override = default;
bool IsLayoutFlowThread() const final { return true; }
@@ -101,9 +101,7 @@ class CORE_EXPORT LayoutFlowThread : public LayoutBlockFlow {
void UpdateLayout() override;
- // Always create a Layer for the LayoutFlowThread so that we
- // can easily avoid drawing the children directly.
- PaintLayerType LayerTypeRequired() const final { return kNormalPaintLayer; }
+ PaintLayerType LayerTypeRequired() const final;
bool NeedsPreferredWidthsRecalculation() const final { return true; }
@@ -229,6 +227,7 @@ class CORE_EXPORT LayoutFlowThread : public LayoutBlockFlow {
bool column_sets_invalidated_ : 1;
bool page_logical_size_changed_ : 1;
+ bool needs_paint_layer_ : 1;
};
DEFINE_LAYOUT_OBJECT_TYPE_CASTS(LayoutFlowThread, IsLayoutFlowThread());
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_frame_set.h b/chromium/third_party/blink/renderer/core/layout/layout_frame_set.h
index 6c9aae4e7c9..c9c26c7857e 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_frame_set.h
+++ b/chromium/third_party/blink/renderer/core/layout/layout_frame_set.h
@@ -135,7 +135,6 @@ class LayoutFrameSet final : public LayoutBox {
MinMaxSizes PreferredLogicalWidths() const override { return MinMaxSizes(); }
MinMaxSizes ComputeIntrinsicLogicalWidths() const final {
- NOTREACHED();
return MinMaxSizes();
}
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_grid.cc b/chromium/third_party/blink/renderer/core/layout/layout_grid.cc
index 1b03b70feb3..6e500101073 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_grid.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_grid.cc
@@ -29,6 +29,7 @@
#include <memory>
#include <utility>
+#include "third_party/blink/public/mojom/web_feature/web_feature.mojom-blink.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
#include "third_party/blink/renderer/core/layout/grid_layout_utils.h"
#include "third_party/blink/renderer/core/layout/layout_state.h"
@@ -377,6 +378,15 @@ void LayoutGrid::UpdateBlockLayout(bool relayout_children) {
LayoutGridItems();
track_sizing_algorithm_.Reset();
+ if (NumTracks(kForRows, *grid_) > 1u && !StyleRef().RowGap().IsNormal() &&
+ StyleRef().RowGap().GetLength().IsPercentOrCalc()) {
+ UseCounter::Count(GetDocument(), WebFeature::kGridRowGapPercent);
+ if (!CachedHasDefiniteLogicalHeight()) {
+ UseCounter::Count(GetDocument(),
+ WebFeature::kGridRowGapPercentIndefinite);
+ }
+ }
+
if (Size() != previous_size)
relayout_children = true;
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_grid_test.cc b/chromium/third_party/blink/renderer/core/layout/layout_grid_test.cc
new file mode 100644
index 00000000000..69120c925bb
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/layout/layout_grid_test.cc
@@ -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.
+
+#include "third_party/blink/renderer/core/testing/core_unit_test_helper.h"
+
+namespace blink {
+
+class LayoutGridTest : public RenderingTest {};
+
+TEST_F(LayoutGridTest, RowGapUseCounter) {
+ SetBodyInnerHTML(R"HTML(
+ <div style="display: grid; gap: 20%;">
+ <div></div>
+ <div></div>
+ </div>
+ )HTML");
+ RunDocumentLifecycle();
+
+ EXPECT_TRUE(GetDocument().IsUseCounted(WebFeature::kGridRowGapPercent));
+ EXPECT_TRUE(
+ GetDocument().IsUseCounted(WebFeature::kGridRowGapPercentIndefinite));
+}
+
+TEST_F(LayoutGridTest, RowGapUseCounterOneTrack) {
+ SetBodyInnerHTML(R"HTML(
+ <div style="display: grid; gap: 20%;">
+ <div></div>
+ </div>
+ )HTML");
+ RunDocumentLifecycle();
+
+ EXPECT_FALSE(GetDocument().IsUseCounted(WebFeature::kGridRowGapPercent));
+ EXPECT_FALSE(
+ GetDocument().IsUseCounted(WebFeature::kGridRowGapPercentIndefinite));
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_inline.cc b/chromium/third_party/blink/renderer/core/layout/layout_inline.cc
index a7dd0e57408..d55ad530de2 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_inline.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_inline.cc
@@ -136,10 +136,15 @@ void LayoutInline::WillBeDestroyed() {
box->Remove();
}
} else {
- if (NGPaintFragment* first_inline_fragment = FirstInlineFragment())
- first_inline_fragment->LayoutObjectWillBeDestroyed();
if (Parent())
Parent()->DirtyLinesFromChangedChild(this);
+ if (!RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()) {
+ if (NGPaintFragment* first_inline_fragment = FirstInlineFragment())
+ first_inline_fragment->LayoutObjectWillBeDestroyed();
+ } else if (FirstInlineFragmentItemIndex()) {
+ NGFragmentItems::LayoutObjectWillBeDestroyed(*this);
+ ClearFirstInlineFragmentItemIndex();
+ }
}
}
@@ -155,9 +160,7 @@ void LayoutInline::DeleteLineBoxes() {
void LayoutInline::SetFirstInlineFragment(NGPaintFragment* fragment) {
CHECK(IsInLayoutNGInlineFormattingContext()) << *this;
- // TODO(yosin): Once we remove |NGPaintFragment|, we should get rid of
- // |!fragment|.
- DCHECK(!fragment || !RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled());
+ DCHECK(!RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled());
first_paint_fragment_ = fragment;
}
@@ -171,9 +174,7 @@ void LayoutInline::SetFirstInlineFragmentItemIndex(wtf_size_t index) {
CHECK(IsInLayoutNGInlineFormattingContext()) << *this;
DCHECK(RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled());
DCHECK_NE(index, 0u);
- // TDOO(yosin): Once we update all |LayoutObject::FirstInlineFragment()|,
- // we should enable below.
- // first_fragment_item_index_ = index;
+ first_fragment_item_index_ = index;
}
bool LayoutInline::HasInlineFragments() const {
@@ -181,18 +182,26 @@ bool LayoutInline::HasInlineFragments() const {
return FirstLineBox();
if (!RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled())
return first_paint_fragment_;
- // TODO(yosin): We should use |first_fragment_item_index_|.
- NGInlineCursor cursor;
- cursor.MoveTo(*this);
- return cursor;
+ return first_fragment_item_index_;
}
void LayoutInline::InLayoutNGInlineFormattingContextWillChange(bool new_value) {
- DeleteLineBoxes();
+ if (IsInLayoutNGInlineFormattingContext()) {
+ if (!RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()) {
+ SetFirstInlineFragment(nullptr);
+ } else {
+ ClearFirstInlineFragmentItemIndex();
+ }
+ } else {
+ DeleteLineBoxes();
+ }
// Because |first_paint_fragment_| and |line_boxes_| are union, when one is
// deleted, the other should be initialized to nullptr.
- DCHECK(new_value ? !first_paint_fragment_ : !line_boxes_.First());
+ DCHECK(new_value ? (RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()
+ ? !first_fragment_item_index_
+ : !first_paint_fragment_)
+ : !line_boxes_.First());
}
LayoutInline* LayoutInline::InlineElementContinuation() const {
@@ -810,7 +819,7 @@ void LayoutInline::CollectLineBoxRects(
return;
}
NGInlineCursor cursor;
- cursor.MoveTo(*this);
+ cursor.MoveToIncludingCulledInline(*this);
for (; cursor; cursor.MoveToNextForSameLayoutObject())
yield(cursor.Current().RectInContainerBlock());
return;
@@ -957,7 +966,7 @@ base::Optional<PhysicalOffset> LayoutInline::FirstLineBoxTopLeftInternal()
const {
if (IsInLayoutNGInlineFormattingContext()) {
NGInlineCursor cursor;
- cursor.MoveTo(*this);
+ cursor.MoveToIncludingCulledInline(*this);
if (!cursor)
return base::nullopt;
return cursor.Current().OffsetInContainerBlock();
@@ -1092,12 +1101,11 @@ bool LayoutInline::NodeAtPoint(HitTestResult& result,
hit_test_action);
}
-bool LayoutInline::HitTestCulledInline(
- HitTestResult& result,
- const HitTestLocation& hit_test_location,
- const PhysicalOffset& accumulated_offset,
- const NGPaintFragment* container_fragment) {
- DCHECK(container_fragment || !AlwaysCreateLineBoxes());
+bool LayoutInline::HitTestCulledInline(HitTestResult& result,
+ const HitTestLocation& hit_test_location,
+ const PhysicalOffset& accumulated_offset,
+ const NGInlineCursor* parent_cursor) {
+ DCHECK(parent_cursor || !AlwaysCreateLineBoxes());
if (!VisibleToHitTestRequest(result.GetHitTestRequest()))
return false;
@@ -1115,14 +1123,13 @@ bool LayoutInline::HitTestCulledInline(
// NG generates purely physical rectangles here, while legacy sets the block
// offset on the rectangles relatively to the block-start. NG is doing the
// right thing. Legacy is wrong.
- if (container_fragment) {
- DCHECK(ContainingNGBlockFlow());
- DCHECK(container_fragment->IsDescendantOfNotSelf(
- *ContainingNGBlockFlow()->PaintFragment()));
- DCHECK(container_fragment->PhysicalFragment().IsInline() ||
- container_fragment->PhysicalFragment().IsLineBox());
- NGInlineCursor cursor(*container_fragment);
- for (cursor.MoveTo(*this); cursor; cursor.MoveToNextForSameLayoutObject())
+ if (parent_cursor) {
+ // Iterate fragments for |this|, including culled inline, but only that are
+ // descendants of |parent_cursor|.
+ DCHECK(IsDescendantOf(parent_cursor->GetLayoutBlockFlow()));
+ NGInlineCursor cursor(*parent_cursor);
+ cursor.MoveToIncludingCulledInline(*this);
+ for (; cursor; cursor.MoveToNextForSameLayoutObject())
yield(cursor.Current().RectInContainerBlock());
} else {
DCHECK(!ContainingNGBlockFlow());
@@ -1172,7 +1179,7 @@ PositionWithAffinity LayoutInline::PositionForPoint(
PhysicalRect LayoutInline::PhysicalLinesBoundingBox() const {
if (IsInLayoutNGInlineFormattingContext()) {
NGInlineCursor cursor;
- cursor.MoveTo(*this);
+ cursor.MoveToIncludingCulledInline(*this);
PhysicalRect bounding_box;
for (; cursor; cursor.MoveToNextForSameLayoutObject())
bounding_box.UniteIfNonZero(cursor.Current().RectInContainerBlock());
@@ -1321,7 +1328,7 @@ PhysicalRect LayoutInline::LinesVisualOverflowBoundingBox() const {
if (IsInLayoutNGInlineFormattingContext()) {
PhysicalRect result;
NGInlineCursor cursor;
- cursor.MoveTo(*this);
+ cursor.MoveToIncludingCulledInline(*this);
for (; cursor; cursor.MoveToNextForSameLayoutObject()) {
PhysicalRect child_rect = cursor.Current().InkOverflow();
child_rect.offset += cursor.Current().OffsetInContainerBlock();
@@ -1585,11 +1592,14 @@ void LayoutInline::DirtyLinesFromChangedChild(
LayoutObject* child,
MarkingBehavior marking_behavior) {
if (IsInLayoutNGInlineFormattingContext()) {
- // TODO(yosin): We should move |SetAncestorLineBoxDirty()| into
- // |DirtyLinesFromChangedChild()| like legacy layout.
+ if (UNLIKELY(RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled())) {
+ if (const LayoutBlockFlow* container = FragmentItemsContainer()) {
+ if (const NGFragmentItems* items = container->FragmentItems())
+ items->DirtyLinesFromChangedChild(child);
+ }
+ return;
+ }
SetAncestorLineBoxDirty();
- if (child->IsInLayoutNGInlineFormattingContext())
- NGPaintFragment::DirtyLinesFromChangedChild(child);
return;
}
MutableLineBoxes()->DirtyLinesFromChangedChild(
@@ -1634,10 +1644,10 @@ PhysicalOffset LayoutInline::OffsetForInFlowPositionedInline(
// but LayoutNG has fixed the issue. This function seems to always return
// zero in LayoutNG. We should probably remove this function for LayoutNG.
- DCHECK(IsInFlowPositioned() || StyleRef().HasFilter() ||
- StyleRef().HasBackdropFilter());
- if (!IsInFlowPositioned() && !StyleRef().HasFilter() &&
- !StyleRef().HasBackdropFilter()) {
+ DCHECK(IsInFlowPositioned() || StyleRef().HasNonInitialFilter() ||
+ StyleRef().HasNonInitialBackdropFilter());
+ if (!IsInFlowPositioned() && !StyleRef().HasNonInitialFilter() &&
+ !StyleRef().HasNonInitialBackdropFilter()) {
DCHECK(CreatesGroup())
<< "Inlines with filters or backdrop-filters should create a group";
return PhysicalOffset();
@@ -1789,8 +1799,7 @@ void LayoutInline::InvalidateDisplayItemClients(
}
if (IsInLayoutNGInlineFormattingContext()) {
- if (!ShouldCreateBoxFragment() &&
- !RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled())
+ if (!ShouldCreateBoxFragment())
return;
NGInlineCursor cursor;
for (cursor.MoveTo(*this); cursor; cursor.MoveToNextForSameLayoutObject()) {
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_inline.h b/chromium/third_party/blink/renderer/core/layout/layout_inline.h
index 448bf29cadd..4e1ae54ff14 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_inline.h
+++ b/chromium/third_party/blink/renderer/core/layout/layout_inline.h
@@ -34,7 +34,9 @@
namespace blink {
class LayoutBlockFlow;
+class NGInlineCursor;
class NGPaintFragment;
+
// LayoutInline is the LayoutObject associated with display: inline.
// This is called an "inline box" in CSS 2.1.
// http://www.w3.org/TR/CSS2/visuren.html#inline-boxes
@@ -235,7 +237,7 @@ class CORE_EXPORT LayoutInline : public LayoutBoxModelObject {
bool HitTestCulledInline(HitTestResult&,
const HitTestLocation&,
const PhysicalOffset& accumulated_offset,
- const NGPaintFragment* parent_fragment = nullptr);
+ const NGInlineCursor* parent_cursor = nullptr);
PhysicalOffset FirstLineBoxTopLeft() const {
return FirstLineBoxTopLeftInternal().value_or(PhysicalOffset());
@@ -429,6 +431,7 @@ inline NGPaintFragment* LayoutInline::FirstInlineFragment() const {
return nullptr;
// TODO(yosin): Once we replace all usage of |FirstInlineFragment()| to
// |NGInlineCursor|, we should change this to |DCHECK()|.
+ DCHECK(!RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled());
if (RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled())
return nullptr;
return first_paint_fragment_;
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_inline_test.cc b/chromium/third_party/blink/renderer/core/layout/layout_inline_test.cc
index 2c8922ef27c..f2af84a79e1 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_inline_test.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_inline_test.cc
@@ -151,8 +151,9 @@ TEST_F(LayoutInlineTest, RegionHitTest) {
const auto* div = To<LayoutBlockFlow>(lots_of_boxes->Parent());
for (const NGPaintFragment* line : div->PaintFragment()->Children()) {
DCHECK(line->PhysicalFragment().IsLineBox());
- bool hit_outcome = lots_of_boxes->HitTestCulledInline(hit_result, location,
- hit_offset, line);
+ NGInlineCursor line_cursor(*line);
+ bool hit_outcome = lots_of_boxes->HitTestCulledInline(
+ hit_result, location, hit_offset, &line_cursor);
EXPECT_FALSE(hit_outcome);
}
// Make sure that the inline is hit
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_multi_column_flow_thread.cc b/chromium/third_party/blink/renderer/core/layout/layout_multi_column_flow_thread.cc
index 2c6e4fc788e..19754331b32 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_multi_column_flow_thread.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_multi_column_flow_thread.cc
@@ -39,8 +39,9 @@ const LayoutBox* LayoutMultiColumnFlowThread::style_changed_box_;
bool LayoutMultiColumnFlowThread::could_contain_spanners_;
bool LayoutMultiColumnFlowThread::toggle_spanners_if_needed_;
-LayoutMultiColumnFlowThread::LayoutMultiColumnFlowThread()
- : last_set_worked_on_(nullptr),
+LayoutMultiColumnFlowThread::LayoutMultiColumnFlowThread(bool needs_paint_layer)
+ : LayoutFlowThread(needs_paint_layer),
+ last_set_worked_on_(nullptr),
column_count_(1),
column_heights_changed_(false),
is_being_evacuated_(false) {
@@ -51,9 +52,10 @@ LayoutMultiColumnFlowThread::~LayoutMultiColumnFlowThread() = default;
LayoutMultiColumnFlowThread* LayoutMultiColumnFlowThread::CreateAnonymous(
Document& document,
- const ComputedStyle& parent_style) {
+ const ComputedStyle& parent_style,
+ bool needs_paint_layer) {
LayoutMultiColumnFlowThread* layout_object =
- new LayoutMultiColumnFlowThread();
+ new LayoutMultiColumnFlowThread(needs_paint_layer);
layout_object->SetDocumentForAnonymous(&document);
layout_object->SetStyle(ComputedStyle::CreateAnonymousStyleWithDisplay(
parent_style, EDisplay::kBlock));
@@ -1173,10 +1175,7 @@ static inline bool NeedsToReinsertIntoFlowThread(
if (old_style.CanContainFixedPositionObjects(false) !=
new_style.CanContainFixedPositionObjects(false))
return true;
- return (old_style.HasInFlowPosition() &&
- new_style.GetPosition() == EPosition::kStatic) ||
- (new_style.HasInFlowPosition() &&
- old_style.GetPosition() == EPosition::kStatic);
+ return old_style.GetPosition() != new_style.GetPosition();
}
static inline bool NeedsToRemoveFromFlowThread(const ComputedStyle& old_style,
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_multi_column_flow_thread.h b/chromium/third_party/blink/renderer/core/layout/layout_multi_column_flow_thread.h
index e09739b2a21..7a61cd11d7b 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_multi_column_flow_thread.h
+++ b/chromium/third_party/blink/renderer/core/layout/layout_multi_column_flow_thread.h
@@ -148,7 +148,8 @@ class CORE_EXPORT LayoutMultiColumnFlowThread final
static LayoutMultiColumnFlowThread* CreateAnonymous(
Document&,
- const ComputedStyle& parent_style);
+ const ComputedStyle& parent_style,
+ bool needs_paint_layer);
bool IsLayoutMultiColumnFlowThread() const final { return true; }
@@ -291,7 +292,7 @@ class CORE_EXPORT LayoutMultiColumnFlowThread final
const char* GetName() const override { return "LayoutMultiColumnFlowThread"; }
private:
- LayoutMultiColumnFlowThread();
+ explicit LayoutMultiColumnFlowThread(bool needs_paint_layer);
void UpdateLayout() override;
void CalculateColumnHeightAvailable();
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_object.cc b/chromium/third_party/blink/renderer/core/layout/layout_object.cc
index 9d6d6f718aa..688121f8ab6 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_object.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_object.cc
@@ -197,7 +197,7 @@ void* LayoutObject::operator new(size_t sz) {
void LayoutObject::operator delete(void* ptr) {
DCHECK(IsMainThread());
- base::PartitionFree(ptr);
+ WTF::Partitions::LayoutPartition()->Free(ptr);
}
LayoutObject* LayoutObject::CreateObject(Element* element,
@@ -242,20 +242,26 @@ LayoutObject* LayoutObject::CreateObject(Element* element,
case EDisplay::kFlowRoot:
case EDisplay::kInlineBlock:
case EDisplay::kListItem:
- case EDisplay::kMath:
- case EDisplay::kInlineMath:
return LayoutObjectFactory::CreateBlockFlow(*element, style, legacy);
case EDisplay::kTable:
case EDisplay::kInlineTable:
+ UseCounter::Count(element->GetDocument(),
+ WebFeature::kLegacyLayoutByTable);
return new LayoutTable(element);
case EDisplay::kTableRowGroup:
case EDisplay::kTableHeaderGroup:
case EDisplay::kTableFooterGroup:
+ UseCounter::Count(element->GetDocument(),
+ WebFeature::kLegacyLayoutByTable);
return new LayoutTableSection(element);
case EDisplay::kTableRow:
+ UseCounter::Count(element->GetDocument(),
+ WebFeature::kLegacyLayoutByTable);
return new LayoutTableRow(element);
case EDisplay::kTableColumnGroup:
case EDisplay::kTableColumn:
+ UseCounter::Count(element->GetDocument(),
+ WebFeature::kLegacyLayoutByTable);
return new LayoutTableCol(element);
case EDisplay::kTableCell:
return LayoutObjectFactory::CreateTableCell(*element, style, legacy);
@@ -268,8 +274,13 @@ LayoutObject* LayoutObject::CreateObject(Element* element,
return LayoutObjectFactory::CreateBlockForLineClamp(*element, style,
legacy);
}
- if (style.IsDeprecatedFlexboxUsingFlexLayout())
+ if (style.IsDeprecatedFlexboxUsingFlexLayout()) {
+ UseCounter::Count(element->GetDocument(),
+ WebFeature::kLegacyLayoutByFlexBox);
return new LayoutFlexibleBox(element);
+ }
+ UseCounter::Count(element->GetDocument(),
+ WebFeature::kLegacyLayoutByDeprecatedFlexBox);
return new LayoutDeprecatedFlexibleBox(element);
case EDisplay::kFlex:
case EDisplay::kInlineFlex:
@@ -278,7 +289,10 @@ LayoutObject* LayoutObject::CreateObject(Element* element,
case EDisplay::kGrid:
case EDisplay::kInlineGrid:
UseCounter::Count(element->GetDocument(), WebFeature::kCSSGridLayout);
- return new LayoutGrid(element);
+ return LayoutObjectFactory::CreateGrid(*element, style, legacy);
+ case EDisplay::kMath:
+ case EDisplay::kInlineMath:
+ return LayoutObjectFactory::CreateMath(*element, style, legacy);
case EDisplay::kLayoutCustom:
case EDisplay::kInlineLayoutCustom:
DCHECK(RuntimeEnabledFeatures::LayoutNGEnabled());
@@ -332,6 +346,14 @@ bool LayoutObject::IsHR() const {
return IsA<HTMLHRElement>(GetNode());
}
+bool LayoutObject::IsStyleGenerated() const {
+ if (const auto* layout_text_fragment = ToLayoutTextFragmentOrNull(this))
+ return !layout_text_fragment->AssociatedTextNode();
+
+ const Node* node = GetNode();
+ return !node || node->IsPseudoElement();
+}
+
void LayoutObject::SetIsInsideFlowThreadIncludingDescendants(
bool inside_flow_thread) {
LayoutObject* next;
@@ -354,9 +376,9 @@ bool LayoutObject::RequiresAnonymousTableWrappers(
// CSS 2.1 Tables: 17.2.1 Anonymous table objects
// http://www.w3.org/TR/CSS21/tables.html#anonymous-boxes
if (new_child->IsLayoutTableCol()) {
- const LayoutTableCol* new_table_column = ToLayoutTableCol(new_child);
bool is_column_in_column_group =
- new_table_column->IsTableColumn() && IsLayoutTableCol();
+ new_child->StyleRef().Display() == EDisplay::kTableColumn &&
+ IsLayoutTableCol();
return !IsTable() && !is_column_in_column_group;
}
if (new_child->IsTableCaption())
@@ -378,7 +400,9 @@ void LayoutObject::AssertClearedPaintInvalidationFlags() const {
return;
// NG text objects are exempt, as pre-paint walking doesn't visit those with
// no paint effects (only white-space, for instance).
- if (IsText() && IsLayoutNGObject())
+ if ((IsText() && IsLayoutNGObject()) ||
+ // and culled inline boxes too.
+ (IsInLayoutNGInlineFormattingContext() && IsLayoutInline()))
return;
ShowLayoutTreeForThis();
NOTREACHED();
@@ -431,6 +455,19 @@ void LayoutObject::RemoveChild(LayoutObject* old_child) {
children->RemoveChildNode(this, old_child);
}
+void LayoutObject::NotifyPriorityScrollAnchorStatusChanged() {
+ if (!Parent())
+ return;
+ for (auto* layer = Parent()->EnclosingLayer(); layer;
+ layer = layer->Parent()) {
+ if (PaintLayerScrollableArea* scrollable_area =
+ layer->GetScrollableArea()) {
+ DCHECK(scrollable_area->GetScrollAnchor());
+ scrollable_area->GetScrollAnchor()->ClearSelf();
+ }
+ }
+}
+
void LayoutObject::RegisterSubtreeChangeListenerOnDescendants(bool value) {
// If we're set to the same value then we're done as that means it's
// set down the tree that way already.
@@ -526,7 +563,10 @@ bool LayoutObject::IsRenderedLegendInternal() const {
const auto* parent = Parent();
if (RuntimeEnabledFeatures::LayoutNGFieldsetEnabled()) {
// If there is a rendered legend, it will be found inside the anonymous
- // fieldset wrapper.
+ // fieldset wrapper. If the anonymous fieldset wrapper is a multi-column,
+ // the rendered legend will be found inside the multi-column flow thread.
+ if (parent->IsLayoutFlowThread())
+ parent = parent->Parent();
if (parent->IsAnonymous() && parent->Parent()->IsLayoutNGFieldset())
parent = parent->Parent();
}
@@ -818,6 +858,15 @@ LayoutBlockFlow* LayoutObject::RootInlineFormattingContext() const {
return nullptr;
}
+LayoutBlockFlow* LayoutObject::FragmentItemsContainer() const {
+ DCHECK(IsInline());
+ for (LayoutObject* parent = Parent(); parent; parent = parent->Parent()) {
+ if (auto* block_flow = DynamicTo<LayoutBlockFlow>(parent))
+ return block_flow;
+ }
+ return nullptr;
+}
+
LayoutBlockFlow* LayoutObject::ContainingNGBlockFlow() const {
DCHECK(IsInline());
if (!RuntimeEnabledFeatures::LayoutNGEnabled())
@@ -931,20 +980,6 @@ static inline bool ObjectIsRelayoutBoundary(const LayoutObject* object) {
if (!style->Width().IsFixed() || !style->Height().IsFixed())
return false;
- if (object->IsTextControl())
- return true;
-
- if (is_svg_root)
- return true;
-
- if (!object->HasOverflowClip())
- return false;
-
- // Scrollbar parts can be removed during layout. Avoid the complexity of
- // having to deal with that.
- if (object->IsLayoutCustomScrollbarPart())
- return false;
-
if (const LayoutBox* layout_box = ToLayoutBoxOrNull(object)) {
// In general we can't relayout a flex item independently of its container;
// not only is the result incorrect due to the override size that's set, it
@@ -961,6 +996,20 @@ static inline bool ObjectIsRelayoutBoundary(const LayoutObject* object) {
return false;
}
+ if (object->IsTextControl())
+ return true;
+
+ if (is_svg_root)
+ return true;
+
+ if (!object->HasOverflowClip())
+ return false;
+
+ // Scrollbar parts can be removed during layout. Avoid the complexity of
+ // having to deal with that.
+ if (object->IsLayoutCustomScrollbarPart())
+ return false;
+
// Inside multicol it's generally problematic to allow relayout roots. The
// multicol container itself may be scheduled for relayout as well (due to
// other changes that may have happened since the previous layout pass),
@@ -1162,6 +1211,8 @@ void LayoutObject::CheckBlockPositionedObjectsNeedLayout() {
void LayoutObject::SetIntrinsicLogicalWidthsDirty(
MarkingBehavior mark_parents) {
bitfields_.SetIntrinsicLogicalWidthsDirty(true);
+ bitfields_.SetIntrinsicLogicalWidthsDependsOnPercentageBlockSize(true);
+ bitfields_.SetIntrinsicLogicalWidthsChildDependsOnPercentageBlockSize(true);
if (mark_parents == kMarkContainerChain &&
(IsText() || !StyleRef().HasOutOfFlowPosition()))
InvalidateContainerIntrinsicLogicalWidths();
@@ -1171,9 +1222,18 @@ void LayoutObject::ClearIntrinsicLogicalWidthsDirty() {
bitfields_.SetIntrinsicLogicalWidthsDirty(false);
}
+bool LayoutObject::IsFontFallbackValid() const {
+ return StyleRef().GetFont().IsFallbackValid() &&
+ FirstLineStyle()->GetFont().IsFallbackValid();
+}
+
void LayoutObject::InvalidateSubtreeLayoutForFontUpdates() {
- SetNeedsLayoutAndIntrinsicWidthsRecalcAndFullPaintInvalidation(
- layout_invalidation_reason::kFontsChanged);
+ if (!RuntimeEnabledFeatures::
+ CSSReducedFontLoadingLayoutInvalidationsEnabled() ||
+ !IsFontFallbackValid()) {
+ SetNeedsLayoutAndIntrinsicWidthsRecalcAndFullPaintInvalidation(
+ layout_invalidation_reason::kFontsChanged);
+ }
for (LayoutObject* child = SlowFirstChild(); child;
child = child->NextSibling()) {
child->InvalidateSubtreeLayoutForFontUpdates();
@@ -1319,13 +1379,14 @@ LayoutBlock* LayoutObject::FindNonAnonymousContainingBlock(
bool LayoutObject::ComputeIsFixedContainer(const ComputedStyle* style) const {
if (!style)
return false;
+ bool is_document_element = IsDocumentElement();
// https://www.w3.org/TR/filter-effects-1/#FilterProperty
- if (style->HasFilter() && !IsDocumentElement())
+ if (!is_document_element && style->HasNonInitialFilter())
return true;
// Backdrop-filter creates a containing block for fixed and absolute
// positioned elements:
// https://drafts.fxtf.org/filter-effects-2/#backdrop-filter-operation
- if (style->HasBackdropFilter() && !IsDocumentElement())
+ if (!is_document_element && style->HasNonInitialBackdropFilter())
return true;
// The LayoutView is always a container of fixed positioned descendants. In
// addition, SVG foreignObjects become such containers, so that descendants
@@ -1344,6 +1405,18 @@ bool LayoutObject::ComputeIsFixedContainer(const ComputedStyle* style) const {
if (ShouldApplyPaintContainment(*style) ||
ShouldApplyLayoutContainment(*style))
return true;
+
+ // We intend to change behavior to set containing block based on computed
+ // rather than used style of transform-style. HasTransformRelatedProperty
+ // above will return true if the *used* value of transform-style is
+ // preserve-3d, so to estimate compat we need to count if the line below is
+ // reached.
+ if (style->TransformStyle3D() == ETransformStyle3D::kPreserve3d) {
+ UseCounter::Count(
+ GetDocument(),
+ WebFeature::kTransformStyleContainingBlockComputedUsedMismatch);
+ }
+
return false;
}
@@ -1973,11 +2046,12 @@ StyleDifference LayoutObject::AdjustStyleDifference(
StyleRef().HasBackgroundRelatedColorReferencingCurrentColor() ||
// Skip any text nodes that do not contain text boxes. Whitespace cannot
// be skipped or we will miss invalidating decorations (e.g.,
- // underlines).
+ // underlines). MathML elements are not skipped either as some of them
+ // do special painting (e.g. fraction bar).
(IsText() && !IsBR() && ToLayoutText(this)->HasInlineFragments()) ||
(IsSVG() && StyleRef().SvgStyle().IsFillColorCurrentColor()) ||
(IsSVG() && StyleRef().SvgStyle().IsStrokeColorCurrentColor()) ||
- IsListMarker() || IsDetailsMarker())
+ IsListMarker() || IsDetailsMarker() || IsMathML())
diff.SetNeedsPaintInvalidation();
}
@@ -2457,6 +2531,15 @@ static void ClearAncestorScrollAnchors(LayoutObject* layout_object) {
void LayoutObject::StyleDidChange(StyleDifference diff,
const ComputedStyle* old_style) {
+ if (style_->TransformStyle3D() == ETransformStyle3D::kPreserve3d) {
+ if (style_->HasNonInitialBackdropFilter() || style_->HasBlendMode() ||
+ !style_->HasAutoClip() || style_->ClipPath() ||
+ style_->HasIsolation() || style_->HasMask()) {
+ UseCounter::Count(GetDocument(),
+ WebFeature::kAdditionalGroupingPropertiesForCompat);
+ }
+ }
+
// First assume the outline will be affected. It may be updated when we know
// it's not affected.
bool has_outline = style_->HasOutline();
@@ -3540,9 +3623,12 @@ const ComputedStyle* LayoutObject::FirstLineStyleWithoutFallback() const {
// it's based on first_line_block's style. We need to get the uncached
// first line style based on this object's style and cache the result in
// it.
- return StyleRef().AddCachedPseudoElementStyle(
- first_line_block->GetUncachedPseudoElementStyle(
- PseudoElementStyleRequest(kPseudoIdFirstLine), Style()));
+ if (scoped_refptr<ComputedStyle> first_line_style =
+ first_line_block->GetUncachedPseudoElementStyle(
+ PseudoElementStyleRequest(kPseudoIdFirstLine), Style())) {
+ return StyleRef().AddCachedPseudoElementStyle(
+ std::move(first_line_style));
+ }
}
} else if (!IsAnonymous() && IsLayoutInline() &&
!GetNode()->IsFirstLetterPseudoElement()) {
@@ -3554,9 +3640,12 @@ const ComputedStyle* LayoutObject::FirstLineStyleWithoutFallback() const {
Parent()->FirstLineStyleWithoutFallback()) {
// A first-line style is in effect. Get uncached first line style based on
// parent_first_line_style and cache the result in this object's style.
- return StyleRef().AddCachedPseudoElementStyle(
- GetUncachedPseudoElementStyle(kPseudoIdFirstLineInherited,
- parent_first_line_style));
+ if (scoped_refptr<ComputedStyle> first_line_style =
+ GetUncachedPseudoElementStyle(kPseudoIdFirstLineInherited,
+ parent_first_line_style)) {
+ return StyleRef().AddCachedPseudoElementStyle(
+ std::move(first_line_style));
+ }
}
}
return nullptr;
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_object.h b/chromium/third_party/blink/renderer/core/layout/layout_object.h
index 714d1246169..f1d44dd67ce 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_object.h
+++ b/chromium/third_party/blink/renderer/core/layout/layout_object.h
@@ -389,10 +389,16 @@ class CORE_EXPORT LayoutObject : public ImageResourceObserver,
LayoutBox* EnclosingScrollableBox() const;
// Returns the root of the inline formatting context |this| belongs to. |this|
- // must be |IsInline()|. The root is the object that holds |NGPaintFragment|
- // if it's in LayoutNG context.
+ // must be |IsInline()|. The root is the object that holds |NGInlineNodeData|
+ // and the root |NGPaintFragment| if it's in LayoutNG context. See also
+ // |ContainingFragmentainer()|.
LayoutBlockFlow* RootInlineFormattingContext() const;
+ // Returns the |LayoutBlockFlow| that has |NGFragmentItems| for |this|. This
+ // is usually the same as |RootInlineFormattingContext()|, but it is the child
+ // of that when the IFC has multicol applied. TODO(crbug.com/1076470)
+ LayoutBlockFlow* FragmentItemsContainer() const;
+
// Returns the containing block flow if it's a LayoutNGBlockFlow, or nullptr
// otherwise. Note that the semantics is different from |EnclosingBox| for
// atomic inlines that this function returns the container, while
@@ -545,6 +551,8 @@ class CORE_EXPORT LayoutObject : public ImageResourceObserver,
ShouldApplySizeContainment();
}
+ void NotifyPriorityScrollAnchorStatusChanged();
+
private:
//////////////////////////////////////////
// Helper functions. Dangerous to use!
@@ -669,6 +677,9 @@ class CORE_EXPORT LayoutObject : public ImageResourceObserver,
bool IsLayoutTableCol() const {
return IsOfType(kLayoutObjectLayoutTableCol);
}
+ bool IsLayoutNGTableCol() const {
+ return IsOfType(kLayoutObjectLayoutNGTableCol);
+ }
bool IsListItem() const { return IsOfType(kLayoutObjectListItem); }
bool IsMathML() const { return IsOfType(kLayoutObjectMathML); }
bool IsMathMLRoot() const { return IsOfType(kLayoutObjectMathMLRoot); }
@@ -707,6 +718,9 @@ class CORE_EXPORT LayoutObject : public ImageResourceObserver,
bool IsTable() const { return IsOfType(kLayoutObjectTable); }
bool IsTableCaption() const { return IsOfType(kLayoutObjectTableCaption); }
bool IsTableCell() const { return IsOfType(kLayoutObjectTableCell); }
+ bool IsTableCellLegacy() const {
+ return IsOfType(kLayoutObjectTableCellLegacy);
+ }
bool IsTableRow() const { return IsOfType(kLayoutObjectTableRow); }
bool IsTableSection() const { return IsOfType(kLayoutObjectTableSection); }
bool IsTextArea() const { return IsOfType(kLayoutObjectTextArea); }
@@ -766,6 +780,11 @@ class CORE_EXPORT LayoutObject : public ImageResourceObserver,
return obj && obj->IsAfterContent();
}
+ // Returns true if the text is generated (from, e.g., list marker,
+ // pseudo-element, ...) instead of from a DOM text node. See
+ // |NGTextType::kLayoutGenerated| for the other type of generated text.
+ bool IsStyleGenerated() const;
+
bool HasCounterNodeMap() const { return bitfields_.HasCounterNodeMap(); }
void SetHasCounterNodeMap(bool has_counter_node_map) {
bitfields_.SetHasCounterNodeMap(has_counter_node_map);
@@ -1074,6 +1093,13 @@ class CORE_EXPORT LayoutObject : public ImageResourceObserver,
}
bool NeedsCollectInlines() const { return bitfields_.NeedsCollectInlines(); }
+ bool MaybeHasPercentHeightDescendant() const {
+ return bitfields_.MaybeHasPercentHeightDescendant();
+ }
+ void SetMaybeHasPercentHeightDescendant() {
+ bitfields_.SetMaybeHasPercentHeightDescendant(true);
+ }
+
// Return true if the min/max intrinsic logical widths aren't up-to-date.
// Note that for objects that *don't* need to calculate intrinsic logical
// widths (e.g. if inline-size is a fixed value, and no other inline lengths
@@ -1084,6 +1110,19 @@ class CORE_EXPORT LayoutObject : public ImageResourceObserver,
return bitfields_.IntrinsicLogicalWidthsDirty();
}
+ bool IntrinsicLogicalWidthsDependsOnPercentageBlockSize() const {
+ return bitfields_.IntrinsicLogicalWidthsDependsOnPercentageBlockSize();
+ }
+ void SetIntrinsicLogicalWidthsDependsOnPercentageBlockSize(bool b) {
+ bitfields_.SetIntrinsicLogicalWidthsDependsOnPercentageBlockSize(b);
+ }
+ bool IntrinsicLogicalWidthsChildDependsOnPercentageBlockSize() const {
+ return bitfields_.IntrinsicLogicalWidthsChildDependsOnPercentageBlockSize();
+ }
+ void SetIntrinsicLogicalWidthsChildDependsOnPercentageBlockSize(bool b) {
+ bitfields_.SetIntrinsicLogicalWidthsChildDependsOnPercentageBlockSize(b);
+ }
+
bool NeedsLayoutOverflowRecalc() const {
return bitfields_.SelfNeedsLayoutOverflowRecalc() ||
bitfields_.ChildNeedsLayoutOverflowRecalc();
@@ -1125,14 +1164,16 @@ class CORE_EXPORT LayoutObject : public ImageResourceObserver,
bool HasHiddenBackface() const {
return StyleRef().BackfaceVisibility() == EBackfaceVisibility::kHidden;
}
- bool HasBackdropFilter() const { return StyleRef().HasBackdropFilter(); }
+ bool HasNonInitialBackdropFilter() const {
+ return StyleRef().HasNonInitialBackdropFilter();
+ }
// Returns |true| if any property that renders using filter operations is
// used (including, but not limited to, 'filter' and 'box-reflect').
// Not calling style()->hasFilterInducingProperty because some objects force
// to ignore reflection style (e.g. LayoutInline).
bool HasFilterInducingProperty() const {
- return StyleRef().HasFilter() || HasReflection();
+ return StyleRef().HasNonInitialFilter() || HasReflection();
}
bool HasShapeOutside() const { return StyleRef().ShapeOutside(); }
@@ -1313,6 +1354,8 @@ class CORE_EXPORT LayoutObject : public ImageResourceObserver,
// Returns true if style would make this object a fixed container.
// This value gets cached by bitfields_.can_contain_fixed_position_objects_.
+ // TODO(pdr): Should this function be unified with
+ // ComputedStyle::CanContainFixedPositionObjects?
bool ComputeIsFixedContainer(const ComputedStyle* style) const;
virtual LayoutObject* HoverAncestor() const { return Parent(); }
@@ -1359,9 +1402,12 @@ class CORE_EXPORT LayoutObject : public ImageResourceObserver,
SetIntrinsicLogicalWidthsDirty();
}
+ // Returns false when certain font changes (e.g., font-face rule changes, web
+ // font loaded, etc) have occurred, in which case |this| needs relayout.
+ bool IsFontFallbackValid() const;
+
// Traverses subtree, and marks all layout objects as need relayout, repaint
// and preferred width recalc. Also invalidates shaping on all text nodes.
- // TODO(crbug.com/441925): Try to partially invalidate layout on font updates.
virtual void InvalidateSubtreeLayoutForFontUpdates();
void InvalidateIntersectionObserverCachedRects();
@@ -2058,7 +2104,7 @@ class CORE_EXPORT LayoutObject : public ImageResourceObserver,
bool CreatesGroup() const {
return StyleRef().HasOpacity() || HasMask() || HasClipPath() ||
- HasFilterInducingProperty() || HasBackdropFilter() ||
+ HasFilterInducingProperty() || HasNonInitialBackdropFilter() ||
StyleRef().HasBlendMode();
}
@@ -2525,7 +2571,7 @@ class CORE_EXPORT LayoutObject : public ImageResourceObserver,
bool BeingDestroyed() const { return bitfields_.BeingDestroyed(); }
DisplayLockContext* GetDisplayLockContext() const {
- if (!RuntimeEnabledFeatures::CSSSubtreeVisibilityEnabled())
+ if (!RuntimeEnabledFeatures::CSSContentVisibilityEnabled())
return nullptr;
auto* element = DynamicTo<Element>(GetNode());
if (!element)
@@ -2546,6 +2592,7 @@ class CORE_EXPORT LayoutObject : public ImageResourceObserver,
kLayoutObjectFrameSet,
kLayoutObjectInsideListMarker,
kLayoutObjectLayoutTableCol,
+ kLayoutObjectLayoutNGTableCol,
kLayoutObjectListItem,
kLayoutObjectMathML,
kLayoutObjectMathMLRoot,
@@ -2553,6 +2600,7 @@ class CORE_EXPORT LayoutObject : public ImageResourceObserver,
kLayoutObjectNGBlockFlow,
kLayoutObjectNGFieldset,
kLayoutObjectNGFlexibleBox,
+ kLayoutObjectNGGrid,
kLayoutObjectNGMixin,
kLayoutObjectNGListItem,
kLayoutObjectNGInsideListMarker,
@@ -2585,6 +2633,7 @@ class CORE_EXPORT LayoutObject : public ImageResourceObserver,
kLayoutObjectTable,
kLayoutObjectTableCaption,
kLayoutObjectTableCell,
+ kLayoutObjectTableCellLegacy,
kLayoutObjectTableRow,
kLayoutObjectTableSection,
kLayoutObjectTextArea,
@@ -2875,7 +2924,11 @@ class CORE_EXPORT LayoutObject : public ImageResourceObserver,
self_needs_layout_overflow_recalc_(false),
child_needs_layout_overflow_recalc_(false),
intrinsic_logical_widths_dirty_(false),
+ intrinsic_logical_widths_depends_on_percentage_block_size_(true),
+ intrinsic_logical_widths_child_depends_on_percentage_block_size_(
+ true),
needs_collect_inlines_(false),
+ maybe_has_percent_height_descendant_(false),
should_check_for_paint_invalidation_(true),
subtree_should_check_for_paint_invalidation_(false),
should_delay_full_paint_invalidation_(false),
@@ -2990,11 +3043,31 @@ class CORE_EXPORT LayoutObject : public ImageResourceObserver,
ADD_BOOLEAN_BITFIELD(intrinsic_logical_widths_dirty_,
IntrinsicLogicalWidthsDirty);
+ // This boolean indicates if the cached intrinsic logical widths may depend
+ // on the input %-block-size given by the parent.
+ ADD_BOOLEAN_BITFIELD(
+ intrinsic_logical_widths_depends_on_percentage_block_size_,
+ IntrinsicLogicalWidthsDependsOnPercentageBlockSize);
+
+ // This boolean indicates if a *child* of this node may depend on the input
+ // %-block-size given by the parent. Must always be true for legacy layout
+ // roots.
+ ADD_BOOLEAN_BITFIELD(
+ intrinsic_logical_widths_child_depends_on_percentage_block_size_,
+ IntrinsicLogicalWidthsChildDependsOnPercentageBlockSize);
+
// This flag is set on inline container boxes that need to run the
// Pre-layout phase in LayoutNG. See NGInlineNode::CollectInlines().
// Also maybe set to inline boxes to optimize the propagation.
ADD_BOOLEAN_BITFIELD(needs_collect_inlines_, NeedsCollectInlines);
+ // This boolean tracks if a containing-block potentially has a percentage
+ // height descentant within its subtree. A relayout may be required if a
+ // %-block-size or definiteness changes. This flag is only set, and never
+ // cleared.
+ ADD_BOOLEAN_BITFIELD(maybe_has_percent_height_descendant_,
+ MaybeHasPercentHeightDescendant);
+
// Paint related dirty bits.
ADD_BOOLEAN_BITFIELD(should_check_for_paint_invalidation_,
ShouldCheckForPaintInvalidation);
@@ -3374,10 +3447,6 @@ inline bool LayoutObject::CanTraversePhysicalFragments() const {
// will not attempt to add support for them here.
if (PaintFragment())
return false;
- // We don't support fragmentation traversal inside block fragmentation just
- // yet.
- if (IsInsideFlowThread())
- return false;
// The NG paint system currently doesn't support table-cells.
if (IsTableCell())
return false;
@@ -3490,7 +3559,11 @@ inline void LayoutObject::SetIsInLayoutNGInlineFormattingContext(
if (IsInLayoutNGInlineFormattingContext() == new_value)
return;
InLayoutNGInlineFormattingContextWillChange(new_value);
+ // The association cache for inline fragments is in union. Make sure the
+ // cache is cleared before and after changing this flag.
+ DCHECK(!HasInlineFragments());
bitfields_.SetIsInLayoutNGInlineFormattingContext(new_value);
+ DCHECK(!HasInlineFragments());
}
inline void LayoutObject::SetHasBoxDecorationBackground(bool b) {
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_object_child_list.cc b/chromium/third_party/blink/renderer/core/layout/layout_object_child_list.cc
index 8a71bc3a13b..63b241f3f8f 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_object_child_list.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_object_child_list.cc
@@ -31,6 +31,7 @@
#include "third_party/blink/renderer/core/layout/layout_inline.h"
#include "third_party/blink/renderer/core/layout/layout_object.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
+#include "third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items.h"
#include "third_party/blink/renderer/core/paint/ng/ng_paint_fragment.h"
#include "third_party/blink/renderer/core/paint/object_paint_invalidator.h"
@@ -59,9 +60,13 @@ void InvalidateInlineItems(LayoutObject* object) {
}
if (RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()) {
- // TODO(yosin): Tells |NGFragmentItem| about they become not to associate
- // to layout object.
- object->ClearFirstInlineFragmentItemIndex();
+ // This LayoutObject is not technically destroyed, but further access should
+ // be prohibited when moved to different parent as if it were destroyed.
+ if (object->FirstInlineFragmentItemIndex()) {
+ if (auto* text = ToLayoutTextOrNull(object))
+ text->DetachAbstractInlineTextBoxesIfNeeded();
+ NGFragmentItems::LayoutObjectWillBeMoved(*object);
+ }
} else if (NGPaintFragment* fragment = object->FirstInlineFragment()) {
// This LayoutObject is not technically destroyed, but further access should
// be prohibited when moved to different parent as if it were destroyed.
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_object_factory.cc b/chromium/third_party/blink/renderer/core/layout/layout_object_factory.cc
index 5ec6031ef59..eb9bd180d32 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_object_factory.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_object_factory.cc
@@ -11,6 +11,7 @@
#include "third_party/blink/renderer/core/layout/layout_fieldset.h"
#include "third_party/blink/renderer/core/layout/layout_file_upload_control.h"
#include "third_party/blink/renderer/core/layout/layout_flexible_box.h"
+#include "third_party/blink/renderer/core/layout/layout_grid.h"
#include "third_party/blink/renderer/core/layout/layout_inside_list_marker.h"
#include "third_party/blink/renderer/core/layout/layout_list_item.h"
#include "third_party/blink/renderer/core/layout/layout_outside_list_marker.h"
@@ -19,17 +20,20 @@
#include "third_party/blink/renderer/core/layout/layout_text.h"
#include "third_party/blink/renderer/core/layout/layout_text_fragment.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
+#include "third_party/blink/renderer/core/layout/ng/flex/layout_ng_flexible_box.h"
#include "third_party/blink/renderer/core/layout/ng/inline/layout_ng_text.h"
#include "third_party/blink/renderer/core/layout/ng/inline/layout_ng_text_fragment.h"
#include "third_party/blink/renderer/core/layout/ng/layout_ng_block_flow.h"
#include "third_party/blink/renderer/core/layout/ng/layout_ng_fieldset.h"
-#include "third_party/blink/renderer/core/layout/ng/layout_ng_flexible_box.h"
+#include "third_party/blink/renderer/core/layout/ng/layout_ng_grid.h"
#include "third_party/blink/renderer/core/layout/ng/layout_ng_progress.h"
-#include "third_party/blink/renderer/core/layout/ng/layout_ng_table_caption.h"
-#include "third_party/blink/renderer/core/layout/ng/layout_ng_table_cell.h"
+#include "third_party/blink/renderer/core/layout/ng/layout_ng_ruby_as_block.h"
#include "third_party/blink/renderer/core/layout/ng/list/layout_ng_inside_list_marker.h"
#include "third_party/blink/renderer/core/layout/ng/list/layout_ng_list_item.h"
#include "third_party/blink/renderer/core/layout/ng/list/layout_ng_outside_list_marker.h"
+#include "third_party/blink/renderer/core/layout/ng/mathml/layout_ng_mathml_block.h"
+#include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_caption.h"
+#include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_cell_legacy.h"
#include "third_party/blink/renderer/core/style/computed_style.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
@@ -103,10 +107,30 @@ LayoutBlock* LayoutObjectFactory::CreateFlexibleBox(Node& node,
const ComputedStyle& style,
LegacyLayout legacy) {
bool disable_ng_for_type = !RuntimeEnabledFeatures::LayoutNGFlexBoxEnabled();
+ if (disable_ng_for_type)
+ UseCounter::Count(node.GetDocument(), WebFeature::kLegacyLayoutByFlexBox);
return CreateObject<LayoutBlock, LayoutNGFlexibleBox, LayoutFlexibleBox>(
node, style, legacy, disable_ng_for_type);
}
+LayoutBlock* LayoutObjectFactory::CreateGrid(Node& node,
+ const ComputedStyle& style,
+ LegacyLayout legacy) {
+ bool disable_ng_for_type = !RuntimeEnabledFeatures::LayoutNGGridEnabled();
+ if (disable_ng_for_type)
+ UseCounter::Count(node.GetDocument(), WebFeature::kLegacyLayoutByGrid);
+ return CreateObject<LayoutBlock, LayoutNGGrid, LayoutGrid>(
+ node, style, legacy, disable_ng_for_type);
+}
+
+LayoutBlock* LayoutObjectFactory::CreateMath(Node& node,
+ const ComputedStyle& style,
+ LegacyLayout legacy) {
+ bool disable_ng_for_type = !RuntimeEnabledFeatures::MathMLCoreEnabled();
+ return CreateObject<LayoutBlock, LayoutNGMathMLBlock, LayoutBlockFlow>(
+ node, style, legacy, disable_ng_for_type);
+}
+
LayoutObject* LayoutObjectFactory::CreateListMarker(Node& node,
const ComputedStyle& style,
LegacyLayout legacy) {
@@ -135,13 +159,16 @@ LayoutTableCell* LayoutObjectFactory::CreateTableCell(
Node& node,
const ComputedStyle& style,
LegacyLayout legacy) {
- return CreateObject<LayoutTableCell, LayoutNGTableCell>(node, style, legacy);
+ return CreateObject<LayoutTableCell, LayoutNGTableCellLegacy>(node, style,
+ legacy);
}
LayoutBlock* LayoutObjectFactory::CreateFieldset(Node& node,
const ComputedStyle& style,
LegacyLayout legacy) {
bool disable_ng_for_type = !RuntimeEnabledFeatures::LayoutNGFieldsetEnabled();
+ if (disable_ng_for_type)
+ UseCounter::Count(node.GetDocument(), WebFeature::kLegacyLayoutByFieldSet);
return CreateObject<LayoutBlock, LayoutNGFieldset, LayoutFieldset>(
node, style, legacy, disable_ng_for_type);
}
@@ -194,4 +221,12 @@ LayoutProgress* LayoutObjectFactory::CreateProgress(Node* node,
return CreateObject<LayoutProgress, LayoutNGProgress>(*node, style, legacy);
}
+LayoutRubyAsBlock* LayoutObjectFactory::CreateRubyAsBlock(
+ Node* node,
+ const ComputedStyle& style,
+ LegacyLayout legacy) {
+ return CreateObject<LayoutRubyAsBlock, LayoutNGRubyAsBlock>(*node, style,
+ legacy);
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_object_factory.h b/chromium/third_party/blink/renderer/core/layout/layout_object_factory.h
index 37428424c92..1cc47ff245c 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_object_factory.h
+++ b/chromium/third_party/blink/renderer/core/layout/layout_object_factory.h
@@ -17,6 +17,7 @@ class LayoutBlockFlow;
class LayoutObject;
enum class LegacyLayout;
class LayoutProgress;
+class LayoutRubyAsBlock;
class LayoutTableCaption;
class LayoutTableCell;
class LayoutText;
@@ -44,6 +45,8 @@ class LayoutObjectFactory {
static LayoutBlock* CreateFlexibleBox(Node&,
const ComputedStyle&,
LegacyLayout);
+ static LayoutBlock* CreateGrid(Node&, const ComputedStyle&, LegacyLayout);
+ static LayoutBlock* CreateMath(Node&, const ComputedStyle&, LegacyLayout);
static LayoutObject* CreateListMarker(Node&,
const ComputedStyle&,
LegacyLayout);
@@ -66,6 +69,9 @@ class LayoutObjectFactory {
static LayoutProgress* CreateProgress(Node* node,
const ComputedStyle& style,
LegacyLayout legacy);
+ static LayoutRubyAsBlock* CreateRubyAsBlock(Node* node,
+ const ComputedStyle& style,
+ LegacyLayout legacy);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_object_test.cc b/chromium/third_party/blink/renderer/core/layout/layout_object_test.cc
index d1d45474fa0..5d06f5326ac 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_object_test.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_object_test.cc
@@ -86,6 +86,31 @@ TEST_F(LayoutObjectTest, DisplayInlineBlockCreateObject) {
EXPECT_TRUE(layout_object->IsInline());
}
+TEST_F(LayoutObjectTest, UseCountBackdropFilterAsGroupingProperty) {
+ SetBodyInnerHTML(R"HTML(
+ <style> div { transform-style: preserve-3d; } </style>
+ <div id=target style="backdrop-filter: blur(2px)"></div>
+ )HTML");
+ EXPECT_FALSE(
+ GetLayoutObjectByElementId("target")->StyleRef().HasGroupingProperty());
+ EXPECT_TRUE(GetDocument().IsUseCounted(
+ WebFeature::kAdditionalGroupingPropertiesForCompat));
+}
+
+TEST_F(LayoutObjectTest, UseCountContainingBlockFixedPosUnderFlattened3D) {
+ SetBodyInnerHTML(R"HTML(
+ <div style='transform-style: preserve-3d; opacity: 0.9'>
+ <div id=target style='position:fixed'></div>
+ </div>
+ )HTML");
+
+ LayoutObject* target = GetLayoutObjectByElementId("target");
+ EXPECT_EQ(target->View(), target->Container());
+
+ EXPECT_TRUE(GetDocument().IsUseCounted(
+ WebFeature::kTransformStyleContainingBlockComputedUsedMismatch));
+}
+
// Containing block test.
TEST_F(LayoutObjectTest, ContainingBlockLayoutViewShouldBeNull) {
EXPECT_EQ(nullptr, GetLayoutView().ContainingBlock());
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_ruby.cc b/chromium/third_party/blink/renderer/core/layout/layout_ruby.cc
index 3e653de8bab..61ea140526d 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_ruby.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_ruby.cc
@@ -94,7 +94,7 @@ void LayoutRubyAsInline::AddChild(LayoutObject* child,
// (The LayoutRubyRun object will handle the details)
LayoutRubyRun* last_run = LastRubyRun(this);
if (!last_run || last_run->HasRubyText()) {
- last_run = LayoutRubyRun::StaticCreateRubyRun(this);
+ last_run = LayoutRubyRun::StaticCreateRubyRun(this, *ContainingBlock());
LayoutInline::AddChild(last_run, before_child);
}
last_run->AddChild(child);
@@ -159,7 +159,7 @@ void LayoutRubyAsBlock::AddChild(LayoutObject* child,
// (The LayoutRubyRun object will handle the details)
LayoutRubyRun* last_run = LastRubyRun(this);
if (!last_run || last_run->HasRubyText()) {
- last_run = LayoutRubyRun::StaticCreateRubyRun(this);
+ last_run = LayoutRubyRun::StaticCreateRubyRun(this, *this);
LayoutBlockFlow::AddChild(last_run, before_child);
}
last_run->AddChild(child);
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_ruby.h b/chromium/third_party/blink/renderer/core/layout/layout_ruby.h
index d28c25bad64..66747efa17d 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_ruby.h
+++ b/chromium/third_party/blink/renderer/core/layout/layout_ruby.h
@@ -77,7 +77,7 @@ class LayoutRubyAsInline final : public LayoutInline {
};
// <ruby> when used as 'display:block' or 'display:inline-block'
-class LayoutRubyAsBlock final : public LayoutBlockFlow {
+class LayoutRubyAsBlock : public LayoutBlockFlow {
public:
LayoutRubyAsBlock(Element*);
~LayoutRubyAsBlock() override;
@@ -90,11 +90,11 @@ class LayoutRubyAsBlock final : public LayoutBlockFlow {
protected:
void StyleDidChange(StyleDifference, const ComputedStyle* old_style) override;
-
- private:
bool IsOfType(LayoutObjectType type) const override {
return type == kLayoutObjectRuby || LayoutBlockFlow::IsOfType(type);
}
+
+ private:
bool CreatesAnonymousWrapper() const override { return true; }
void RemoveLeftoverAnonymousBlock(LayoutBlock*) override { NOTREACHED(); }
};
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_ruby_base.cc b/chromium/third_party/blink/renderer/core/layout/layout_ruby_base.cc
index 1bb9a9e2685..6418d0a37a6 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_ruby_base.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_ruby_base.cc
@@ -30,16 +30,27 @@
#include "third_party/blink/renderer/core/layout/layout_ruby_base.h"
+#include "third_party/blink/renderer/core/layout/layout_ruby_run.h"
+#include "third_party/blink/renderer/core/layout/ng/layout_ng_ruby_base.h"
+
namespace blink {
-LayoutRubyBase::LayoutRubyBase() : LayoutBlockFlow(nullptr) {
+LayoutRubyBase::LayoutRubyBase(Element* element) : LayoutBlockFlow(nullptr) {
+ DCHECK(!element);
SetInline(false);
}
LayoutRubyBase::~LayoutRubyBase() = default;
-LayoutRubyBase* LayoutRubyBase::CreateAnonymous(Document* document) {
- LayoutRubyBase* layout_object = new LayoutRubyBase();
+LayoutRubyBase* LayoutRubyBase::CreateAnonymous(Document* document,
+ const LayoutRubyRun& ruby_run) {
+ LayoutRubyBase* layout_object;
+ if (ruby_run.IsLayoutNGObject()) {
+ DCHECK(RuntimeEnabledFeatures::LayoutNGRubyEnabled());
+ layout_object = new LayoutNGRubyBase();
+ } else {
+ layout_object = new LayoutRubyBase(nullptr);
+ }
layout_object->SetDocumentForAnonymous(document);
return layout_object;
}
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_ruby_base.h b/chromium/third_party/blink/renderer/core/layout/layout_ruby_base.h
index 7d4336b90be..6e474be96d9 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_ruby_base.h
+++ b/chromium/third_party/blink/renderer/core/layout/layout_ruby_base.h
@@ -36,11 +36,14 @@
namespace blink {
class LayoutRubyRun;
+template <typename Base>
+class LayoutNGMixin;
-class LayoutRubyBase final : public LayoutBlockFlow {
+class LayoutRubyBase : public LayoutBlockFlow {
public:
~LayoutRubyBase() override;
- static LayoutRubyBase* CreateAnonymous(Document*);
+ static LayoutRubyBase* CreateAnonymous(Document*,
+ const LayoutRubyRun& ruby_run);
const char* GetName() const override { return "LayoutRubyBase"; }
@@ -51,7 +54,9 @@ class LayoutRubyBase final : public LayoutBlockFlow {
bool IsChildAllowed(LayoutObject*, const ComputedStyle&) const override;
private:
- LayoutRubyBase();
+ // The argument must be nullptr. It's necessary for the LayoutNGMixin
+ // constructor.
+ explicit LayoutRubyBase(Element*);
ETextAlign TextAlignmentForLine(bool ends_with_soft_break) const override;
void AdjustInlineDirectionLineBounds(
@@ -66,6 +71,7 @@ class LayoutRubyBase final : public LayoutBlockFlow {
void MoveBlockChildren(LayoutRubyBase* to_base,
LayoutObject* before_child = nullptr);
+ friend class LayoutNGMixin<LayoutRubyBase>;
// Allow LayoutRubyRun to manipulate the children within ruby bases.
friend class LayoutRubyRun;
};
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_ruby_run.cc b/chromium/third_party/blink/renderer/core/layout/layout_ruby_run.cc
index bba4c5c90b8..9b86bda50b0 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_ruby_run.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_ruby_run.cc
@@ -33,10 +33,12 @@
#include "third_party/blink/renderer/core/layout/layout_ruby_base.h"
#include "third_party/blink/renderer/core/layout/layout_ruby_text.h"
#include "third_party/blink/renderer/core/layout/layout_text.h"
+#include "third_party/blink/renderer/core/layout/ng/layout_ng_ruby_run.h"
namespace blink {
-LayoutRubyRun::LayoutRubyRun() : LayoutBlockFlow(nullptr) {
+LayoutRubyRun::LayoutRubyRun(Element* element) : LayoutBlockFlow(nullptr) {
+ DCHECK(!element);
SetInline(true);
SetIsAtomicInlineLevel(true);
}
@@ -103,7 +105,7 @@ void LayoutRubyRun::AddChild(LayoutObject* child, LayoutObject* before_child) {
DCHECK_EQ(before_child->Parent(), this);
LayoutObject* ruby = Parent();
DCHECK(ruby->IsRuby());
- LayoutBlock* new_run = StaticCreateRubyRun(ruby);
+ LayoutBlock* new_run = StaticCreateRubyRun(ruby, *ContainingBlock());
ruby->AddChild(new_run, NextSibling());
// Add the new ruby text and move the old one to the new run
// Note: Doing it in this order and not using LayoutRubyRun's methods,
@@ -117,7 +119,7 @@ void LayoutRubyRun::AddChild(LayoutObject* child, LayoutObject* before_child) {
// In this case we need insert a new run before the current one and split
// the base.
LayoutObject* ruby = Parent();
- LayoutRubyRun* new_run = StaticCreateRubyRun(ruby);
+ LayoutRubyRun* new_run = StaticCreateRubyRun(ruby, *ContainingBlock());
ruby->AddChild(new_run, this);
new_run->AddChild(child);
@@ -182,7 +184,7 @@ void LayoutRubyRun::RemoveChild(LayoutObject* child) {
LayoutRubyBase* LayoutRubyRun::CreateRubyBase() const {
LayoutRubyBase* layout_object =
- LayoutRubyBase::CreateAnonymous(&GetDocument());
+ LayoutRubyBase::CreateAnonymous(&GetDocument(), *this);
scoped_refptr<ComputedStyle> new_style =
ComputedStyle::CreateAnonymousStyleWithDisplay(StyleRef(),
EDisplay::kBlock);
@@ -192,10 +194,17 @@ LayoutRubyBase* LayoutRubyRun::CreateRubyBase() const {
}
LayoutRubyRun* LayoutRubyRun::StaticCreateRubyRun(
- const LayoutObject* parent_ruby) {
+ const LayoutObject* parent_ruby,
+ const LayoutBlock& containing_block) {
DCHECK(parent_ruby);
DCHECK(parent_ruby->IsRuby());
- LayoutRubyRun* rr = new LayoutRubyRun();
+ LayoutRubyRun* rr;
+ if (RuntimeEnabledFeatures::LayoutNGRubyEnabled() &&
+ containing_block.IsLayoutNGObject()) {
+ rr = new LayoutNGRubyRun();
+ } else {
+ rr = new LayoutRubyRun(nullptr);
+ }
rr->SetDocumentForAnonymous(&parent_ruby->GetDocument());
scoped_refptr<ComputedStyle> new_style =
ComputedStyle::CreateAnonymousStyleWithDisplay(parent_ruby->StyleRef(),
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_ruby_run.h b/chromium/third_party/blink/renderer/core/layout/layout_ruby_run.h
index a1fb0b239b3..163a9780fd1 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_ruby_run.h
+++ b/chromium/third_party/blink/renderer/core/layout/layout_ruby_run.h
@@ -38,12 +38,14 @@ namespace blink {
class LayoutRubyBase;
class LayoutRubyText;
+template <typename Base>
+class LayoutNGMixin;
// LayoutRubyRun are 'inline-block/table' like objects,and wrap a single pairing
// of a ruby base with its ruby text(s).
// See LayoutRuby.h for further comments on the structure
-class LayoutRubyRun final : public LayoutBlockFlow {
+class LayoutRubyRun : public LayoutBlockFlow {
public:
~LayoutRubyRun() override;
@@ -69,7 +71,9 @@ class LayoutRubyRun final : public LayoutBlockFlow {
int& start_overhang,
int& end_overhang) const;
- static LayoutRubyRun* StaticCreateRubyRun(const LayoutObject* parent_ruby);
+ static LayoutRubyRun* StaticCreateRubyRun(
+ const LayoutObject* parent_ruby,
+ const LayoutBlock& containing_block);
bool CanBreakBefore(const LazyLineBreakIterator&) const;
@@ -79,13 +83,16 @@ class LayoutRubyRun final : public LayoutBlockFlow {
LayoutRubyBase* CreateRubyBase() const;
private:
- LayoutRubyRun();
+ // The argument must be nullptr.
+ explicit LayoutRubyRun(Element*);
bool IsOfType(LayoutObjectType type) const override {
return type == kLayoutObjectRubyRun || LayoutBlockFlow::IsOfType(type);
}
bool CreatesAnonymousWrapper() const override { return true; }
void RemoveLeftoverAnonymousBlock(LayoutBlock*) override {}
+
+ friend class LayoutNGMixin<LayoutRubyRun>;
};
DEFINE_LAYOUT_OBJECT_TYPE_CASTS(LayoutRubyRun, IsRubyRun());
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_ruby_text.h b/chromium/third_party/blink/renderer/core/layout/layout_ruby_text.h
index b2e1ced4916..3684bc00e6b 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_ruby_text.h
+++ b/chromium/third_party/blink/renderer/core/layout/layout_ruby_text.h
@@ -35,7 +35,7 @@
namespace blink {
-class LayoutRubyText final : public LayoutBlockFlow {
+class LayoutRubyText : public LayoutBlockFlow {
public:
LayoutRubyText(Element*);
~LayoutRubyText() override;
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_shift_tracker.cc b/chromium/third_party/blink/renderer/core/layout/layout_shift_tracker.cc
index 20ab99f71b4..dc374a71017 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_shift_tracker.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_shift_tracker.cc
@@ -14,6 +14,7 @@
#include "third_party/blink/renderer/core/frame/local_frame_client.h"
#include "third_party/blink/renderer/core/frame/location.h"
#include "third_party/blink/renderer/core/frame/visual_viewport.h"
+#include "third_party/blink/renderer/core/geometry/dom_rect_read_only.h"
#include "third_party/blink/renderer/core/layout/layout_object.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
#include "third_party/blink/renderer/core/page/chrome_client.h"
@@ -363,6 +364,38 @@ void LayoutShiftTracker::NotifyPrePaintFinished() {
attributions_.fill(Attribution());
}
+LayoutShift::AttributionList LayoutShiftTracker::CreateAttributionList() const {
+ LayoutShift::AttributionList list;
+ for (const Attribution& att : attributions_) {
+ if (att.node_id == kInvalidDOMNodeId)
+ break;
+ list.push_back(LayoutShiftAttribution::Create(
+ DOMNodeIds::NodeForId(att.node_id),
+ DOMRectReadOnly::FromIntRect(att.old_visual_rect),
+ DOMRectReadOnly::FromIntRect(att.new_visual_rect)));
+ }
+ return list;
+}
+
+void LayoutShiftTracker::SubmitPerformanceEntry(double score_delta,
+ bool had_recent_input) const {
+ LocalDOMWindow* window = frame_view_->GetFrame().DomWindow();
+ if (!window)
+ return;
+ WindowPerformance* performance = DOMWindowPerformance::performance(*window);
+ DCHECK(performance);
+
+ double input_timestamp =
+ had_recent_input ? performance->MonotonicTimeToDOMHighResTimeStamp(
+ most_recent_input_timestamp_)
+ : 0.0;
+ LayoutShift* entry =
+ LayoutShift::Create(performance->now(), score_delta, had_recent_input,
+ input_timestamp, CreateAttributionList());
+
+ performance->AddLayoutShiftEntry(entry);
+}
+
void LayoutShiftTracker::ReportShift(double score_delta,
double weighted_score_delta) {
LocalFrame& frame = frame_view_->GetFrame();
@@ -377,14 +410,7 @@ void LayoutShiftTracker::ReportShift(double score_delta,
}
}
- if (frame.DomWindow()) {
- WindowPerformance* performance =
- DOMWindowPerformance::performance(*frame.DomWindow());
- if (performance) {
- performance->AddLayoutShiftValue(score_delta, had_recent_input,
- most_recent_input_timestamp_);
- }
- }
+ SubmitPerformanceEntry(score_delta, had_recent_input);
TRACE_EVENT_INSTANT2("loading", "LayoutShift", TRACE_EVENT_SCOPE_THREAD,
"data", PerFrameTraceData(score_delta, had_recent_input),
@@ -405,23 +431,24 @@ void LayoutShiftTracker::NotifyInput(const WebInputEvent& event) {
const WebInputEvent::Type type = event.GetType();
const bool saw_pointerdown = pointerdown_pending_data_.saw_pointerdown;
const bool pointerdown_became_tap =
- saw_pointerdown && type == WebInputEvent::kPointerUp;
+ saw_pointerdown && type == WebInputEvent::Type::kPointerUp;
const bool event_type_stops_pointerdown_buffering =
- type == WebInputEvent::kPointerUp ||
- type == WebInputEvent::kPointerCausedUaAction ||
- type == WebInputEvent::kPointerCancel;
+ type == WebInputEvent::Type::kPointerUp ||
+ type == WebInputEvent::Type::kPointerCausedUaAction ||
+ type == WebInputEvent::Type::kPointerCancel;
// Only non-hovering pointerdown requires buffering.
const bool is_hovering_pointerdown =
- type == WebInputEvent::kPointerDown &&
+ type == WebInputEvent::Type::kPointerDown &&
static_cast<const WebPointerEvent&>(event).hovering;
const bool should_trigger_shift_exclusion =
- type == WebInputEvent::kMouseDown || type == WebInputEvent::kKeyDown ||
- type == WebInputEvent::kRawKeyDown ||
+ type == WebInputEvent::Type::kMouseDown ||
+ type == WebInputEvent::Type::kKeyDown ||
+ type == WebInputEvent::Type::kRawKeyDown ||
// We need to explicitly include tap, as if there are no listeners, we
// won't receive the pointer events.
- type == WebInputEvent::kGestureTap || is_hovering_pointerdown ||
+ type == WebInputEvent::Type::kGestureTap || is_hovering_pointerdown ||
pointerdown_became_tap;
if (should_trigger_shift_exclusion) {
@@ -438,7 +465,7 @@ void LayoutShiftTracker::NotifyInput(const WebInputEvent& event) {
ReportShift(score_delta, pointerdown_pending_data_.weighted_score_delta);
pointerdown_pending_data_ = PointerdownPendingData();
}
- if (type == WebInputEvent::kPointerDown && !is_hovering_pointerdown)
+ if (type == WebInputEvent::Type::kPointerDown && !is_hovering_pointerdown)
pointerdown_pending_data_.saw_pointerdown = true;
}
@@ -536,6 +563,10 @@ void LayoutShiftTracker::SetLayoutShiftRects(const Vector<IntRect>& int_rects) {
}
}
+void LayoutShiftTracker::Trace(Visitor* visitor) {
+ visitor->Trace(frame_view_);
+}
+
ReattachHook::Scope::Scope(const Node& node) : active_(node.GetLayoutObject()) {
if (active_) {
auto& hook = GetReattachHook();
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_shift_tracker.h b/chromium/third_party/blink/renderer/core/layout/layout_shift_tracker.h
index 24bbd221df5..fcff32159d9 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_shift_tracker.h
+++ b/chromium/third_party/blink/renderer/core/layout/layout_shift_tracker.h
@@ -9,6 +9,7 @@
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/layout/layout_shift_region.h"
#include "third_party/blink/renderer/core/scroll/scroll_types.h"
+#include "third_party/blink/renderer/core/timing/layout_shift.h"
#include "third_party/blink/renderer/platform/geometry/region.h"
#include "third_party/blink/renderer/platform/graphics/dom_node_id.h"
#include "third_party/blink/renderer/platform/timer.h"
@@ -25,12 +26,11 @@ class WebInputEvent;
// Tracks "layout shifts" from layout objects changing their visual location
// between animation frames. See https://github.com/WICG/layout-instability.
-class CORE_EXPORT LayoutShiftTracker {
- USING_FAST_MALLOC(LayoutShiftTracker);
-
+class CORE_EXPORT LayoutShiftTracker final
+ : public GarbageCollected<LayoutShiftTracker> {
public:
- LayoutShiftTracker(LocalFrameView*);
- ~LayoutShiftTracker() {}
+ explicit LayoutShiftTracker(LocalFrameView*);
+ ~LayoutShiftTracker() = default;
// |paint_offset_diff| is an additional amount by which the paint offset
// shifted that is not tracked in visual rects. Visual rects are in the
// local transform space of the LayoutObject. Any time the transform space is
@@ -60,6 +60,7 @@ class CORE_EXPORT LayoutShiftTracker {
base::TimeTicks MostRecentInputTimestamp() {
return most_recent_input_timestamp_;
}
+ void Trace(Visitor* visitor);
// Saves and restores visual rects on layout objects when a layout tree is
// rebuilt by Node::ReattachLayoutTree.
@@ -100,9 +101,10 @@ class CORE_EXPORT LayoutShiftTracker {
double SubframeWeightingFactor() const;
void SetLayoutShiftRects(const Vector<IntRect>& int_rects);
void UpdateInputTimestamp(base::TimeTicks timestamp);
+ LayoutShift::AttributionList CreateAttributionList() const;
+ void SubmitPerformanceEntry(double score_delta, bool input_detected) const;
- // This owns us.
- UntracedMember<LocalFrameView> frame_view_;
+ Member<LocalFrameView> frame_view_;
// The document cumulative layout shift (DCLS) score for this LocalFrame,
// unweighted, with move distance applied.
@@ -175,13 +177,11 @@ class CORE_EXPORT LayoutShiftTracker {
bool MoreImpactfulThan(const Attribution&) const;
int Area() const;
};
- static constexpr int kMaxAttributions = 5;
void MaybeRecordAttribution(const Attribution&);
- // Nodes that have contributed to the impact region for the current frame, for
- // use in trace event. Only populated while tracing.
- std::array<Attribution, kMaxAttributions> attributions_;
+ // Nodes that have contributed to the impact region for the current frame.
+ std::array<Attribution, LayoutShift::kMaxAttributions> attributions_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_shift_tracker_test.cc b/chromium/third_party/blink/renderer/core/layout/layout_shift_tracker_test.cc
index 4418bcf5202..32508f593cd 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_shift_tracker_test.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_shift_tracker_test.cc
@@ -30,7 +30,7 @@ class LayoutShiftTrackerTest : public RenderingTest {
void SimulateInput() {
GetLayoutShiftTracker().NotifyInput(WebMouseEvent(
- WebInputEvent::kMouseDown, gfx::PointF(), gfx::PointF(),
+ WebInputEvent::Type::kMouseDown, gfx::PointF(), gfx::PointF(),
WebPointerProperties::Button::kLeft, 0,
WebInputEvent::Modifiers::kLeftButtonDown, base::TimeTicks::Now()));
}
@@ -232,14 +232,16 @@ void LayoutShiftTrackerPointerdownTest::RunTest(
1 /* PointerId */, WebPointerProperties::PointerType::kTouch,
WebPointerProperties::Button::kLeft);
- WebPointerEvent event1(WebInputEvent::kPointerDown, pointer_properties, 5, 5);
+ WebPointerEvent event1(WebInputEvent::Type::kPointerDown, pointer_properties,
+ 5, 5);
WebPointerEvent event2(completion_type, pointer_properties, 5, 5);
// Coordinates inside #box.
event1.SetPositionInWidget(50, 150);
event2.SetPositionInWidget(50, 160);
- WebView().MainFrameWidget()->HandleInputEvent(WebCoalescedInputEvent(event1));
+ WebView().MainFrameWidget()->HandleInputEvent(
+ WebCoalescedInputEvent(event1, ui::LatencyInfo()));
Compositor().BeginFrame();
test::RunPendingTasks();
@@ -250,7 +252,8 @@ void LayoutShiftTrackerPointerdownTest::RunTest(
EXPECT_EQ(0u, perf.getBufferedEntriesByType("layout-shift").size());
EXPECT_FLOAT_EQ(0.0, tracker.Score());
- WebView().MainFrameWidget()->HandleInputEvent(WebCoalescedInputEvent(event2));
+ WebView().MainFrameWidget()->HandleInputEvent(
+ WebCoalescedInputEvent(event2, ui::LatencyInfo()));
// region fraction 50%, distance fraction 1/8
const double expected_shift = 0.5 * 0.125;
@@ -265,15 +268,16 @@ void LayoutShiftTrackerPointerdownTest::RunTest(
}
TEST_F(LayoutShiftTrackerPointerdownTest, PointerdownBecomesTap) {
- RunTest(WebInputEvent::kPointerUp, true /* expect_exclusion */);
+ RunTest(WebInputEvent::Type::kPointerUp, true /* expect_exclusion */);
}
TEST_F(LayoutShiftTrackerPointerdownTest, PointerdownCancelled) {
- RunTest(WebInputEvent::kPointerCancel, false /* expect_exclusion */);
+ RunTest(WebInputEvent::Type::kPointerCancel, false /* expect_exclusion */);
}
TEST_F(LayoutShiftTrackerPointerdownTest, PointerdownBecomesScroll) {
- RunTest(WebInputEvent::kPointerCausedUaAction, false /* expect_exclusion */);
+ RunTest(WebInputEvent::Type::kPointerCausedUaAction,
+ false /* expect_exclusion */);
}
TEST_F(LayoutShiftTrackerTest, StableCompositingChanges) {
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_table_section.cc b/chromium/third_party/blink/renderer/core/layout/layout_table_section.cc
index e109f213be7..c67288cb774 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_table_section.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_table_section.cc
@@ -1096,6 +1096,11 @@ void LayoutTableSection::DistributeRemainingExtraLogicalHeight(
int total_logical_height_added = 0;
int previous_row_position = row_pos_[0];
float total_row_size = row_pos_[total_rows] - previous_row_position;
+ if (total_row_size == 0) {
+ // crbug.com/1074722 prevents division by 0.
+ extra_logical_height = 0;
+ return;
+ }
for (unsigned r = 0; r < total_rows; r++) {
// weight with the original height
float height_to_add = extra_logical_height *
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_text.cc b/chromium/third_party/blink/renderer/core/layout/layout_text.cc
index b1ccf91480c..6e6add82e13 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_text.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_text.cc
@@ -153,10 +153,14 @@ LayoutText::LayoutText(Node* node, scoped_refptr<StringImpl> str)
LayoutText::~LayoutText() {
#if DCHECK_IS_ON()
- if (IsInLayoutNGInlineFormattingContext())
- DCHECK(!first_paint_fragment_);
- else
+ if (IsInLayoutNGInlineFormattingContext()) {
+ if (!RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled())
+ DCHECK(!first_paint_fragment_);
+ else
+ DCHECK(!first_fragment_item_index_);
+ } else {
text_boxes_.AssertIsEmpty();
+ }
#endif
}
@@ -223,20 +227,26 @@ void LayoutText::RemoveAndDestroyTextBoxes() {
for (InlineTextBox* box : TextBoxes())
box->Remove();
} else {
+ if (Parent())
+ Parent()->DirtyLinesFromChangedChild(this);
if (RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()) {
- if (has_abstract_inline_text_box_)
+ if (FirstInlineFragmentItemIndex()) {
+ DetachAbstractInlineTextBoxesIfNeeded();
+ NGFragmentItems::LayoutObjectWillBeDestroyed(*this);
ClearFirstInlineFragmentItemIndex();
+ }
} else if (NGPaintFragment* first_inline_fragment =
FirstInlineFragment()) {
first_inline_fragment->LayoutObjectWillBeDestroyed();
SetFirstInlineFragment(nullptr);
}
- if (Parent())
- Parent()->DirtyLinesFromChangedChild(this);
}
} else if (RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()) {
- if (has_abstract_inline_text_box_)
+ if (FirstInlineFragmentItemIndex()) {
+ DetachAbstractInlineTextBoxesIfNeeded();
+ NGFragmentItems::LayoutObjectWillBeDestroyed(*this);
ClearFirstInlineFragmentItemIndex();
+ }
} else if (NGPaintFragment* first_inline_fragment = FirstInlineFragment()) {
// Still do this to clear the global hash map in NGAbstractInlineTextBox.
SetFirstInlineFragment(nullptr);
@@ -298,10 +308,7 @@ void LayoutText::DetachAbstractInlineTextBoxes() {
void LayoutText::SetFirstInlineFragment(NGPaintFragment* first_fragment) {
CHECK(IsInLayoutNGInlineFormattingContext());
- // TODO(yosin): Once we remove |NGPaintFragment|, we should get rid of
- // |!fragment|.
- DCHECK(!first_fragment ||
- !RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled());
+ DCHECK(!RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled());
DetachAbstractInlineTextBoxesIfNeeded();
first_paint_fragment_ = first_fragment;
}
@@ -319,17 +326,26 @@ void LayoutText::SetFirstInlineFragmentItemIndex(wtf_size_t index) {
DCHECK(RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled());
DCHECK_NE(index, 0u);
DetachAbstractInlineTextBoxesIfNeeded();
- // TDOO(yosin): Once we update all |LayoutObject::FirstInlineFragment()|,
- // we should enable below.
- // first_fragment_item_index_ = index;
+ first_fragment_item_index_ = index;
}
void LayoutText::InLayoutNGInlineFormattingContextWillChange(bool new_value) {
- DeleteTextBoxes();
+ if (IsInLayoutNGInlineFormattingContext()) {
+ if (!RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()) {
+ SetFirstInlineFragment(nullptr);
+ } else {
+ ClearFirstInlineFragmentItemIndex();
+ }
+ } else {
+ DeleteTextBoxes();
+ }
// Because |first_paint_fragment_| and |text_boxes_| are union, when one is
// deleted, the other should be initialized to nullptr.
- DCHECK(new_value ? !first_paint_fragment_ : !text_boxes_.First());
+ DCHECK(new_value ? (RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()
+ ? !first_fragment_item_index_
+ : !first_paint_fragment_)
+ : !text_boxes_.First());
// Because there are no inline boxes associated to this text, we should not
// have abstract inline text boxes too.
@@ -359,7 +375,7 @@ Vector<LayoutText::TextBoxInfo> LayoutText::GetTextBoxInfo() const {
}
// We don't put generated texts, e.g. ellipsis, hyphen, etc. not in text
// content, into results. Note: CSS "content" aren't categorized this.
- if (cursor.Current().IsGeneratedTextType())
+ if (cursor.Current().IsLayoutGeneratedText())
continue;
// When the corresponding DOM range contains collapsed whitespaces, NG
// produces one fragment but legacy produces multiple text boxes broken at
@@ -414,11 +430,11 @@ Vector<LayoutText::TextBoxInfo> LayoutText::GetTextBoxInfo() const {
}
bool LayoutText::HasInlineFragments() const {
- if (IsInLayoutNGInlineFormattingContext()) {
- NGInlineCursor cursor;
- cursor.MoveTo(*this);
- return cursor.IsNotNull();
- }
+ if (IsInLayoutNGInlineFormattingContext()) {
+ if (!RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled())
+ return first_paint_fragment_;
+ return first_fragment_item_index_;
+ }
return FirstTextBox();
}
@@ -1953,6 +1969,12 @@ void LayoutText::TextDidChangeWithoutInvalidation() {
}
void LayoutText::InvalidateSubtreeLayoutForFontUpdates() {
+ if (RuntimeEnabledFeatures::
+ CSSReducedFontLoadingLayoutInvalidationsEnabled() &&
+ IsFontFallbackValid()) {
+ return;
+ }
+
known_to_have_no_overflow_and_no_fallback_fonts_ = false;
valid_ng_items_ = false;
SetNeedsCollectInlines();
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_text.h b/chromium/third_party/blink/renderer/core/layout/layout_text.h
index 17ca490ad20..42b67a90ac0 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_text.h
+++ b/chromium/third_party/blink/renderer/core/layout/layout_text.h
@@ -476,11 +476,10 @@ inline InlineTextBoxList& LayoutText::MutableTextBoxes() {
inline NGPaintFragment* LayoutText::FirstInlineFragment() const {
if (!IsInLayoutNGInlineFormattingContext())
return nullptr;
- // TODO(yosin): Once we replace all usage of |FirstInlineFragment()| to
- // |NGInlineCursor|, we should change this to |DCHECK()|.
- if (RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled())
- return nullptr;
- return first_paint_fragment_;
+ if (!RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled())
+ return first_paint_fragment_;
+ NOTREACHED();
+ return nullptr;
}
inline wtf_size_t LayoutText::FirstInlineFragmentItemIndex() const {
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_text_control.cc b/chromium/third_party/blink/renderer/core/layout/layout_text_control.cc
index cce0469a265..16c8ce7dd59 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_text_control.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_text_control.cc
@@ -55,8 +55,11 @@ void LayoutTextControl::StyleDidChange(StyleDifference diff,
LayoutBlock* inner_editor_layout_object =
To<LayoutBlock>(inner_editor->GetLayoutObject());
if (inner_editor_layout_object) {
+ // This is necessary to update the style on the inner_editor based on the
+ // changes in the input element ComputedStyle.
+ // (See TextControlInnerEditorElement::CreateInnerEditorStyle()).
inner_editor->SetNeedsStyleRecalc(
- kSubtreeStyleChange,
+ kLocalStyleChange,
StyleChangeReasonForTracing::Create(style_change_reason::kControl));
// The inner editor element uses the LayoutTextControl's ::selection style
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_theme.cc b/chromium/third_party/blink/renderer/core/layout/layout_theme.cc
index b1cbf5326ba..9481ac334da 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_theme.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_theme.cc
@@ -573,11 +573,7 @@ bool LayoutTheme::IsReadOnlyControl(const Node* node) {
bool LayoutTheme::IsHovered(const Node* node) {
if (!node)
return false;
- const auto* element = DynamicTo<SpinButtonElement>(node);
- if (!element)
- return node->IsHovered();
- return element->IsHovered() &&
- element->GetUpDownState() != SpinButtonElement::kIndeterminate;
+ return node->IsHovered();
}
bool LayoutTheme::IsSpinUpButtonPartHovered(const Node* node) {
@@ -866,10 +862,6 @@ void LayoutTheme::SetCustomFocusRingColor(const Color& c) {
has_custom_focus_ring_color_ = true;
}
-bool LayoutTheme::IsFocusRingOutset() const {
- return false;
-}
-
Color LayoutTheme::FocusRingColor() const {
return has_custom_focus_ring_color_ ? custom_focus_ring_color_
: GetTheme().PlatformFocusRingColor();
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_theme.h b/chromium/third_party/blink/renderer/core/layout/layout_theme.h
index 9ffb65caaab..6701b242741 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_theme.h
+++ b/chromium/third_party/blink/renderer/core/layout/layout_theme.h
@@ -169,7 +169,6 @@ class CORE_EXPORT LayoutTheme : public RefCounted<LayoutTheme> {
bool in_forced_colors_mode,
WebColorScheme color_scheme) const;
- virtual bool IsFocusRingOutset() const;
virtual Color FocusRingColor() const;
virtual Color PlatformFocusRingColor() const { return Color(0, 0, 0); }
void SetCustomFocusRingColor(const Color&);
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_theme_default.cc b/chromium/third_party/blink/renderer/core/layout/layout_theme_default.cc
index 806f976d723..5b46435b30e 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_theme_default.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_theme_default.cc
@@ -240,6 +240,10 @@ void LayoutThemeDefault::AdjustInnerSpinButtonStyle(
style.SetMinWidth(Length::Fixed(size.Width() * zoom_level));
}
+bool LayoutThemeDefault::PopsMenuByReturnKey() const {
+ return true;
+}
+
bool LayoutThemeDefault::ShouldOpenPickerWithF4Key() const {
return true;
}
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_theme_default.h b/chromium/third_party/blink/renderer/core/layout/layout_theme_default.h
index 50588077553..58293c5eacb 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_theme_default.h
+++ b/chromium/third_party/blink/renderer/core/layout/layout_theme_default.h
@@ -74,8 +74,8 @@ class CORE_EXPORT LayoutThemeDefault : public LayoutTheme {
void AdjustInnerSpinButtonStyle(ComputedStyle&) const override;
void AdjustButtonStyle(ComputedStyle&) const override;
- bool PopsMenuBySpaceKey() const final { return true; }
- bool PopsMenuByReturnKey() const final { return true; }
+ bool PopsMenuBySpaceKey() const override { return true; }
+ bool PopsMenuByReturnKey() const override;
bool PopsMenuByAltDownUpOrF4Key() const override { return true; }
bool ShouldOpenPickerWithF4Key() const override;
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_theme_mac.mm b/chromium/third_party/blink/renderer/core/layout/layout_theme_mac.mm
index f9912f0c745..7bda1506824 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_theme_mac.mm
+++ b/chromium/third_party/blink/renderer/core/layout/layout_theme_mac.mm
@@ -162,6 +162,8 @@ class LayoutThemeMacRefresh final : public LayoutThemeDefault {
return file.name();
}
bool PopsMenuByArrowKeys() const override;
+ bool PopsMenuByReturnKey() const override;
+ bool SupportsSelectionForegroundColors() const override { return false; }
protected:
// Controls color values returned from FocusRingColor().
@@ -382,6 +384,10 @@ bool LayoutThemeMacRefresh::PopsMenuByArrowKeys() const {
return true;
}
+bool LayoutThemeMacRefresh::PopsMenuByReturnKey() const {
+ return false;
+}
+
static FontSelectionValue ToFontWeight(NSInteger app_kit_font_weight) {
DCHECK_GT(app_kit_font_weight, 0);
DCHECK_LT(app_kit_font_weight, 15);
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_view.cc b/chromium/third_party/blink/renderer/core/layout/layout_view.cc
index 65ecfe44e87..67af94038fa 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_view.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_view.cc
@@ -45,6 +45,7 @@
#include "third_party/blink/renderer/core/layout/svg/layout_svg_root.h"
#include "third_party/blink/renderer/core/layout/view_fragmentation_context.h"
#include "third_party/blink/renderer/core/page/chrome_client.h"
+#include "third_party/blink/renderer/core/page/named_pages_mapper.h"
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/core/page/scrolling/root_scroller_controller.h"
#include "third_party/blink/renderer/core/page/scrolling/scrolling_coordinator_context.h"
@@ -306,10 +307,14 @@ void LayoutView::UpdateBlockLayout(bool relayout_children) {
}
void LayoutView::UpdateLayout() {
- if (!GetDocument().Printing())
+ if (!GetDocument().Printing()) {
SetPageLogicalHeight(LayoutUnit());
+ named_pages_mapper_ = nullptr;
+ }
if (PageLogicalHeight() && ShouldUsePrintingLayout()) {
+ if (RuntimeEnabledFeatures::NamedPagesEnabled())
+ named_pages_mapper_ = std::make_unique<NamedPagesMapper>();
intrinsic_logical_widths_ = LogicalWidth();
if (!fragmentation_context_) {
fragmentation_context_ =
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_view.h b/chromium/third_party/blink/renderer/core/layout/layout_view.h
index 10753eb247a..7a36102b35d 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_view.h
+++ b/chromium/third_party/blink/renderer/core/layout/layout_view.h
@@ -38,6 +38,7 @@ namespace blink {
class LayoutQuote;
class LocalFrameView;
+class NamedPagesMapper;
class PaintLayerCompositor;
class ViewFragmentationContext;
@@ -192,6 +193,10 @@ class CORE_EXPORT LayoutView final : public LayoutBlockFlow {
page_logical_height_ = height;
}
+ NamedPagesMapper* GetNamedPagesMapper() const {
+ return named_pages_mapper_.get();
+ }
+
PaintLayerCompositor* Compositor();
bool UsesCompositing() const;
@@ -282,6 +287,8 @@ class CORE_EXPORT LayoutView final : public LayoutBlockFlow {
TransformState&,
MapCoordinatesFlags) const override;
+ bool ShouldUsePrintingLayout() const;
+
private:
void MapLocalToAncestor(const LayoutBoxModelObject* ancestor,
TransformState&,
@@ -300,8 +307,6 @@ class CORE_EXPORT LayoutView final : public LayoutBlockFlow {
void UpdateFromStyle() override;
- bool ShouldUsePrintingLayout() const;
-
int ViewLogicalWidthForBoxSizing() const {
return ViewLogicalWidth(kIncludeScrollbars);
}
@@ -325,6 +330,7 @@ class CORE_EXPORT LayoutView final : public LayoutBlockFlow {
LayoutState* layout_state_;
std::unique_ptr<ViewFragmentationContext> fragmentation_context_;
+ std::unique_ptr<NamedPagesMapper> named_pages_mapper_;
std::unique_ptr<PaintLayerCompositor> compositor_;
scoped_refptr<IntervalArena> interval_arena_;
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_view_test.cc b/chromium/third_party/blink/renderer/core/layout/layout_view_test.cc
index 94dbb303112..e41c96484d1 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_view_test.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_view_test.cc
@@ -8,6 +8,8 @@
#include "third_party/blink/renderer/core/dom/node_computed_style.h"
#include "third_party/blink/renderer/core/editing/text_affinity.h"
#include "third_party/blink/renderer/core/html/html_iframe_element.h"
+#include "third_party/blink/renderer/core/page/named_pages_mapper.h"
+#include "third_party/blink/renderer/core/page/print_context.h"
#include "third_party/blink/renderer/core/testing/core_unit_test_helper.h"
#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
@@ -64,6 +66,59 @@ TEST_F(LayoutViewTest, DisplayNoneFrame) {
EXPECT_FALSE(frame_doc->NeedsLayoutTreeUpdate());
}
+TEST_F(LayoutViewTest, NamedPages) {
+ ScopedNamedPagesForTest named_pages_enabler(true);
+
+ SetBodyInnerHTML(R"HTML(
+ <!DOCTYPE html>
+ <style>
+ div:empty { height:10px; }
+ </style>
+ <!-- First page: -->
+ <div></div>
+ <!-- Second page: -->
+ <div style="break-before:page;"></div>
+ <!-- Third page: -->
+ <div style="page:yksi;"></div>
+ <!-- Fourth page: -->
+ <div style="page:yksi;">
+ <div style="page:yksi; break-before:page;"></div>
+ <!-- Fifth page: -->
+ <div style="page:yksi; break-before:page;"></div>
+ </div>
+ <!-- Sixth page: -->
+ <div style="page:kaksi;"></div>
+ <!-- Seventh page: -->
+ <div style="page:maksitaksi;"></div>
+ <!-- Eighth page: -->
+ <div></div>
+ <!-- Ninth page: -->
+ <div style="page:yksi;"></div>
+ )HTML");
+
+ UpdateAllLifecyclePhasesForTest();
+ const LayoutView* view = GetDocument().GetLayoutView();
+ ASSERT_TRUE(view);
+
+ ScopedPrintContext print_context(&GetDocument().View()->GetFrame());
+ print_context->BeginPrintMode(500, 500);
+ const NamedPagesMapper* mapper = view->GetNamedPagesMapper();
+ ASSERT_TRUE(mapper);
+
+ EXPECT_EQ(mapper->NamedPageAtIndex(0), AtomicString());
+ EXPECT_EQ(mapper->NamedPageAtIndex(1), AtomicString());
+ EXPECT_EQ(mapper->NamedPageAtIndex(2), "yksi");
+ EXPECT_EQ(mapper->NamedPageAtIndex(3), "yksi");
+ EXPECT_EQ(mapper->NamedPageAtIndex(4), "yksi");
+ EXPECT_EQ(mapper->NamedPageAtIndex(5), "kaksi");
+ EXPECT_EQ(mapper->NamedPageAtIndex(6), "maksitaksi");
+ EXPECT_EQ(mapper->NamedPageAtIndex(7), AtomicString());
+ EXPECT_EQ(mapper->NamedPageAtIndex(8), "yksi");
+ EXPECT_EQ(mapper->NamedPageAtIndex(9), "yksi");
+ EXPECT_EQ(mapper->NamedPageAtIndex(100), "yksi");
+ EXPECT_EQ(mapper->LastPageName(), "yksi");
+}
+
struct HitTestConfig {
bool layout_ng;
EditingBehaviorType editing_behavior;
diff --git a/chromium/third_party/blink/renderer/core/layout/line/inline_box.cc b/chromium/third_party/blink/renderer/core/layout/line/inline_box.cc
index 234f99caab9..fbb94e4db67 100644
--- a/chromium/third_party/blink/renderer/core/layout/line/inline_box.cc
+++ b/chromium/third_party/blink/renderer/core/layout/line/inline_box.cc
@@ -82,7 +82,7 @@ void* InlineBox::operator new(size_t sz) {
}
void InlineBox::operator delete(void* ptr) {
- base::PartitionFree(ptr);
+ WTF::Partitions::LayoutPartition()->Free(ptr);
}
const char* InlineBox::BoxName() const {
diff --git a/chromium/third_party/blink/renderer/core/layout/multi_column_fragmentainer_group_test.cc b/chromium/third_party/blink/renderer/core/layout/multi_column_fragmentainer_group_test.cc
index f86cb314e26..a41618e5170 100644
--- a/chromium/third_party/blink/renderer/core/layout/multi_column_fragmentainer_group_test.cc
+++ b/chromium/third_party/blink/renderer/core/layout/multi_column_fragmentainer_group_test.cc
@@ -34,8 +34,8 @@ class MultiColumnFragmentainerGroupTest : public RenderingTest {
void MultiColumnFragmentainerGroupTest::SetUp() {
RenderingTest::SetUp();
scoped_refptr<ComputedStyle> style = ComputedStyle::Create();
- flow_thread_ =
- LayoutMultiColumnFlowThread::CreateAnonymous(GetDocument(), *style.get());
+ flow_thread_ = LayoutMultiColumnFlowThread::CreateAnonymous(
+ GetDocument(), *style.get(), /* needs_paint_layer */ true);
column_set_ = LayoutMultiColumnSet::CreateAnonymous(*flow_thread_,
*flow_thread_->Style());
}
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/custom/css_layout_definition.cc b/chromium/third_party/blink/renderer/core/layout/ng/custom/css_layout_definition.cc
index b662f819135..3a2d2beb0b1 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/custom/css_layout_definition.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/custom/css_layout_definition.cc
@@ -89,7 +89,6 @@ bool CSSLayoutDefinition::Instance::Layout(
const NGBlockNode& node,
const LogicalSize& border_box_size,
const NGBoxStrut& border_scrollbar_padding,
- const LayoutUnit child_percentage_resolution_block_size_for_min_max,
CustomLayoutScope* custom_layout_scope,
FragmentResultOptions*& fragment_result_options,
scoped_refptr<SerializedScriptValue>* fragment_result_data) {
@@ -145,8 +144,7 @@ bool CSSLayoutDefinition::Instance::Layout(
// Run the work queue until exhaustion.
while (!custom_layout_scope->Queue()->IsEmpty()) {
for (auto& task : *custom_layout_scope->Queue()) {
- task.Run(space, node.Style(),
- child_percentage_resolution_block_size_for_min_max);
+ task.Run(space, node.Style(), border_box_size.block_size);
}
custom_layout_scope->Queue()->clear();
{
@@ -223,7 +221,8 @@ bool CSSLayoutDefinition::Instance::IntrinsicSizes(
const NGBoxStrut& border_scrollbar_padding,
const LayoutUnit child_percentage_resolution_block_size_for_min_max,
CustomLayoutScope* custom_layout_scope,
- IntrinsicSizesResultOptions*& intrinsic_sizes_result_options) {
+ IntrinsicSizesResultOptions** intrinsic_sizes_result_options,
+ bool* child_depends_on_percentage_block_size) {
ScriptState* script_state = definition_->GetScriptState();
v8::Isolate* isolate = script_state->GetIsolate();
@@ -272,7 +271,8 @@ bool CSSLayoutDefinition::Instance::IntrinsicSizes(
while (!custom_layout_scope->Queue()->IsEmpty()) {
for (auto& task : *custom_layout_scope->Queue()) {
task.Run(space, node.Style(),
- child_percentage_resolution_block_size_for_min_max);
+ child_percentage_resolution_block_size_for_min_max,
+ child_depends_on_percentage_block_size);
}
custom_layout_scope->Queue()->clear();
{
@@ -300,7 +300,7 @@ bool CSSLayoutDefinition::Instance::IntrinsicSizes(
v8::Local<v8::Value> inner_value = v8_result_promise->Result();
// Attempt to convert the result.
- intrinsic_sizes_result_options =
+ *intrinsic_sizes_result_options =
NativeValueTraits<IntrinsicSizesResultOptions>::NativeValue(
isolate, inner_value, exception_state);
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/custom/css_layout_definition.h b/chromium/third_party/blink/renderer/core/layout/ng/custom/css_layout_definition.h
index 4c1ff77f733..d2bef60636a 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/custom/css_layout_definition.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/custom/css_layout_definition.h
@@ -61,7 +61,6 @@ class CSSLayoutDefinition final : public GarbageCollected<CSSLayoutDefinition>,
const NGBlockNode&,
const LogicalSize& border_box_size,
const NGBoxStrut& border_scrollbar_padding,
- const LayoutUnit child_percentage_resolution_block_size_for_min_max,
CustomLayoutScope*,
FragmentResultOptions*&,
scoped_refptr<SerializedScriptValue>* fragment_result_data);
@@ -76,7 +75,8 @@ class CSSLayoutDefinition final : public GarbageCollected<CSSLayoutDefinition>,
const NGBoxStrut& border_scrollbar_padding,
const LayoutUnit child_percentage_resolution_block_size_for_min_max,
CustomLayoutScope*,
- IntrinsicSizesResultOptions*&);
+ IntrinsicSizesResultOptions**,
+ bool* child_depends_on_percentage_block_size);
void Trace(Visitor*);
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/custom/custom_layout_child.cc b/chromium/third_party/blink/renderer/core/layout/ng/custom/custom_layout_child.cc
index 11a2762ad9d..a4ed4148eca 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/custom/custom_layout_child.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/custom/custom_layout_child.cc
@@ -62,16 +62,21 @@ ScriptPromise CustomLayoutChild::layoutNextFragment(
// Serialize the provided data if needed.
scoped_refptr<SerializedScriptValue> constraint_data;
if (options->hasData()) {
- // We serialize "kForStorage" so that SharedArrayBuffers can't be shared
- // between LayoutWorkletGlobalScopes.
- constraint_data = SerializedScriptValue::Serialize(
- script_state->GetIsolate(), options->data().V8Value(),
- SerializedScriptValue::SerializeOptions(
- SerializedScriptValue::kForStorage),
- exception_state);
+ v8::Local<v8::Value> data = options->data().V8Value();
+ // TODO(peria): Remove this branch. We don't serialize null values for
+ // backward compatibility. https://crbug.com/1070871
+ if (!data->IsNullOrUndefined()) {
+ // We serialize "kForStorage" so that SharedArrayBuffers can't be shared
+ // between LayoutWorkletGlobalScopes.
+ constraint_data = SerializedScriptValue::Serialize(
+ script_state->GetIsolate(), data,
+ SerializedScriptValue::SerializeOptions(
+ SerializedScriptValue::kForStorage),
+ exception_state);
- if (exception_state.HadException())
- return ScriptPromise();
+ if (exception_state.HadException())
+ return ScriptPromise();
+ }
}
auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/custom/custom_layout_constraints.cc b/chromium/third_party/blink/renderer/core/layout/ng/custom/custom_layout_constraints.cc
index 268d0e72343..9ed31898a5c 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/custom/custom_layout_constraints.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/custom/custom_layout_constraints.cc
@@ -32,16 +32,6 @@ base::Optional<double> CustomLayoutConstraints::fixedBlockSize() const {
return fixed_block_size_;
}
-double CustomLayoutConstraints::fixedBlockSize(bool& is_null) const {
- // Check if we've been passed an indefinite block-size.
- if (fixed_block_size_ < 0.0) {
- is_null = true;
- return 0.0;
- }
-
- return fixed_block_size_;
-}
-
ScriptValue CustomLayoutConstraints::data(ScriptState* script_state) const {
// "data" is *only* exposed to the LayoutWorkletGlobalScope, and we are able
// to return the same deserialized object. We don't need to check which world
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/custom/custom_layout_constraints.h b/chromium/third_party/blink/renderer/core/layout/ng/custom/custom_layout_constraints.h
index 42ce5a8fa06..6a496623aab 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/custom/custom_layout_constraints.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/custom/custom_layout_constraints.h
@@ -30,8 +30,6 @@ class CustomLayoutConstraints : public ScriptWrappable {
// LayoutConstraints.idl
double fixedInlineSize() const { return fixed_inline_size_; }
base::Optional<double> fixedBlockSize() const;
- // TODO(crbug.com/1060971): Remove |is_null| version.
- double fixedBlockSize(bool& is_null) const; // DEPRECATED
ScriptValue data(ScriptState*) const;
void Trace(Visitor*) override;
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/custom/custom_layout_fragment.cc b/chromium/third_party/blink/renderer/core/layout/ng/custom/custom_layout_fragment.cc
index 476d990a0b4..1d724aa4f68 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/custom/custom_layout_fragment.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/custom/custom_layout_fragment.cc
@@ -38,11 +38,6 @@ const NGLayoutInputNode& CustomLayoutFragment::GetLayoutNode() const {
return child_->GetLayoutNode();
}
-double CustomLayoutFragment::baseline(bool& is_null) const {
- is_null = !baseline_.has_value();
- return baseline_.value_or(0.0);
-}
-
ScriptValue CustomLayoutFragment::data(ScriptState* script_state) const {
// "data" is *only* exposed to the LayoutWorkletGlobalScope, and we are able
// to return the same deserialized object. We don't need to check which world
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/custom/custom_layout_fragment.h b/chromium/third_party/blink/renderer/core/layout/ng/custom/custom_layout_fragment.h
index 29adc05f5a9..c9b5dde905d 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/custom/custom_layout_fragment.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/custom/custom_layout_fragment.h
@@ -53,8 +53,6 @@ class CustomLayoutFragment : public ScriptWrappable {
void setBlockOffset(double block_offset) { block_offset_ = block_offset; }
base::Optional<double> baseline() const { return baseline_; }
- // TODO(crbug.com/1060971): Remove |is_null| version.
- double baseline(bool& is_null) const; // DEPRECATED
ScriptValue data(ScriptState*) const;
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/custom/custom_layout_work_task.cc b/chromium/third_party/blink/renderer/core/layout/ng/custom/custom_layout_work_task.cc
index 3e9dc834b29..b24800c68ef 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/custom/custom_layout_work_task.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/custom/custom_layout_work_task.cc
@@ -43,14 +43,15 @@ CustomLayoutWorkTask::~CustomLayoutWorkTask() = default;
void CustomLayoutWorkTask::Run(
const NGConstraintSpace& parent_space,
const ComputedStyle& parent_style,
- const LayoutUnit child_percentage_resolution_block_size_for_min_max) {
+ const LayoutUnit child_percentage_resolution_block_size_for_min_max,
+ bool* child_depends_on_percentage_block_size) {
DCHECK(token_->IsValid());
NGLayoutInputNode child = child_->GetLayoutNode();
if (type_ == CustomLayoutWorkTask::TaskType::kIntrinsicSizes) {
RunIntrinsicSizesTask(parent_style,
child_percentage_resolution_block_size_for_min_max,
- child);
+ child, child_depends_on_percentage_block_size);
} else {
DCHECK_EQ(type_, CustomLayoutWorkTask::TaskType::kLayoutFragment);
RunLayoutFragmentTask(parent_space, parent_style, child);
@@ -144,15 +145,21 @@ void CustomLayoutWorkTask::RunLayoutFragmentTask(
void CustomLayoutWorkTask::RunIntrinsicSizesTask(
const ComputedStyle& parent_style,
const LayoutUnit child_percentage_resolution_block_size_for_min_max,
- NGLayoutInputNode child) {
+ NGLayoutInputNode child,
+ bool* child_depends_on_percentage_block_size) {
DCHECK_EQ(type_, CustomLayoutWorkTask::TaskType::kIntrinsicSizes);
DCHECK(resolver_);
MinMaxSizesInput input(child_percentage_resolution_block_size_for_min_max);
- MinMaxSizes sizes =
+ MinMaxSizesResult result =
ComputeMinAndMaxContentContribution(parent_style, child, input);
resolver_->Resolve(MakeGarbageCollected<CustomIntrinsicSizes>(
- child_, token_, sizes.min_size, sizes.max_size));
+ child_, token_, result.sizes.min_size, result.sizes.max_size));
+
+ if (child_depends_on_percentage_block_size) {
+ *child_depends_on_percentage_block_size |=
+ result.depends_on_percentage_block_size;
+ }
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/custom/custom_layout_work_task.h b/chromium/third_party/blink/renderer/core/layout/ng/custom/custom_layout_work_task.h
index 7aacc7fce5c..551c27202bc 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/custom/custom_layout_work_task.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/custom/custom_layout_work_task.h
@@ -47,7 +47,8 @@ class CustomLayoutWorkTask {
// Runs this work task.
void Run(const NGConstraintSpace& parent_space,
const ComputedStyle& parent_style,
- const LayoutUnit child_percentage_resolution_block_size_for_min_max);
+ const LayoutUnit child_percentage_resolution_block_size_for_min_max,
+ bool* child_depends_on_percentage_block_size = nullptr);
private:
Persistent<CustomLayoutChild> child_;
@@ -63,7 +64,8 @@ class CustomLayoutWorkTask {
void RunIntrinsicSizesTask(
const ComputedStyle& parent_style,
const LayoutUnit child_percentage_resolution_block_size_for_min_max,
- NGLayoutInputNode child);
+ NGLayoutInputNode child,
+ bool* child_depends_on_percentage_block_size);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/custom/layout_worklet.cc b/chromium/third_party/blink/renderer/core/layout/ng/custom/layout_worklet.cc
index 71e6bb85888..be7fd1d4847 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/custom/layout_worklet.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/custom/layout_worklet.cc
@@ -22,15 +22,15 @@ LayoutWorklet* LayoutWorklet::From(LocalDOMWindow& window) {
LayoutWorklet* supplement =
Supplement<LocalDOMWindow>::From<LayoutWorklet>(window);
if (!supplement && window.GetFrame()) {
- supplement = MakeGarbageCollected<LayoutWorklet>(window.GetFrame());
+ supplement = MakeGarbageCollected<LayoutWorklet>(window);
ProvideTo(window, supplement);
}
return supplement;
}
-LayoutWorklet::LayoutWorklet(LocalFrame* frame)
- : Worklet(frame->GetDocument()),
- Supplement<LocalDOMWindow>(*frame->DomWindow()),
+LayoutWorklet::LayoutWorklet(LocalDOMWindow& window)
+ : Worklet(window),
+ Supplement<LocalDOMWindow>(window),
pending_layout_registry_(MakeGarbageCollected<PendingLayoutRegistry>()) {}
LayoutWorklet::~LayoutWorklet() = default;
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/custom/layout_worklet.h b/chromium/third_party/blink/renderer/core/layout/ng/custom/layout_worklet.h
index 19d91dd9a97..7f852c563e2 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/custom/layout_worklet.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/custom/layout_worklet.h
@@ -35,7 +35,7 @@ class CORE_EXPORT LayoutWorklet : public Worklet,
static const size_t kNumGlobalScopes;
static LayoutWorklet* From(LocalDOMWindow&);
- explicit LayoutWorklet(LocalFrame*);
+ explicit LayoutWorklet(LocalDOMWindow&);
~LayoutWorklet() override;
typedef HeapHashMap<String, Member<DocumentLayoutDefinition>>
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/custom/layout_worklet_global_scope.cc b/chromium/third_party/blink/renderer/core/layout/ng/custom/layout_worklet_global_scope.cc
index 77870594359..51bb52ea69d 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/custom/layout_worklet_global_scope.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/custom/layout_worklet_global_scope.cc
@@ -12,7 +12,6 @@
#include "third_party/blink/renderer/bindings/core/v8/worker_or_worklet_script_controller.h"
#include "third_party/blink/renderer/core/css/css_property_names.h"
#include "third_party/blink/renderer/core/dom/document.h"
-#include "third_party/blink/renderer/core/execution_context/agent.h"
#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/inspector/main_thread_debugger.h"
@@ -31,21 +30,9 @@ LayoutWorkletGlobalScope* LayoutWorkletGlobalScope::Create(
std::unique_ptr<GlobalScopeCreationParams> creation_params,
WorkerReportingProxy& reporting_proxy,
PendingLayoutRegistry* pending_layout_registry) {
- // Enable a separate microtask queue for LayoutWorklet.
- // TODO(yutak): Set agent for all worklets and workers,
- // not just LayoutWorklet.
- auto* isolate = ToIsolate(frame);
- auto microtask_queue =
- v8::MicrotaskQueue::New(isolate, v8::MicrotasksPolicy::kScoped);
- auto* agent =
- MakeGarbageCollected<Agent>(isolate,
- creation_params->agent_cluster_id.is_empty()
- ? base::UnguessableToken::Create()
- : creation_params->agent_cluster_id,
- std::move(microtask_queue));
auto* global_scope = MakeGarbageCollected<LayoutWorkletGlobalScope>(
frame, std::move(creation_params), reporting_proxy,
- pending_layout_registry, agent);
+ pending_layout_registry);
global_scope->ScriptController()->Initialize(NullURL());
MainThreadDebugger::Instance()->ContextCreated(
global_scope->ScriptController()->GetScriptState(),
@@ -57,12 +44,12 @@ LayoutWorkletGlobalScope::LayoutWorkletGlobalScope(
LocalFrame* frame,
std::unique_ptr<GlobalScopeCreationParams> creation_params,
WorkerReportingProxy& reporting_proxy,
- PendingLayoutRegistry* pending_layout_registry,
- Agent* agent)
+ PendingLayoutRegistry* pending_layout_registry)
: WorkletGlobalScope(std::move(creation_params),
reporting_proxy,
frame,
- agent),
+ // Enable a separate microtask queue for LayoutWorklet.
+ /*create_microtask_queue=*/true),
pending_layout_registry_(pending_layout_registry) {}
LayoutWorkletGlobalScope::~LayoutWorkletGlobalScope() = default;
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/custom/layout_worklet_global_scope.h b/chromium/third_party/blink/renderer/core/layout/ng/custom/layout_worklet_global_scope.h
index d920e67f8d3..c02359b83b2 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/custom/layout_worklet_global_scope.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/custom/layout_worklet_global_scope.h
@@ -31,8 +31,7 @@ class CORE_EXPORT LayoutWorkletGlobalScope final : public WorkletGlobalScope {
LayoutWorkletGlobalScope(LocalFrame*,
std::unique_ptr<GlobalScopeCreationParams>,
WorkerReportingProxy&,
- PendingLayoutRegistry*,
- Agent*);
+ PendingLayoutRegistry*);
~LayoutWorkletGlobalScope() override;
void Dispose() final;
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/custom/layout_worklet_global_scope_proxy.cc b/chromium/third_party/blink/renderer/core/layout/ng/custom/layout_worklet_global_scope_proxy.cc
index b71ceac3b78..4a161756a61 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/custom/layout_worklet_global_scope_proxy.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/custom/layout_worklet_global_scope_proxy.cc
@@ -8,7 +8,6 @@
#include "third_party/blink/public/mojom/script/script_type.mojom-blink.h"
#include "third_party/blink/renderer/bindings/core/v8/script_source_code.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
-#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/local_frame_client.h"
@@ -33,29 +32,28 @@ LayoutWorkletGlobalScopeProxy::LayoutWorkletGlobalScopeProxy(
PendingLayoutRegistry* pending_layout_registry,
size_t global_scope_number) {
DCHECK(IsMainThread());
- Document* document = frame->GetDocument();
- reporting_proxy_ =
- std::make_unique<MainThreadWorkletReportingProxy>(document);
+ LocalDOMWindow* window = frame->DomWindow();
+ reporting_proxy_ = std::make_unique<MainThreadWorkletReportingProxy>(window);
String global_scope_name =
StringView("LayoutWorklet #") + String::Number(global_scope_number);
auto creation_params = std::make_unique<GlobalScopeCreationParams>(
- document->Url(), mojom::blink::ScriptType::kModule, global_scope_name,
- document->UserAgent(), frame->Client()->UserAgentMetadata(),
+ window->Url(), mojom::blink::ScriptType::kModule, global_scope_name,
+ window->UserAgent(), frame->Client()->UserAgentMetadata(),
frame->Client()->CreateWorkerFetchContext(),
- document->GetContentSecurityPolicy()->Headers(),
- document->GetReferrerPolicy(), document->GetSecurityOrigin(),
- document->IsSecureContext(), document->GetHttpsState(),
+ window->GetContentSecurityPolicy()->Headers(),
+ window->GetReferrerPolicy(), window->GetSecurityOrigin(),
+ window->IsSecureContext(), window->GetHttpsState(),
nullptr /* worker_clients */,
frame->Client()->CreateWorkerContentSettingsClient(),
- document->GetSecurityContext().AddressSpace(),
- OriginTrialContext::GetTokens(frame->DomWindow()).get(),
+ window->GetSecurityContext().AddressSpace(),
+ OriginTrialContext::GetTokens(window).get(),
base::UnguessableToken::Create(), nullptr /* worker_settings */,
kV8CacheOptionsDefault, module_responses_map,
mojo::NullRemote() /* browser_interface_broker */,
BeginFrameProviderParams(), nullptr /* parent_feature_policy */,
- base::UnguessableToken() /* agent_cluster_id */);
+ window->GetAgentClusterID());
global_scope_ = LayoutWorkletGlobalScope::Create(
frame, std::move(creation_params), *reporting_proxy_,
pending_layout_registry);
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/custom/layout_worklet_test.cc b/chromium/third_party/blink/renderer/core/layout/ng/custom/layout_worklet_test.cc
index 6d4e88f76bd..3bf55bf0798 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/custom/layout_worklet_test.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/custom/layout_worklet_test.cc
@@ -22,8 +22,8 @@ class LayoutWorkletTest : public PageTestBase {
public:
void SetUp() override {
PageTestBase::SetUp(IntSize());
- layout_worklet_ = MakeGarbageCollected<LayoutWorklet>(
- GetDocument().domWindow()->GetFrame());
+ layout_worklet_ =
+ MakeGarbageCollected<LayoutWorklet>(*GetDocument().domWindow());
proxy_ = layout_worklet_->CreateGlobalScope();
}
@@ -40,11 +40,13 @@ class LayoutWorkletTest : public PageTestBase {
proxy_ = nullptr;
}
- ScriptValue EvaluateScriptModule(const String& source_code) {
- ScriptState* script_state =
- GetGlobalScope()->ScriptController()->GetScriptState();
+ ScriptState* GetScriptState() {
+ return GetGlobalScope()->ScriptController()->GetScriptState();
+ }
+
+ ModuleEvaluationResult EvaluateScriptModule(const String& source_code) {
+ ScriptState* script_state = GetScriptState();
EXPECT_TRUE(script_state);
- ScriptState::Scope scope(script_state);
KURL js_url("https://example.com/worklet.js");
v8::Local<v8::Module> module = ModuleRecord::Compile(
@@ -66,14 +68,16 @@ class LayoutWorkletTest : public PageTestBase {
};
TEST_F(LayoutWorkletTest, ParseProperties) {
- EvaluateScriptModule(R"JS(
+ ScriptState::Scope scope(GetScriptState());
+ EXPECT_TRUE(EvaluateScriptModule(R"JS(
registerLayout('foo', class {
static get inputProperties() { return ['--prop', 'flex-basis', 'thing'] }
static get childInputProperties() { return ['--child-prop', 'margin-top', 'other-thing'] }
async intrinsicSizes() { }
async layout() { }
});
- )JS");
+ )JS")
+ .IsSuccess());
LayoutWorkletGlobalScope* global_scope = GetGlobalScope();
CSSLayoutDefinition* definition = global_scope->FindDefinition("foo");
@@ -100,16 +104,17 @@ TEST_F(LayoutWorkletTest, ParseProperties) {
// layout API actually have effects that we can test in script.
TEST_F(LayoutWorkletTest, RegisterLayout) {
- ScriptValue error = EvaluateScriptModule(R"JS(
+ ScriptState::Scope scope(GetScriptState());
+ ModuleEvaluationResult result = EvaluateScriptModule(R"JS(
registerLayout('foo', class {
async intrinsicSizes() { }
async layout() { }
});
)JS");
- EXPECT_TRUE(error.IsEmpty());
+ EXPECT_TRUE(result.IsSuccess());
- error = EvaluateScriptModule(R"JS(
+ result = EvaluateScriptModule(R"JS(
registerLayout('bar', class {
static get inputProperties() { return ['--prop'] }
static get childInputProperties() { return ['--child-prop'] }
@@ -118,21 +123,23 @@ TEST_F(LayoutWorkletTest, RegisterLayout) {
});
)JS");
- EXPECT_TRUE(error.IsEmpty());
+ EXPECT_TRUE(result.IsSuccess());
}
TEST_F(LayoutWorkletTest, RegisterLayout_EmptyName) {
- ScriptValue error = EvaluateScriptModule(R"JS(
+ ScriptState::Scope scope(GetScriptState());
+ ModuleEvaluationResult result = EvaluateScriptModule(R"JS(
registerLayout('', class {
});
)JS");
// "The empty string is not a valid name."
- EXPECT_FALSE(error.IsEmpty());
+ EXPECT_TRUE(result.IsException());
}
TEST_F(LayoutWorkletTest, RegisterLayout_Duplicate) {
- ScriptValue error = EvaluateScriptModule(R"JS(
+ ScriptState::Scope scope(GetScriptState());
+ ModuleEvaluationResult result = EvaluateScriptModule(R"JS(
registerLayout('foo', class {
async intrinsicSizes() { }
async layout() { }
@@ -144,87 +151,95 @@ TEST_F(LayoutWorkletTest, RegisterLayout_Duplicate) {
)JS");
// "A class with name:'foo' is already registered."
- EXPECT_FALSE(error.IsEmpty());
+ EXPECT_TRUE(result.IsException());
}
TEST_F(LayoutWorkletTest, RegisterLayout_NoIntrinsicSizes) {
- ScriptValue error = EvaluateScriptModule(R"JS(
+ ScriptState::Scope scope(GetScriptState());
+ ModuleEvaluationResult result = EvaluateScriptModule(R"JS(
registerLayout('foo', class {
});
)JS");
// "The 'intrinsicSizes' property on the prototype does not exist."
- EXPECT_FALSE(error.IsEmpty());
+ EXPECT_TRUE(result.IsException());
}
TEST_F(LayoutWorkletTest, RegisterLayout_ThrowingPropertyGetter) {
- ScriptValue error = EvaluateScriptModule(R"JS(
+ ScriptState::Scope scope(GetScriptState());
+ ModuleEvaluationResult result = EvaluateScriptModule(R"JS(
registerLayout('foo', class {
static get inputProperties() { throw Error(); }
});
)JS");
// "Uncaught Error"
- EXPECT_FALSE(error.IsEmpty());
+ EXPECT_TRUE(result.IsException());
}
TEST_F(LayoutWorkletTest, RegisterLayout_BadPropertyGetter) {
- ScriptValue error = EvaluateScriptModule(R"JS(
+ ScriptState::Scope scope(GetScriptState());
+ ModuleEvaluationResult result = EvaluateScriptModule(R"JS(
registerLayout('foo', class {
static get inputProperties() { return 42; }
});
)JS");
// "The provided value cannot be converted to a sequence."
- EXPECT_FALSE(error.IsEmpty());
+ EXPECT_TRUE(result.IsException());
}
TEST_F(LayoutWorkletTest, RegisterLayout_NoPrototype) {
- ScriptValue error = EvaluateScriptModule(R"JS(
+ ScriptState::Scope scope(GetScriptState());
+ ModuleEvaluationResult result = EvaluateScriptModule(R"JS(
const foo = function() { };
foo.prototype = undefined;
registerLayout('foo', foo);
)JS");
// "The 'prototype' object on the class does not exist."
- EXPECT_FALSE(error.IsEmpty());
+ EXPECT_TRUE(result.IsException());
}
TEST_F(LayoutWorkletTest, RegisterLayout_BadPrototype) {
- ScriptValue error = EvaluateScriptModule(R"JS(
+ ScriptState::Scope scope(GetScriptState());
+ ModuleEvaluationResult result = EvaluateScriptModule(R"JS(
const foo = function() { };
foo.prototype = 42;
registerLayout('foo', foo);
)JS");
// "The 'prototype' property on the class is not an object."
- EXPECT_FALSE(error.IsEmpty());
+ EXPECT_TRUE(result.IsException());
}
TEST_F(LayoutWorkletTest, RegisterLayout_BadIntrinsicSizes) {
- ScriptValue error = EvaluateScriptModule(R"JS(
+ ScriptState::Scope scope(GetScriptState());
+ ModuleEvaluationResult result = EvaluateScriptModule(R"JS(
registerLayout('foo', class {
get intrinsicSizes() { return 42; }
});
)JS");
// "The 'intrinsicSizes' property on the prototype is not a function."
- EXPECT_FALSE(error.IsEmpty());
+ EXPECT_TRUE(result.IsException());
}
TEST_F(LayoutWorkletTest, RegisterLayout_NoLayout) {
- ScriptValue error = EvaluateScriptModule(R"JS(
+ ScriptState::Scope scope(GetScriptState());
+ ModuleEvaluationResult result = EvaluateScriptModule(R"JS(
registerLayout('foo', class {
async intrinsicSizes() { }
});
)JS");
// "The 'layout' property on the prototype does not exist."
- EXPECT_FALSE(error.IsEmpty());
+ EXPECT_TRUE(result.IsException());
}
TEST_F(LayoutWorkletTest, RegisterLayout_BadLayout) {
- ScriptValue error = EvaluateScriptModule(R"JS(
+ ScriptState::Scope scope(GetScriptState());
+ ModuleEvaluationResult result = EvaluateScriptModule(R"JS(
registerLayout('foo', class {
async intrinsicSizes() { }
get layout() { return 42; }
@@ -232,7 +247,7 @@ TEST_F(LayoutWorkletTest, RegisterLayout_BadLayout) {
)JS");
// "The 'layout' property on the prototype is not a function."
- EXPECT_FALSE(error.IsEmpty());
+ EXPECT_TRUE(result.IsException());
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/custom/ng_custom_layout_algorithm.cc b/chromium/third_party/blink/renderer/core/layout/ng/custom/ng_custom_layout_algorithm.cc
index c763349959b..b2dbb2d6b09 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/custom/ng_custom_layout_algorithm.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/custom/ng_custom_layout_algorithm.cc
@@ -31,14 +31,9 @@ NGCustomLayoutAlgorithm::NGCustomLayoutAlgorithm(
container_builder_.SetIsNewFormattingContext(
params.space.IsNewFormattingContext());
container_builder_.SetInitialFragmentGeometry(params.fragment_geometry);
- const NGConstraintSpace& space = ConstraintSpace();
- child_percentage_resolution_block_size_for_min_max_ =
- CalculateChildPercentageBlockSizeForMinMax(
- space, Node(), border_padding_,
- space.PercentageResolutionBlockSize());
}
-base::Optional<MinMaxSizes> NGCustomLayoutAlgorithm::ComputeMinMaxSizes(
+MinMaxSizesResult NGCustomLayoutAlgorithm::ComputeMinMaxSizes(
const MinMaxSizesInput& input) const {
if (!Node().IsCustomLayoutLoaded())
return FallbackMinMaxSizes(input);
@@ -59,12 +54,13 @@ base::Optional<MinMaxSizes> NGCustomLayoutAlgorithm::ComputeMinMaxSizes(
return FallbackMinMaxSizes(input);
}
+ bool depends_on_percentage_block_size = false;
IntrinsicSizesResultOptions* intrinsic_sizes_result_options = nullptr;
if (!instance->IntrinsicSizes(
ConstraintSpace(), document, Node(),
container_builder_.InitialBorderBoxSize(), border_scrollbar_padding_,
- child_percentage_resolution_block_size_for_min_max_, &scope,
- intrinsic_sizes_result_options)) {
+ input.percentage_resolution_block_size, &scope,
+ &intrinsic_sizes_result_options, &depends_on_percentage_block_size)) {
// TODO(ikilpatrick): Report this error to the developer.
return FallbackMinMaxSizes(input);
}
@@ -79,7 +75,7 @@ base::Optional<MinMaxSizes> NGCustomLayoutAlgorithm::ComputeMinMaxSizes(
sizes.min_size.ClampNegativeToZero();
sizes.max_size.ClampNegativeToZero();
- return sizes;
+ return {sizes, depends_on_percentage_block_size};
}
scoped_refptr<const NGLayoutResult> NGCustomLayoutAlgorithm::Layout() {
@@ -106,11 +102,10 @@ scoped_refptr<const NGLayoutResult> NGCustomLayoutAlgorithm::Layout() {
FragmentResultOptions* fragment_result_options = nullptr;
scoped_refptr<SerializedScriptValue> fragment_result_data;
- if (!instance->Layout(
- ConstraintSpace(), document, Node(),
- container_builder_.InitialBorderBoxSize(), border_scrollbar_padding_,
- child_percentage_resolution_block_size_for_min_max_, &scope,
- fragment_result_options, &fragment_result_data)) {
+ if (!instance->Layout(ConstraintSpace(), document, Node(),
+ container_builder_.InitialBorderBoxSize(),
+ border_scrollbar_padding_, &scope,
+ fragment_result_options, &fragment_result_data)) {
// TODO(ikilpatrick): Report this error to the developer.
return FallbackLayout();
}
@@ -164,7 +159,8 @@ scoped_refptr<const NGLayoutResult> NGCustomLayoutAlgorithm::Layout() {
border_padding_.BlockSum(),
LayoutUnit::FromDoubleRound(fragment_result_options->autoBlockSize()));
LayoutUnit block_size = ComputeBlockSizeForFragment(
- ConstraintSpace(), Style(), border_padding_, auto_block_size);
+ ConstraintSpace(), Style(), border_padding_, auto_block_size,
+ container_builder_.InitialBorderBoxSize().inline_size);
if (fragment_result_options->hasBaseline()) {
LayoutUnit baseline =
@@ -200,15 +196,13 @@ void NGCustomLayoutAlgorithm::AddAnyOutOfFlowPositionedChildren(
}
}
-base::Optional<MinMaxSizes> NGCustomLayoutAlgorithm::FallbackMinMaxSizes(
+MinMaxSizesResult NGCustomLayoutAlgorithm::FallbackMinMaxSizes(
const MinMaxSizesInput& input) const {
- NGBlockLayoutAlgorithm algorithm(params_);
- return algorithm.ComputeMinMaxSizes(input);
+ return NGBlockLayoutAlgorithm(params_).ComputeMinMaxSizes(input);
}
scoped_refptr<const NGLayoutResult> NGCustomLayoutAlgorithm::FallbackLayout() {
- NGBlockLayoutAlgorithm algorithm(params_);
- return algorithm.Layout();
+ return NGBlockLayoutAlgorithm(params_).Layout();
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/custom/ng_custom_layout_algorithm.h b/chromium/third_party/blink/renderer/core/layout/ng/custom/ng_custom_layout_algorithm.h
index 5a43340b4a0..2ba330632c7 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/custom/ng_custom_layout_algorithm.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/custom/ng_custom_layout_algorithm.h
@@ -20,20 +20,17 @@ class CORE_EXPORT NGCustomLayoutAlgorithm
public:
NGCustomLayoutAlgorithm(const NGLayoutAlgorithmParams& params);
- base::Optional<MinMaxSizes> ComputeMinMaxSizes(
- const MinMaxSizesInput&) const override;
+ MinMaxSizesResult ComputeMinMaxSizes(const MinMaxSizesInput&) const override;
scoped_refptr<const NGLayoutResult> Layout() override;
private:
void AddAnyOutOfFlowPositionedChildren(NGLayoutInputNode* child);
- base::Optional<MinMaxSizes> FallbackMinMaxSizes(
- const MinMaxSizesInput&) const;
+ MinMaxSizesResult FallbackMinMaxSizes(const MinMaxSizesInput&) const;
scoped_refptr<const NGLayoutResult> FallbackLayout();
const NGLayoutAlgorithmParams& params_;
const NGBoxStrut border_padding_;
const NGBoxStrut border_scrollbar_padding_;
- LayoutUnit child_percentage_resolution_block_size_for_min_max_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_flexible_box.cc b/chromium/third_party/blink/renderer/core/layout/ng/flex/layout_ng_flexible_box.cc
index a74fdfe086d..7ecffbcf6c1 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_flexible_box.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/flex/layout_ng_flexible_box.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "third_party/blink/renderer/core/layout/ng/layout_ng_flexible_box.h"
+#include "third_party/blink/renderer/core/layout/ng/flex/layout_ng_flexible_box.h"
#include "third_party/blink/renderer/core/layout/layout_analyzer.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_flexible_box.h b/chromium/third_party/blink/renderer/core/layout/ng/flex/layout_ng_flexible_box.h
index f1a361e1b56..bd7ae7499d1 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_flexible_box.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/flex/layout_ng_flexible_box.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_LAYOUT_NG_FLEXIBLE_BOX_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_LAYOUT_NG_FLEXIBLE_BOX_H_
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_FLEX_LAYOUT_NG_FLEXIBLE_BOX_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_FLEX_LAYOUT_NG_FLEXIBLE_BOX_H_
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/layout/layout_block.h"
@@ -35,4 +35,4 @@ class CORE_EXPORT LayoutNGFlexibleBox : public LayoutNGMixin<LayoutBlock> {
} // namespace blink
-#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_LAYOUT_NG_FLEXIBLE_BOX_H_
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_FLEX_LAYOUT_NG_FLEXIBLE_BOX_H_
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_flex_child_iterator.cc b/chromium/third_party/blink/renderer/core/layout/ng/flex/ng_flex_child_iterator.cc
index 350d605af11..6272d011118 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_flex_child_iterator.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/flex/ng_flex_child_iterator.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "third_party/blink/renderer/core/layout/ng/ng_flex_child_iterator.h"
+#include "third_party/blink/renderer/core/layout/ng/flex/ng_flex_child_iterator.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_flex_child_iterator.h b/chromium/third_party/blink/renderer/core/layout/ng/flex/ng_flex_child_iterator.h
index 609483fc790..36b30182622 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_flex_child_iterator.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/flex/ng_flex_child_iterator.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_FLEX_CHILD_ITERATOR_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_FLEX_CHILD_ITERATOR_H_
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_FLEX_NG_FLEX_CHILD_ITERATOR_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_FLEX_NG_FLEX_CHILD_ITERATOR_H_
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/layout/ng/ng_block_node.h"
@@ -50,4 +50,4 @@ class CORE_EXPORT NGFlexChildIterator {
WTF_ALLOW_MOVE_AND_INIT_WITH_MEM_FUNCTIONS(
blink::NGFlexChildIterator::ChildWithOrder)
-#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_FLEX_CHILD_ITERATOR_H_
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_FLEX_NG_FLEX_CHILD_ITERATOR_H_
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_flex_layout_algorithm.cc b/chromium/third_party/blink/renderer/core/layout/ng/flex/ng_flex_layout_algorithm.cc
index 21c01f8a5be..6de92e5be92 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_flex_layout_algorithm.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/flex/ng_flex_layout_algorithm.cc
@@ -2,18 +2,19 @@
// 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/core/layout/ng/ng_flex_layout_algorithm.h"
+#include "third_party/blink/renderer/core/layout/ng/flex/ng_flex_layout_algorithm.h"
#include <memory>
#include "third_party/blink/renderer/core/layout/flexible_box_algorithm.h"
#include "third_party/blink/renderer/core/layout/layout_box.h"
#include "third_party/blink/renderer/core/layout/layout_flexible_box.h"
+#include "third_party/blink/renderer/core/layout/ng/flex/ng_flex_child_iterator.h"
#include "third_party/blink/renderer/core/layout/ng/ng_block_break_token.h"
#include "third_party/blink/renderer/core/layout/ng/ng_box_fragment.h"
#include "third_party/blink/renderer/core/layout/ng/ng_constraint_space.h"
#include "third_party/blink/renderer/core/layout/ng/ng_constraint_space_builder.h"
-#include "third_party/blink/renderer/core/layout/ng/ng_flex_child_iterator.h"
#include "third_party/blink/renderer/core/layout/ng/ng_fragment.h"
+#include "third_party/blink/renderer/core/layout/ng/ng_layout_input_node.h"
#include "third_party/blink/renderer/core/layout/ng/ng_length_utils.h"
#include "third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.h"
#include "third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h"
@@ -42,7 +43,9 @@ NGFlexLayoutAlgorithm::NGFlexLayoutAlgorithm(
ShrinkAvailableSize(border_box_size_, border_scrollbar_padding_);
child_percentage_size_ = CalculateChildPercentageSize(
ConstraintSpace(), Node(), content_box_size_);
- algorithm_.emplace(&Style(), MainAxisContentExtent(LayoutUnit::Max()));
+
+ algorithm_.emplace(&Style(), MainAxisContentExtent(LayoutUnit::Max()),
+ child_percentage_size_, &Node().GetDocument());
}
bool NGFlexLayoutAlgorithm::MainAxisIsInlineAxis(
@@ -54,10 +57,17 @@ bool NGFlexLayoutAlgorithm::MainAxisIsInlineAxis(
LayoutUnit NGFlexLayoutAlgorithm::MainAxisContentExtent(
LayoutUnit sum_hypothetical_main_size) const {
if (Style().ResolvedIsColumnFlexDirection()) {
- return ComputeBlockSizeForFragment(
- ConstraintSpace(), Style(), border_padding_,
- sum_hypothetical_main_size +
- border_scrollbar_padding_.BlockSum()) -
+ // Even though we only pass border_padding_ in the third parameter, the
+ // return value includes scrollbar, so subtract scrollbar to get content
+ // size.
+ // We add border_scrollbar_padding to the fourth parameter because
+ // |content_size| needs to be the size of the border box. We've overloaded
+ // the term "content".
+ return ComputeBlockSizeForFragment(ConstraintSpace(), Style(),
+ border_padding_,
+ sum_hypothetical_main_size +
+ border_scrollbar_padding_.BlockSum(),
+ border_box_size_.inline_size) -
border_scrollbar_padding_.BlockSum();
}
return content_box_size_.inline_size;
@@ -331,8 +341,9 @@ LayoutUnit CalculateFixedCrossSize(LayoutUnit available_size,
NGConstraintSpace NGFlexLayoutAlgorithm::BuildSpaceForIntrinsicBlockSize(
const NGBlockNode& flex_item,
- const NGPhysicalBoxStrut& physical_margins,
- const MinMaxSizes& cross_axis_min_max) const {
+ const NGPhysicalBoxStrut& physical_margins = NGPhysicalBoxStrut(),
+ const MinMaxSizes& cross_axis_min_max = MinMaxSizes{
+ kIndefiniteSize, kIndefiniteSize}) const {
const ComputedStyle& child_style = flex_item.Style();
NGConstraintSpaceBuilder space_builder(ConstraintSpace(),
child_style.GetWritingMode(),
@@ -346,7 +357,8 @@ NGConstraintSpace NGFlexLayoutAlgorithm::BuildSpaceForIntrinsicBlockSize(
LogicalSize child_available_size = content_box_size_;
if (ShouldItemShrinkToFit(flex_item)) {
space_builder.SetIsShrinkToFit(true);
- } else if (WillChildCrossSizeBeContainerCrossSize(flex_item)) {
+ } else if (cross_axis_min_max.min_size != kIndefiniteSize &&
+ WillChildCrossSizeBeContainerCrossSize(flex_item)) {
if (is_column_) {
space_builder.SetIsFixedInlineSize(true);
child_available_size.inline_size =
@@ -426,21 +438,23 @@ void NGFlexLayoutAlgorithm::ConstructAndAppendFlexItems() {
is_horizontal_flow_ ? physical_border_padding.VerticalSum()
: physical_border_padding.HorizontalSum();
- base::Optional<MinMaxSizes> min_max_size;
- auto MinMaxSizesFunc = [&]() -> MinMaxSizes {
- if (!min_max_size) {
- if (child.Style().OverflowBlockDirection() == EOverflow::kAuto) {
+ base::Optional<MinMaxSizesResult> min_max_sizes;
+ auto MinMaxSizesFunc = [&]() -> MinMaxSizesResult {
+ if (!min_max_sizes) {
+ NGConstraintSpace child_space = BuildSpaceForIntrinsicBlockSize(child);
+ if (child_style.OverflowBlockDirection() == EOverflow::kAuto) {
// Ensure this child has been laid out so its auto scrollbars are
// included in its intrinsic sizes.
- child.Layout(flex_basis_space);
+ child.Layout(child_space);
}
- // We want the child's min/max size in its writing mode, not ours.
- // We'll only ever use it if the child's inline axis is our main axis.
- min_max_size = child.ComputeMinMaxSizes(
+ // We want the child's intrinsic inline sizes in its writing mode, so
+ // pass child's writing mode as the first parameter, which is nominally
+ // |container_writing_mode|.
+ min_max_sizes = child.ComputeMinMaxSizes(
child_style.GetWritingMode(),
- MinMaxSizesInput(content_box_size_.block_size), &flex_basis_space);
+ MinMaxSizesInput(content_box_size_.block_size), &child_space);
}
- return *min_max_size;
+ return *min_max_sizes;
};
MinMaxSizes min_max_sizes_in_main_axis_direction{main_axis_border_padding,
@@ -548,7 +562,9 @@ void NGFlexLayoutAlgorithm::ConstructAndAppendFlexItems() {
cross_size = min_max_sizes_in_cross_axis_direction.ClampSizeToMinAndMax(
cross_size);
flex_base_border_box =
- LayoutUnit(cross_size * GetMainOverCrossAspectRatio(child));
+ LayoutUnit((cross_size - cross_axis_border_padding) *
+ GetMainOverCrossAspectRatio(child) +
+ main_axis_border_padding);
} else if (MainAxisIsInlineAxis(child)) {
// We're now in parts C, D, and E for what are usually (horizontal-tb
// containers AND children) row flex containers. I _think_ the C and D
@@ -559,10 +575,12 @@ void NGFlexLayoutAlgorithm::ConstructAndAppendFlexItems() {
// is not exactly correct.
// TODO(dgrogan): Replace with a variant of ComputeReplacedSize that
// ignores min-width, width, max-width.
+ MinMaxSizesInput input(child_percentage_size_.block_size);
flex_base_border_box =
- child.GetLayoutBox()->PreferredLogicalWidths().max_size;
+ ComputeMinAndMaxContentContribution(Style(), child, input)
+ .sizes.max_size;
} else {
- flex_base_border_box = MinMaxSizesFunc().max_size;
+ flex_base_border_box = MinMaxSizesFunc().sizes.max_size;
}
} else {
// Parts C, D, and E for what are usually column flex containers.
@@ -602,116 +620,109 @@ void NGFlexLayoutAlgorithm::ConstructAndAppendFlexItems() {
const Length& min = is_horizontal_flow_ ? child.Style().MinWidth()
: child.Style().MinHeight();
- // TODO(dgrogan): min.IsIntrinsic should enter this block when it's in the
- // item's block direction.
- if (min.IsAuto()) {
- if (algorithm_->ShouldApplyMinSizeAutoForChild(*child.GetLayoutBox())) {
- // TODO(dgrogan): This should probably apply to column flexboxes also,
- // but that's not what legacy does.
- if (child.IsTable() && !is_column_) {
- MinMaxSizes table_preferred_widths =
- ComputeMinAndMaxContentContribution(
- Style(), child,
- MinMaxSizesInput(child_percentage_size_.block_size));
- min_max_sizes_in_main_axis_direction.min_size =
- table_preferred_widths.min_size;
+ if (algorithm_->ShouldApplyMinSizeAutoForChild(*child.GetLayoutBox())) {
+ // TODO(dgrogan): This should probably apply to column flexboxes also,
+ // but that's not what legacy does.
+ if (child.IsTable() && !is_column_) {
+ MinMaxSizes table_preferred_widths =
+ ComputeMinAndMaxContentContribution(
+ Style(), child,
+ MinMaxSizesInput(child_percentage_size_.block_size))
+ .sizes;
+ min_max_sizes_in_main_axis_direction.min_size =
+ table_preferred_widths.min_size;
+ } else {
+ LayoutUnit content_size_suggestion;
+ if (MainAxisIsInlineAxis(child)) {
+ content_size_suggestion = MinMaxSizesFunc().sizes.min_size;
} else {
- LayoutUnit content_size_suggestion;
- if (MainAxisIsInlineAxis(child)) {
- content_size_suggestion = MinMaxSizesFunc().min_size;
+ LayoutUnit intrinsic_block_size;
+ if (child.IsReplaced()) {
+ base::Optional<LayoutUnit> computed_inline_size;
+ base::Optional<LayoutUnit> computed_block_size;
+ child.IntrinsicSize(&computed_inline_size, &computed_block_size);
+
+ // The 150 is for replaced elements that have no size, which SVG
+ // can have (maybe others?).
+ intrinsic_block_size =
+ computed_block_size.value_or(LayoutUnit(150)) +
+ border_padding_in_child_writing_mode.BlockSum();
} else {
- LayoutUnit intrinsic_block_size;
- if (child.HasAspectRatio()) {
- base::Optional<LayoutUnit> computed_inline_size;
- base::Optional<LayoutUnit> computed_block_size;
- child.IntrinsicSize(&computed_inline_size, &computed_block_size);
-
- // The 150 is for elements that have an aspect ratio but no size,
- // which SVG can have (maybe others?).
- intrinsic_block_size =
- computed_block_size.value_or(LayoutUnit(150));
- } else {
- intrinsic_block_size = IntrinsicBlockSizeFunc();
- }
- content_size_suggestion = intrinsic_block_size;
+ intrinsic_block_size = IntrinsicBlockSizeFunc();
}
+ content_size_suggestion = intrinsic_block_size;
+ }
+ DCHECK_GE(content_size_suggestion, main_axis_border_padding);
+ if (child.HasAspectRatio()) {
+ content_size_suggestion =
+ AdjustChildSizeForAspectRatioCrossAxisMinAndMax(
+ child, content_size_suggestion,
+ min_max_sizes_in_cross_axis_direction.min_size,
+ min_max_sizes_in_cross_axis_direction.max_size,
+ main_axis_border_padding, cross_axis_border_padding);
+ }
- if (child.HasAspectRatio()) {
- // TODO(dgrogan): We're including borders/padding in both
- // content_size_suggestion and
- // min_max_sizes_in_cross_axis_direction. Maybe we need to multiply
- // the content size by the aspect ratio and then apply the
- // border/padding from the other axis inside the Adjust* function.
- // Test legacy/firefox. Start with
- // https://jsfiddle.net/dgrogan/9uyg3aro/
- content_size_suggestion =
- AdjustChildSizeForAspectRatioCrossAxisMinAndMax(
- child, content_size_suggestion,
- min_max_sizes_in_cross_axis_direction.min_size,
- min_max_sizes_in_cross_axis_direction.max_size);
- }
-
- LayoutUnit specified_size_suggestion = LayoutUnit::Max();
- // If the item’s computed main size property is definite, then the
- // specified size suggestion is that size.
- if (MainAxisIsInlineAxis(child)) {
- if (!specified_length_in_main_axis.IsAuto()) {
- // TODO(dgrogan): Optimization opportunity: we may have already
- // resolved specified_length_in_main_axis in the flex basis
- // calculation. Reuse that if possible.
- specified_size_suggestion = ResolveMainInlineLength(
- flex_basis_space, child_style,
- border_padding_in_child_writing_mode, MinMaxSizesFunc,
- specified_length_in_main_axis);
- }
- } else if (!BlockLengthUnresolvable(flex_basis_space,
- specified_length_in_main_axis,
- LengthResolvePhase::kLayout)) {
- specified_size_suggestion = ResolveMainBlockLength(
+ LayoutUnit specified_size_suggestion = LayoutUnit::Max();
+ // If the item’s computed main size property is definite, then the
+ // specified size suggestion is that size.
+ if (MainAxisIsInlineAxis(child)) {
+ if (!specified_length_in_main_axis.IsAuto()) {
+ // TODO(dgrogan): Optimization opportunity: we may have already
+ // resolved specified_length_in_main_axis in the flex basis
+ // calculation. Reuse that if possible.
+ specified_size_suggestion = ResolveMainInlineLength(
flex_basis_space, child_style,
- border_padding_in_child_writing_mode,
- specified_length_in_main_axis, IntrinsicBlockSizeFunc,
- LengthResolvePhase::kLayout);
- DCHECK_NE(specified_size_suggestion, kIndefiniteSize);
+ border_padding_in_child_writing_mode, MinMaxSizesFunc,
+ specified_length_in_main_axis);
}
+ } else if (!BlockLengthUnresolvable(flex_basis_space,
+ specified_length_in_main_axis,
+ LengthResolvePhase::kLayout)) {
+ specified_size_suggestion = ResolveMainBlockLength(
+ flex_basis_space, child_style,
+ border_padding_in_child_writing_mode,
+ specified_length_in_main_axis, IntrinsicBlockSizeFunc,
+ LengthResolvePhase::kLayout);
+ DCHECK_NE(specified_size_suggestion, kIndefiniteSize);
+ }
- LayoutUnit transferred_size_suggestion = LayoutUnit::Max();
- if (specified_size_suggestion == LayoutUnit::Max() &&
- child.HasAspectRatio()) {
- const Length& cross_axis_length = is_horizontal_flow_
- ? child_style.Height()
- : child_style.Width();
- if (IsItemCrossAxisLengthDefinite(child, cross_axis_length)) {
- LayoutUnit cross_axis_size;
- if (MainAxisIsInlineAxis(child)) {
- cross_axis_size = ResolveMainBlockLength(
- flex_basis_space, child_style,
- border_padding_in_child_writing_mode, cross_axis_length,
- kIndefiniteSize, LengthResolvePhase::kLayout);
- DCHECK_NE(cross_axis_size, kIndefiniteSize);
- } else {
- cross_axis_size = ResolveMainInlineLength(
- flex_basis_space, child_style,
- border_padding_in_child_writing_mode, MinMaxSizesFunc,
- cross_axis_length);
- }
- double ratio = GetMainOverCrossAspectRatio(child);
- transferred_size_suggestion = LayoutUnit(
- ratio *
- min_max_sizes_in_cross_axis_direction.ClampSizeToMinAndMax(
- cross_axis_size));
+ LayoutUnit transferred_size_suggestion = LayoutUnit::Max();
+ if (specified_size_suggestion == LayoutUnit::Max() &&
+ child.HasAspectRatio()) {
+ const Length& cross_axis_length =
+ is_horizontal_flow_ ? child_style.Height() : child_style.Width();
+ if (IsItemCrossAxisLengthDefinite(child, cross_axis_length)) {
+ LayoutUnit cross_axis_size;
+ if (MainAxisIsInlineAxis(child)) {
+ cross_axis_size = ResolveMainBlockLength(
+ flex_basis_space, child_style,
+ border_padding_in_child_writing_mode, cross_axis_length,
+ kIndefiniteSize, LengthResolvePhase::kLayout);
+ DCHECK_NE(cross_axis_size, kIndefiniteSize);
+ } else {
+ cross_axis_size =
+ ResolveMainInlineLength(flex_basis_space, child_style,
+ border_padding_in_child_writing_mode,
+ MinMaxSizesFunc, cross_axis_length);
}
+ double ratio = GetMainOverCrossAspectRatio(child);
+ transferred_size_suggestion = LayoutUnit(
+ main_axis_border_padding +
+ ratio *
+ (min_max_sizes_in_cross_axis_direction.ClampSizeToMinAndMax(
+ cross_axis_size) -
+ cross_axis_border_padding));
}
+ }
- DCHECK(specified_size_suggestion == LayoutUnit::Max() ||
- transferred_size_suggestion == LayoutUnit::Max());
+ DCHECK(specified_size_suggestion == LayoutUnit::Max() ||
+ transferred_size_suggestion == LayoutUnit::Max());
- min_max_sizes_in_main_axis_direction.min_size =
- std::min({specified_size_suggestion, content_size_suggestion,
- transferred_size_suggestion,
- min_max_sizes_in_main_axis_direction.max_size});
- }
+ min_max_sizes_in_main_axis_direction.min_size =
+ std::min({specified_size_suggestion, content_size_suggestion,
+ transferred_size_suggestion,
+ min_max_sizes_in_main_axis_direction.max_size});
}
} else if (MainAxisIsInlineAxis(child)) {
min_max_sizes_in_main_axis_direction.min_size = ResolveMinInlineLength(
@@ -726,8 +737,6 @@ void NGFlexLayoutAlgorithm::ConstructAndAppendFlexItems() {
DCHECK_GE(min_max_sizes_in_main_axis_direction.min_size, 0);
DCHECK_GE(min_max_sizes_in_main_axis_direction.max_size, 0);
- // TODO(dgrogan): Should min_max_sizes_in_cross_axis_direction include
- // cross_axis_border_padding?
algorithm_
->emplace_back(nullptr, child.Style(), flex_base_content_size,
min_max_sizes_in_main_axis_direction,
@@ -741,9 +750,11 @@ void NGFlexLayoutAlgorithm::ConstructAndAppendFlexItems() {
LayoutUnit
NGFlexLayoutAlgorithm::AdjustChildSizeForAspectRatioCrossAxisMinAndMax(
const NGBlockNode& child,
- LayoutUnit content_suggestion,
+ LayoutUnit content_size_suggestion,
LayoutUnit cross_min,
- LayoutUnit cross_max) {
+ LayoutUnit cross_max,
+ LayoutUnit main_axis_border_padding,
+ LayoutUnit cross_axis_border_padding) {
DCHECK(child.HasAspectRatio());
double ratio = GetMainOverCrossAspectRatio(child);
@@ -752,23 +763,31 @@ NGFlexLayoutAlgorithm::AdjustChildSizeForAspectRatioCrossAxisMinAndMax(
const Length& cross_max_length = is_horizontal_flow_
? child.Style().MaxHeight()
: child.Style().MaxWidth();
+ DCHECK_GE(cross_max, cross_axis_border_padding);
// TODO(dgrogan): No tests fail if we unconditionally apply max_main_length.
// Either add a test that needs it or remove it.
if (IsItemCrossAxisLengthDefinite(child, cross_max_length)) {
- LayoutUnit max_main_length = LayoutUnit(cross_max * ratio);
- content_suggestion = std::min(max_main_length, content_suggestion);
+ LayoutUnit max_main_length =
+ main_axis_border_padding +
+ LayoutUnit((cross_max - cross_axis_border_padding) * ratio);
+ content_size_suggestion =
+ std::min(max_main_length, content_size_suggestion);
}
const Length& cross_min_length = is_horizontal_flow_
? child.Style().MinHeight()
: child.Style().MinWidth();
+ DCHECK_GE(cross_min, cross_axis_border_padding);
// TODO(dgrogan): Same as above with min_main_length here -- it may be
// unneeded or untested.
if (IsItemCrossAxisLengthDefinite(child, cross_min_length)) {
- LayoutUnit min_main_length = LayoutUnit(cross_min * ratio);
- content_suggestion = std::max(min_main_length, content_suggestion);
+ LayoutUnit min_main_length =
+ main_axis_border_padding +
+ LayoutUnit((cross_min - cross_axis_border_padding) * ratio);
+ content_size_suggestion =
+ std::max(min_main_length, content_size_suggestion);
}
- return content_suggestion;
+ return content_size_suggestion;
}
scoped_refptr<const NGLayoutResult> NGFlexLayoutAlgorithm::Layout() {
@@ -847,6 +866,16 @@ scoped_refptr<const NGLayoutResult> NGFlexLayoutAlgorithm::Layout() {
available_size.block_size = CalculateFixedCrossSize(
available_size.block_size, flex_item.min_max_cross_sizes.value(),
margins.BlockSum());
+ } else if (DoesItemStretch(flex_item.ng_input_node)) {
+ // If we are in a row flexbox, and we don't have a fixed block-size
+ // (yet), use the "measure" cache slot. This will be the first
+ // layout, and we will use the "layout" cache slot if this gets
+ // stretched later.
+ //
+ // Setting the "measure" cache slot on the space writes the result
+ // into both the "measure", and "layout" cache slots. If a subsequent
+ // "layout" occurs, it'll just get written into the "layout" slot.
+ space_builder.SetCacheSlot(NGCacheSlot::kMeasure);
}
}
@@ -891,7 +920,8 @@ scoped_refptr<const NGLayoutResult> NGFlexLayoutAlgorithm::Layout() {
ClampIntrinsicBlockSize(ConstraintSpace(), Node(),
border_scrollbar_padding_, intrinsic_block_size);
LayoutUnit block_size = ComputeBlockSizeForFragment(
- ConstraintSpace(), Style(), border_padding_, intrinsic_block_size);
+ ConstraintSpace(), Style(), border_padding_, intrinsic_block_size,
+ border_box_size_.inline_size);
container_builder_.SetIntrinsicBlockSize(intrinsic_block_size);
container_builder_.SetBlockSize(block_size);
@@ -1057,51 +1087,57 @@ void NGFlexLayoutAlgorithm::PropagateBaselineFromChild(
*fallback_baseline = fallback_baseline->value_or(baseline_offset);
}
-base::Optional<MinMaxSizes> NGFlexLayoutAlgorithm::ComputeMinMaxSizes(
- const MinMaxSizesInput& input) const {
- base::Optional<MinMaxSizes> sizes =
- CalculateMinMaxSizesIgnoringChildren(Node(), border_scrollbar_padding_);
- if (sizes)
- return sizes;
-
- sizes.emplace();
- LayoutUnit child_percentage_resolution_block_size =
- CalculateChildPercentageBlockSizeForMinMax(
- ConstraintSpace(), Node(), border_padding_,
- input.percentage_resolution_block_size);
+MinMaxSizesResult NGFlexLayoutAlgorithm::ComputeMinMaxSizes(
+ const MinMaxSizesInput& child_input) const {
+ if (auto result = CalculateMinMaxSizesIgnoringChildren(
+ Node(), border_scrollbar_padding_))
+ return *result;
- MinMaxSizesInput child_input(child_percentage_resolution_block_size);
+ MinMaxSizes sizes;
+ bool depends_on_percentage_block_size = false;
+ int number_of_items = 0;
NGFlexChildIterator iterator(Node());
for (NGBlockNode child = iterator.NextChild(); child;
child = iterator.NextChild()) {
if (child.IsOutOfFlowPositioned())
continue;
+ number_of_items++;
- MinMaxSizes child_min_max_sizes =
+ MinMaxSizesResult child_result =
ComputeMinAndMaxContentContribution(Style(), child, child_input);
NGBoxStrut child_margins = ComputeMinMaxMargins(Style(), child);
- child_min_max_sizes += child_margins.InlineSum();
+ child_result.sizes += child_margins.InlineSum();
+
+ depends_on_percentage_block_size |=
+ child_result.depends_on_percentage_block_size;
if (is_column_) {
- sizes->min_size = std::max(sizes->min_size, child_min_max_sizes.min_size);
- sizes->max_size = std::max(sizes->max_size, child_min_max_sizes.max_size);
+ sizes.min_size = std::max(sizes.min_size, child_result.sizes.min_size);
+ sizes.max_size = std::max(sizes.max_size, child_result.sizes.max_size);
} else {
- sizes->max_size += child_min_max_sizes.max_size;
+ sizes.max_size += child_result.sizes.max_size;
if (algorithm_->IsMultiline()) {
- sizes->min_size =
- std::max(sizes->min_size, child_min_max_sizes.min_size);
+ sizes.min_size = std::max(sizes.min_size, child_result.sizes.min_size);
} else {
- sizes->min_size += child_min_max_sizes.min_size;
+ sizes.min_size += child_result.sizes.min_size;
}
}
}
- sizes->max_size = std::max(sizes->max_size, sizes->min_size);
+ if (!is_column_) {
+ LayoutUnit gap_inline_size =
+ (number_of_items - 1) * algorithm_->gap_between_items_;
+ sizes.max_size += gap_inline_size;
+ if (!algorithm_->IsMultiline()) {
+ sizes.min_size += gap_inline_size;
+ }
+ }
+ sizes.max_size = std::max(sizes.max_size, sizes.min_size);
// Due to negative margins, it is possible that we calculated a negative
// intrinsic width. Make sure that we never return a negative width.
- sizes->Encompass(LayoutUnit());
- *sizes += border_scrollbar_padding_.InlineSum();
- return sizes;
+ sizes.Encompass(LayoutUnit());
+ sizes += border_scrollbar_padding_.InlineSum();
+ return {sizes, depends_on_percentage_block_size};
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_flex_layout_algorithm.h b/chromium/third_party/blink/renderer/core/layout/ng/flex/ng_flex_layout_algorithm.h
index 066277e3075..e0e33c2bdc6 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_flex_layout_algorithm.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/flex/ng_flex_layout_algorithm.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_FLEX_LAYOUT_ALGORITHM_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_FLEX_LAYOUT_ALGORITHM_H_
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_FLEX_NG_FLEX_LAYOUT_ALGORITHM_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_FLEX_NG_FLEX_LAYOUT_ALGORITHM_H_
#include "third_party/blink/renderer/core/layout/ng/ng_layout_algorithm.h"
@@ -25,8 +25,7 @@ class CORE_EXPORT NGFlexLayoutAlgorithm
scoped_refptr<const NGLayoutResult> Layout() override;
- base::Optional<MinMaxSizes> ComputeMinMaxSizes(
- const MinMaxSizesInput&) const override;
+ MinMaxSizesResult ComputeMinMaxSizes(const MinMaxSizesInput&) const override;
private:
bool DoesItemCrossSizeComputeToAuto(const NGBlockNode& child) const;
@@ -45,7 +44,9 @@ class CORE_EXPORT NGFlexLayoutAlgorithm
const NGBlockNode& child,
LayoutUnit content_suggestion,
LayoutUnit cross_min,
- LayoutUnit cross_max);
+ LayoutUnit cross_max,
+ LayoutUnit main_axis_border_padding,
+ LayoutUnit cross_axis_border_padding);
bool IsColumnContainerMainSizeDefinite() const;
bool IsContainerCrossSizeDefinite() const;
@@ -87,4 +88,4 @@ class CORE_EXPORT NGFlexLayoutAlgorithm
} // namespace blink
-#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_FLEX_LAYOUT_ALGORITHM_H_
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_FLEX_NG_FLEX_LAYOUT_ALGORITHM_H_
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/README.md b/chromium/third_party/blink/renderer/core/layout/ng/inline/README.md
index a9b42d7c716..0ddc51ec99d 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/README.md
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/README.md
@@ -279,6 +279,38 @@ responsible for computing different baseline types from font metrics.
[dominant-baseline]: https://drafts.csswg.org/css-inline/#dominant-baseline-property
[writing-mode]: https://drafts.csswg.org/css-writing-modes-3/#propdef-writing-mode
+### <a name="culled"></a>Culled Inline ###
+[Culled inline]: #culled
+
+For performance and memory consumption,
+Blink ignores some inline-boxes during inline layout
+because they don't impact layout nor they are needed for paint purposes.
+An example of this is
+```html
+<span style="border: 1px solid blue"><b>Text</b></span>
+```
+The `<b>` has the same size as the inner text-node
+so it can be ignored for layout purpose,
+while the `<span>` has borders, which impacts paint,
+so it produces a box fragment.
+This optimization is called "culled inline" in the code.
+
+LayoutNG uses similar criteria as legacy engine
+on whether to generate a fragment or not,
+but LayoutNG generates fragments in a little more cases than legacy
+in order to improve the accuracy of hit-testing and bounding rects.
+This is determined by `ShouldCreateBoxFragment()`,
+which is primarily computed during style recalc,
+but layout may also turn it on when the need is discovered during layout.
+
+One downside of this optimization is that we have extra work to do when
+querying post-layout information; e.g., hit-testing or asking for bounding rects.
+
+Another downside is making a culled inline box not to be culled requires re-layout
+even if the change does not affect layout; e.g., adding background.
+To mitigate multiple layouts by like hover highlighting,
+`ShouldCreateBoxFragment()` will not be reset once it's set.
+
### <a name="bidi"></a>Bidirectional Text ###
[Bidirectional Text]: #bidi
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_abstract_inline_text_box.cc b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_abstract_inline_text_box.cc
index 34643cd55f2..8acb82aec9a 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_abstract_inline_text_box.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_abstract_inline_text_box.cc
@@ -155,7 +155,7 @@ NGInlineCursor NGAbstractInlineTextBox::GetCursorOnLine() const {
String NGAbstractInlineTextBox::GetTextContent() const {
const NGInlineCursor& cursor = GetCursor();
- if (cursor.Current().IsGeneratedTextType())
+ if (cursor.Current().IsLayoutGeneratedText())
return cursor.Current().Text(cursor).ToString();
if (const NGPaintFragment* paint_fragment = cursor.CurrentPaintFragment()) {
return To<NGPhysicalTextFragment>(paint_fragment->PhysicalFragment())
@@ -170,7 +170,7 @@ bool NGAbstractInlineTextBox::NeedsTrailingSpace() const {
return false;
NGInlineCursor line_box = cursor;
line_box.MoveToContainingLine();
- if (!line_box.HasSoftWrapToNextLine())
+ if (!line_box.Current().HasSoftWrapToNextLine())
return false;
const String text_content = GetTextContent();
const unsigned end_offset = cursor.Current().TextEndOffset();
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_caret_position.cc b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_caret_position.cc
index ed88fbe192b..d5075dba7d6 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_caret_position.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_caret_position.cc
@@ -64,7 +64,7 @@ bool CanResolveCaretPositionBeforeFragment(const NGInlineCursor& cursor,
return true;
NGInlineCursor last_line(current_line);
last_line.MoveToPreviousLine();
- return !last_line || !last_line.HasSoftWrapToNextLine();
+ return !last_line || !last_line.Current().HasSoftWrapToNextLine();
}
bool CanResolveCaretPositionAfterFragment(const NGInlineCursor& cursor,
@@ -80,7 +80,7 @@ bool CanResolveCaretPositionAfterFragment(const NGInlineCursor& cursor,
last_logical_leaf.MoveToLastLogicalLeaf();
if (cursor != last_logical_leaf)
return true;
- return !current_line.HasSoftWrapToNextLine();
+ return !current_line.Current().HasSoftWrapToNextLine();
}
// Returns a |kFailed| resolution if |offset| doesn't belong to the text
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_dirty_lines.cc b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_dirty_lines.cc
deleted file mode 100644
index 61a0ecf53b5..00000000000
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_dirty_lines.cc
+++ /dev/null
@@ -1,50 +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/core/layout/ng/inline/ng_dirty_lines.h"
-
-#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_break_token.h"
-#include "third_party/blink/renderer/core/layout/ng/inline/ng_physical_line_box_fragment.h"
-
-namespace blink {
-
-void NGDirtyLines::MarkLastFragment() {
- if (last_fragment_) {
- // Changes in this LayoutObject may affect the line that contains its
- // previous object. Mark the line box that contains the last fragment
- // of the previous object.
- last_fragment_->LastForSameLayoutObject()->MarkContainingLineBoxDirty();
- } else {
- // If there were no fragments so far in this pre-order traversal, mark
- // the first line box dirty.
- DCHECK(block_fragment_);
- if (NGPaintFragment* first_line = block_fragment_->FirstLineBox())
- first_line->MarkLineBoxDirty();
- }
-}
-
-void NGDirtyLines::MarkAtTextOffset(unsigned offset) {
- for (NGPaintFragment* child : block_fragment_->Children()) {
- // Only the first dirty line is relevant.
- if (child->IsDirty())
- break;
-
- const auto* line =
- DynamicTo<NGPhysicalLineBoxFragment>(child->PhysicalFragment());
- if (!line)
- continue;
-
- const auto* break_token = To<NGInlineBreakToken>(line->BreakToken());
- DCHECK(break_token);
- if (break_token->IsFinished())
- break;
-
- if (offset < break_token->TextOffset()) {
- child->MarkLineBoxDirty();
- break;
- }
- }
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_dirty_lines.h b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_dirty_lines.h
deleted file mode 100644
index 5e97423cd95..00000000000
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_dirty_lines.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.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_DIRTY_LINES_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_DIRTY_LINES_H_
-
-#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/core/layout/layout_box.h"
-#include "third_party/blink/renderer/core/layout/layout_inline.h"
-#include "third_party/blink/renderer/core/layout/layout_text.h"
-#include "third_party/blink/renderer/core/paint/ng/ng_paint_fragment.h"
-
-namespace blink {
-
-// This class computes dirty line boxes.
-class CORE_EXPORT NGDirtyLines {
- STACK_ALLOCATED();
-
- public:
- explicit NGDirtyLines(const NGPaintFragment* block_fragment)
- : block_fragment_(block_fragment) {
- DCHECK(block_fragment_);
- }
-
- // Call |Handle*| functions for each object by traversing the LayoutObject
- // tree in pre-order DFS.
- //
- // They return |true| when a dirty line was found. Because only the first
- // dirty line is relevant, no further calls are necessary.
- bool HandleText(LayoutText* layout_text) {
- if (layout_text->SelfNeedsLayout()) {
- MarkLastFragment();
- return true;
- }
- UpdateLastFragment(layout_text->FirstInlineFragment());
- return false;
- }
-
- bool HandleInlineBox(LayoutInline* layout_inline) {
- if (layout_inline->SelfNeedsLayout()) {
- MarkLastFragment();
- return true;
- }
- // Do not keep fragments of LayoutInline unless it's a leaf, because
- // the last fragment of LayoutInline is not the previous fragment of its
- // descendants.
- if (UNLIKELY(!layout_inline->FirstChild()))
- UpdateLastFragment(layout_inline->FirstInlineFragment());
- return false;
- }
-
- bool HandleAtomicInline(LayoutBox* layout_box) {
- if (layout_box->NeedsLayout()) {
- MarkLastFragment();
- return true;
- }
- UpdateLastFragment(layout_box->FirstInlineFragment());
- return false;
- }
-
- bool HandleFloatingOrOutOfFlowPositioned(LayoutObject* layout_object) {
- DCHECK(layout_object->IsFloatingOrOutOfFlowPositioned());
- if (layout_object->NeedsLayout()) {
- MarkLastFragment();
- return true;
- }
- // Don't update last fragment. Floats and OOF are opaque.
- return false;
- }
-
- // Mark the line box at the specified text offset dirty.
- void MarkAtTextOffset(unsigned offset);
-
- private:
- void UpdateLastFragment(NGPaintFragment* fragment) {
- if (fragment)
- last_fragment_ = fragment;
- }
-
- // Mark the line box that contains |last_fragment_| dirty. If |last_fragment_|
- // is |nullptr|, the first line box is marked as dirty.
- void MarkLastFragment();
-
- const NGPaintFragment* block_fragment_;
- NGPaintFragment* last_fragment_ = nullptr;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_DIRTY_LINES_H_
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.cc b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.cc
index 63a23dff82b..4aedb519e64 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.cc
@@ -10,6 +10,7 @@
#include "third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items_builder.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_item.h"
+#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_item_result.h"
#include "third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h"
namespace blink {
@@ -21,18 +22,19 @@ NGFragmentItem::NGFragmentItem(const NGPhysicalTextFragment& text)
type_(kText),
sub_type_(static_cast<unsigned>(text.TextType())),
style_variant_(static_cast<unsigned>(text.StyleVariant())),
- is_generated_text_(text.IsGeneratedText()),
is_hidden_for_paint_(text.IsHiddenForPaint()),
text_direction_(static_cast<unsigned>(text.ResolvedDirection())),
ink_overflow_computed_(false),
- is_first_for_node_(text.IsFirstForNode()) {
+ is_dirty_(false),
+ is_first_for_node_(true),
+ is_last_for_node_(true) {
#if DCHECK_IS_ON()
if (text_.shape_result) {
DCHECK_EQ(text_.shape_result->StartIndex(), StartOffset());
DCHECK_EQ(text_.shape_result->EndIndex(), EndOffset());
}
#endif
- if (text.TextType() == NGPhysicalTextFragment::kGeneratedText) {
+ if (text.TextType() == NGTextType::kLayoutGenerated) {
type_ = kGeneratedText;
// Note: Because of |text_| and |generated_text_| are in same union and
// we initialize |text_| instead of |generated_text_|, we should construct
@@ -42,6 +44,31 @@ NGFragmentItem::NGFragmentItem(const NGPhysicalTextFragment& text)
DCHECK(!IsFormattingContextRoot());
}
+NGFragmentItem::NGFragmentItem(NGInlineItemResult&& item_result,
+ const PhysicalSize& size)
+ : layout_object_(item_result.item->GetLayoutObject()),
+ text_({std::move(item_result.shape_result), item_result.TextOffset()}),
+ rect_({PhysicalOffset(), size}),
+ type_(kText),
+ sub_type_(static_cast<unsigned>(item_result.item->TextType())),
+ style_variant_(static_cast<unsigned>(item_result.item->StyleVariant())),
+ is_hidden_for_paint_(false), // TODO(kojii): not supported yet.
+ text_direction_(static_cast<unsigned>(item_result.item->Direction())),
+ ink_overflow_computed_(false),
+ is_dirty_(false),
+ is_first_for_node_(true),
+ is_last_for_node_(true) {
+#if DCHECK_IS_ON()
+ if (text_.shape_result) {
+ DCHECK_EQ(text_.shape_result->StartIndex(), StartOffset());
+ DCHECK_EQ(text_.shape_result->EndIndex(), EndOffset());
+ }
+#endif
+ // TODO(kojii): Generated text not supported yet.
+ DCHECK_NE(TextType(), NGTextType::kLayoutGenerated);
+ DCHECK(!IsFormattingContextRoot());
+}
+
NGFragmentItem::NGFragmentItem(const NGPhysicalLineBoxFragment& line,
wtf_size_t item_count)
: layout_object_(line.ContainerLayoutObject()),
@@ -53,7 +80,9 @@ NGFragmentItem::NGFragmentItem(const NGPhysicalLineBoxFragment& line,
is_hidden_for_paint_(false),
text_direction_(static_cast<unsigned>(line.BaseDirection())),
ink_overflow_computed_(false),
- is_first_for_node_(true) {
+ is_dirty_(false),
+ is_first_for_node_(true),
+ is_last_for_node_(true) {
DCHECK(!IsFormattingContextRoot());
}
@@ -67,7 +96,9 @@ NGFragmentItem::NGFragmentItem(const NGPhysicalBoxFragment& box,
is_hidden_for_paint_(box.IsHiddenForPaint()),
text_direction_(static_cast<unsigned>(resolved_direction)),
ink_overflow_computed_(false),
- is_first_for_node_(box.IsFirstForNode()) {
+ is_dirty_(false),
+ is_first_for_node_(true),
+ is_last_for_node_(true) {
DCHECK_EQ(IsFormattingContextRoot(), box.IsFormattingContextRoot());
}
@@ -81,13 +112,52 @@ NGFragmentItem::NGFragmentItem(const NGInlineItem& inline_item,
is_hidden_for_paint_(false),
text_direction_(static_cast<unsigned>(TextDirection::kLtr)),
ink_overflow_computed_(false),
- is_first_for_node_(true) {
+ is_dirty_(false),
+ is_first_for_node_(true),
+ is_last_for_node_(true) {
DCHECK_EQ(inline_item.Type(), NGInlineItem::kOpenTag);
DCHECK(layout_object_);
DCHECK(layout_object_->IsLayoutInline());
DCHECK(!IsFormattingContextRoot());
}
+// static
+void NGFragmentItem::Create(NGLineBoxFragmentBuilder::ChildList* child_list,
+ const String& text_content,
+ WritingMode writing_mode) {
+ for (auto& child : *child_list) {
+ DCHECK(!child.fragment_item);
+
+ if (child.fragment) {
+ child.fragment_item = base::AdoptRef(new NGFragmentItem(*child.fragment));
+ continue;
+ }
+
+ if (child.item_result) {
+ child.fragment_item = base::AdoptRef(new NGFragmentItem(
+ std::move(*child.item_result),
+ ToPhysicalSize({child.inline_size, child.rect.size.block_size},
+ writing_mode)));
+ continue;
+ }
+
+ if (child.layout_result) {
+ const NGPhysicalBoxFragment& fragment =
+ To<NGPhysicalBoxFragment>(child.layout_result->PhysicalFragment());
+ child.fragment_item = base::AdoptRef(
+ new NGFragmentItem(fragment, child.ResolvedDirection()));
+ continue;
+ }
+
+ if (child.inline_item) {
+ child.fragment_item = base::AdoptRef(new NGFragmentItem(
+ *child.inline_item,
+ ToPhysicalSize(child.rect.size,
+ child.inline_item->Style()->GetWritingMode())));
+ }
+ }
+}
+
NGFragmentItem::~NGFragmentItem() {
switch (Type()) {
case kText:
@@ -105,24 +175,6 @@ NGFragmentItem::~NGFragmentItem() {
}
}
-bool NGFragmentItem::IsSiblingOf(const NGFragmentItem& other) const {
- if (!GetLayoutObject())
- return !other.GetLayoutObject();
- if (!other.GetLayoutObject())
- return false;
- if (GetLayoutObject()->Parent() == other.GetLayoutObject()->Parent())
- return true;
- // To traverse list marker and line box of <li> with |MoveToNextSibling()|,
- // we think list marker and <li> are sibling.
- // See hittesting/culled-inline-crash.html (skip list marker)
- // See fast/events/onclick-list-marker.html (hit on list marker)
- if (IsListMarker())
- return GetLayoutObject()->Parent() == other.GetLayoutObject();
- if (other.IsListMarker())
- return other.GetLayoutObject()->Parent() == GetLayoutObject();
- return false;
-}
-
bool NGFragmentItem::IsInlineBox() const {
if (Type() == kBox) {
if (const NGPhysicalBoxFragment* box = BoxFragment())
@@ -152,8 +204,13 @@ bool NGFragmentItem::IsEmptyLineBox() const {
}
bool NGFragmentItem::IsGeneratedText() const {
- if (Type() == kText || Type() == kGeneratedText)
- return is_generated_text_;
+ if (Type() == kGeneratedText) {
+ DCHECK_EQ(TextType(), NGTextType::kLayoutGenerated);
+ return true;
+ }
+ DCHECK_NE(TextType(), NGTextType::kLayoutGenerated);
+ if (Type() == kText)
+ return GetLayoutObject()->IsStyleGenerated();
NOTREACHED();
return false;
}
@@ -174,6 +231,21 @@ bool NGFragmentItem::HasSelfPaintingLayer() const {
return false;
}
+void NGFragmentItem::LayoutObjectWillBeDestroyed() const {
+ const_cast<NGFragmentItem*>(this)->layout_object_ = nullptr;
+ if (const NGPhysicalBoxFragment* fragment = BoxFragment())
+ fragment->LayoutObjectWillBeDestroyed();
+}
+
+void NGFragmentItem::LayoutObjectWillBeMoved() const {
+ // When |Layoutobject| is moved out from the current IFC, we should not clear
+ // the association with it in |ClearAssociatedFragments|, because the
+ // |LayoutObject| may be moved to a different IFC and is already laid out
+ // before clearing this IFC. This happens e.g., when split inlines moves
+ // inline children into a child anonymous block.
+ const_cast<NGFragmentItem*>(this)->layout_object_ = nullptr;
+}
+
inline const LayoutBox* NGFragmentItem::InkOverflowOwnerBox() const {
if (Type() == kBox)
return ToLayoutBoxOrNull(GetLayoutObject());
@@ -277,7 +349,17 @@ String NGFragmentItem::DebugName() const {
if (Type() == NGFragmentItem::kText) {
StringBuilder name;
name.Append("NGPhysicalTextFragment '");
- name.Append(Text(*layout_object_->ContainingBlockFlowFragment()->Items()));
+ const NGPhysicalBoxFragment* containing_fragment =
+ layout_object_->ContainingBlockFlowFragment();
+ if (containing_fragment) {
+ name.Append(Text(*containing_fragment->Items()));
+ } else {
+ // TODO(crbug.com/1061423): ContainingBlockFlowFragment() relies on
+ // CurrentFragment(), which doesn't work inside block fragmentation. Check
+ // that we're (most likely) inside block fragmentation. Otherwise, this
+ // shouldn't happen.
+ DCHECK(layout_object_->IsInsideFlowThread());
+ }
name.Append('\'');
return name.ToString();
}
@@ -323,6 +405,7 @@ PhysicalRect NGFragmentItem::LocalVisualRectFor(
PhysicalRect NGFragmentItem::RecalcInkOverflowForCursor(
NGInlineCursor* cursor) {
DCHECK(cursor);
+ DCHECK(!cursor->Current() || cursor->IsAtFirst());
PhysicalRect contents_ink_overflow;
while (*cursor) {
const NGFragmentItem* item = cursor->CurrentItem();
@@ -374,7 +457,7 @@ void NGFragmentItem::RecalcInkOverflow(
// overflow to be stored in |LayoutBox|.
if (LayoutBox* owner_box = MutableInkOverflowOwnerBox()) {
DCHECK(!HasChildren());
- cursor->MoveToNextSibling();
+ cursor->MoveToNextSkippingChildren();
owner_box->RecalcNormalFlowChildVisualOverflowIfNeeded();
*self_and_contents_rect_out = owner_box->PhysicalVisualOverflowRect();
return;
@@ -382,7 +465,7 @@ void NGFragmentItem::RecalcInkOverflow(
// Re-compute descendants, then compute the contents ink overflow from them.
NGInlineCursor descendants_cursor = cursor->CursorForDescendants();
- cursor->MoveToNextSibling();
+ cursor->MoveToNextSkippingChildren();
PhysicalRect contents_rect = RecalcInkOverflowForCursor(&descendants_cursor);
// |contents_rect| is relative to the inline formatting context. Make it
@@ -420,8 +503,8 @@ void NGFragmentItem::RecalcInkOverflow(
}
}
-void NGFragmentItem::SetDeltaToNextForSameLayoutObject(wtf_size_t delta) {
- DCHECK_NE(delta, 0u);
+void NGFragmentItem::SetDeltaToNextForSameLayoutObject(wtf_size_t delta) const {
+ DCHECK_NE(Type(), kLine);
delta_to_next_for_same_layout_object_ = delta;
}
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.h b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.h
index c07af90d3d8..703564f3ebc 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.h
@@ -5,28 +5,32 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_FRAGMENT_ITEM_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_FRAGMENT_ITEM_H_
+#include "base/memory/scoped_refptr.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/layout/geometry/logical_offset.h"
#include "third_party/blink/renderer/core/layout/layout_object.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_line_box_fragment_builder.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_line_height_metrics.h"
-#include "third_party/blink/renderer/core/layout/ng/inline/ng_physical_text_fragment.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_text_offset.h"
+#include "third_party/blink/renderer/core/layout/ng/inline/ng_text_type.h"
#include "third_party/blink/renderer/core/layout/ng/ng_ink_overflow.h"
#include "third_party/blink/renderer/platform/graphics/paint/display_item_client.h"
+#include "third_party/blink/renderer/platform/wtf/ref_counted.h"
namespace blink {
class NGFragmentItems;
class NGInlineBreakToken;
class NGInlineItem;
+class NGPhysicalTextFragment;
struct NGTextFragmentPaintInfo;
// This class represents a text run or a box in an inline formatting context.
//
// This class consumes less memory than a full fragment, and can be stored in a
// flat list (NGFragmentItems) for easier and faster traversal.
-class CORE_EXPORT NGFragmentItem : public DisplayItemClient {
+class CORE_EXPORT NGFragmentItem : public RefCounted<NGFragmentItem>,
+ public DisplayItemClient {
public:
// Represents regular text that exists in the DOM.
struct TextItem {
@@ -62,13 +66,22 @@ class CORE_EXPORT NGFragmentItem : public DisplayItemClient {
enum ItemType { kText, kGeneratedText, kLine, kBox };
+ // Create a text item.
// TODO(kojii): Should be able to create without once creating fragments.
- NGFragmentItem(const NGPhysicalTextFragment& text);
+ explicit NGFragmentItem(const NGPhysicalTextFragment& text);
+ // Create a box item.
NGFragmentItem(const NGPhysicalBoxFragment& box,
TextDirection resolved_direction);
+ // Create a culled box item.
NGFragmentItem(const NGInlineItem& inline_item, const PhysicalSize& size);
+ // Create a line item.
NGFragmentItem(const NGPhysicalLineBoxFragment& line, wtf_size_t item_count);
+ // Create |NGFragmentItem| for all items in |child_list|.
+ static void Create(NGLineBoxFragmentBuilder::ChildList* child_list,
+ const String& text_content,
+ WritingMode writing_mode);
+
~NGFragmentItem() final;
ItemType Type() const { return static_cast<ItemType>(type_); }
@@ -85,19 +98,18 @@ class CORE_EXPORT NGFragmentItem : public DisplayItemClient {
// Return true if this is the first fragment generated from a node.
bool IsFirstForNode() const {
DCHECK(Type() != kLine);
- DCHECK(!IsInlineBox() || BoxFragment());
return is_first_for_node_;
}
// Return true if this is the last fragment generated from a node.
bool IsLastForNode() const {
- // TODO(layout-dev): This doesn't work if the LayoutObject continues in a
- // next fragmentainer (we get a false negative here then).
DCHECK(Type() != kLine);
- DCHECK(!IsInlineBox() || BoxFragment());
- return !DeltaToNextForSameLayoutObject();
+ return is_last_for_node_;
}
+ void SetIsFirstForNode(bool is_first) const { is_first_for_node_ = is_first; }
+ void SetIsLastForNode(bool is_last) const { is_last_for_node_ = is_last; }
+
NGStyleVariant StyleVariant() const {
return static_cast<NGStyleVariant>(style_variant_);
}
@@ -117,14 +129,15 @@ class CORE_EXPORT NGFragmentItem : public DisplayItemClient {
LayoutObject* GetMutableLayoutObject() const {
return const_cast<LayoutObject*>(layout_object_);
}
+ void LayoutObjectWillBeDestroyed() const;
+ void LayoutObjectWillBeMoved() const;
Node* GetNode() const { return layout_object_->GetNode(); }
Node* NodeForHitTest() const { return layout_object_->NodeForHitTest(); }
- bool IsSiblingOf(const NGFragmentItem& other) const;
wtf_size_t DeltaToNextForSameLayoutObject() const {
return delta_to_next_for_same_layout_object_;
}
- void SetDeltaToNextForSameLayoutObject(wtf_size_t delta);
+ void SetDeltaToNextForSameLayoutObject(wtf_size_t delta) const;
const PhysicalRect& RectInContainerBlock() const { return rect_; }
const PhysicalOffset& OffsetInContainerBlock() const { return rect_.offset; }
@@ -199,11 +212,6 @@ class CORE_EXPORT NGFragmentItem : public DisplayItemClient {
// Re-compute the ink overflow for the |cursor| until its end.
static PhysicalRect RecalcInkOverflowForCursor(NGInlineCursor* cursor);
- // Re-compute the ink overflow for this item. |cursor| should be at |this|,
- // and is advanced to the next item on return.
- void RecalcInkOverflow(NGInlineCursor* cursor,
- PhysicalRect* self_and_contents_rect_out);
-
// Painters can use const methods only, except for these explicitly declared
// methods.
class MutableForPainting {
@@ -235,14 +243,13 @@ class CORE_EXPORT NGFragmentItem : public DisplayItemClient {
}
// Functions for |TextItem| and |GeneratedTextItem|
- using NGTextType = NGPhysicalTextFragment::NGTextType;
NGTextType TextType() const {
if (Type() == kText)
return static_cast<NGTextType>(sub_type_);
if (Type() == kGeneratedText)
- return NGTextType::kGeneratedText;
+ return NGTextType::kLayoutGenerated;
NOTREACHED() << this;
- return NGTextType::kNormalText;
+ return NGTextType::kNormal;
}
// True if this is a forced line break.
@@ -333,10 +340,25 @@ class CORE_EXPORT NGFragmentItem : public DisplayItemClient {
unsigned TextOffsetForPoint(const PhysicalOffset& point,
const NGFragmentItems& items) const;
+ // Whether this item was marked dirty for reuse or not.
+ bool IsDirty() const { return is_dirty_; }
+ void SetDirty() const { is_dirty_ = true; }
+
+ // Returns true if this item is reusable.
+ bool CanReuse() const;
+
private:
+ // Create a text item.
+ NGFragmentItem(NGInlineItemResult&& item_result, const PhysicalSize& size);
+
const LayoutBox* InkOverflowOwnerBox() const;
LayoutBox* MutableInkOverflowOwnerBox();
+ // Re-compute the ink overflow for this item. |cursor| should be at |this|,
+ // and is advanced to the next item on return.
+ void RecalcInkOverflow(NGInlineCursor* cursor,
+ PhysicalRect* self_and_contents_rect_out);
+
const LayoutObject* layout_object_;
// TODO(kojii): We can make them sub-classes if we need to make the vector of
@@ -354,16 +376,12 @@ class CORE_EXPORT NGFragmentItem : public DisplayItemClient {
std::unique_ptr<NGInkOverflow> ink_overflow_;
// Item index delta to the next item for the same |LayoutObject|.
- wtf_size_t delta_to_next_for_same_layout_object_ = 0;
+ mutable wtf_size_t delta_to_next_for_same_layout_object_ = 0;
// Note: We should not add |bidi_level_| because it is used only for layout.
unsigned type_ : 2; // ItemType
unsigned sub_type_ : 3; // NGTextType or NGLineBoxType
unsigned style_variant_ : 2; // NGStyleVariant
- // TODO(yosin): We'll remove |is_generated_text_| field when we construct
- // |NGFragmentItem| without |NGPhysicalTextFragment| because usage of this
- // varaible, IsGeneratedText(), is not hot.
- unsigned is_generated_text_ : 1; // NGPhysicalTextFragment::IsGenerated()
unsigned is_hidden_for_paint_ : 1;
// Note: For |TextItem| and |GeneratedTextItem|, |text_direction_| equals to
// |ShapeResult::Direction()|.
@@ -372,9 +390,21 @@ class CORE_EXPORT NGFragmentItem : public DisplayItemClient {
// Used only when |IsText()| to avoid re-computing ink overflow.
unsigned ink_overflow_computed_ : 1;
- unsigned is_first_for_node_ : 1;
+ mutable unsigned is_dirty_ : 1;
+
+ mutable unsigned is_first_for_node_ : 1;
+ mutable unsigned is_last_for_node_ : 1;
};
+inline bool NGFragmentItem::CanReuse() const {
+ DCHECK_NE(Type(), kLine);
+ if (IsDirty())
+ return false;
+ if (const LayoutObject* layout_object = GetLayoutObject())
+ return !layout_object->SelfNeedsLayout();
+ return false;
+}
+
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_FRAGMENT_ITEM_H_
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item_test.cc b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item_test.cc
index 3e8f4853a6b..5138c33cb7d 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item_test.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item_test.cc
@@ -6,6 +6,7 @@
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/core/dom/dom_token_list.h"
#include "third_party/blink/renderer/core/layout/layout_block_flow.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.h"
@@ -16,10 +17,56 @@ using testing::ElementsAre;
namespace blink {
+// We enable LayoutNGFragmentTraversal here, so that we get the "first/last for
+// node" bits set as appropriate.
class NGFragmentItemTest : public NGLayoutTest,
- ScopedLayoutNGFragmentItemForTest {
+ ScopedLayoutNGFragmentItemForTest,
+ ScopedLayoutNGFragmentTraversalForTest {
public:
- NGFragmentItemTest() : ScopedLayoutNGFragmentItemForTest(true) {}
+ NGFragmentItemTest()
+ : ScopedLayoutNGFragmentItemForTest(true),
+ ScopedLayoutNGFragmentTraversalForTest(true) {}
+
+ void ForceLayout() { RunDocumentLifecycle(); }
+
+ LayoutBlockFlow* GetLayoutBlockFlowByElementId(const char* id) {
+ return To<LayoutBlockFlow>(GetLayoutObjectByElementId(id));
+ }
+
+ const NGFragmentItems* GetFragmentItemsByElementId(const char* id) {
+ const auto* block_flow =
+ To<LayoutBlockFlow>(GetLayoutObjectByElementId("container"));
+ return block_flow->FragmentItems();
+ }
+
+ Vector<NGInlineCursorPosition> GetLines(NGInlineCursor* cursor) {
+ Vector<NGInlineCursorPosition> lines;
+ for (cursor->MoveToFirstLine(); *cursor; cursor->MoveToNextLine())
+ lines.push_back(cursor->Current());
+ return lines;
+ }
+
+ wtf_size_t IndexOf(const Vector<NGInlineCursorPosition>& items,
+ const NGFragmentItem* target) {
+ wtf_size_t index = 0;
+ for (const auto& item : items) {
+ if (item.Item() == target)
+ return index;
+ ++index;
+ }
+ return kNotFound;
+ }
+
+ void TestFirstDirtyLineIndex(const char* id, wtf_size_t expected_index) {
+ LayoutBlockFlow* block_flow = GetLayoutBlockFlowByElementId(id);
+ const NGFragmentItems* items = block_flow->FragmentItems();
+ items->DirtyLinesFromNeedsLayout(block_flow);
+ const NGFragmentItem* end_reusable_item = items->EndOfReusableItems();
+
+ NGInlineCursor cursor(*items);
+ const auto lines = GetLines(&cursor);
+ EXPECT_EQ(IndexOf(lines, end_reusable_item), expected_index);
+ }
Vector<const NGFragmentItem*> ItemsForAsVector(
const LayoutObject& layout_object) {
@@ -72,16 +119,82 @@ TEST_F(NGFragmentItemTest, BasicText) {
EXPECT_EQ(text1.Type(), NGFragmentItem::kText);
EXPECT_EQ(text1.GetLayoutObject(), layout_text);
EXPECT_EQ(text1.OffsetInContainerBlock(), PhysicalOffset());
+ EXPECT_TRUE(text1.IsFirstForNode());
+ EXPECT_FALSE(text1.IsLastForNode());
const NGFragmentItem& text2 = *items_for_text[1];
EXPECT_EQ(text2.Type(), NGFragmentItem::kText);
EXPECT_EQ(text2.GetLayoutObject(), layout_text);
EXPECT_EQ(text2.OffsetInContainerBlock(), PhysicalOffset(0, 10));
+ EXPECT_FALSE(text2.IsFirstForNode());
+ EXPECT_TRUE(text2.IsLastForNode());
EXPECT_EQ(IntRect(0, 0, 70, 20),
layout_text->FragmentsVisualRectBoundingBox());
}
+TEST_F(NGFragmentItemTest, RtlText) {
+ LoadAhem();
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ div {
+ font-family: Ahem;
+ font-size: 10px;
+ width: 10ch;
+ direction: rtl;
+ }
+ </style>
+ <div id="container">
+ <span id="span" style="background:hotpink;">
+ 11111. 22222.
+ </span>
+ </div>
+ )HTML");
+
+ LayoutBlockFlow* container =
+ To<LayoutBlockFlow>(GetLayoutObjectByElementId("container"));
+ LayoutObject* span = GetLayoutObjectByElementId("span");
+ LayoutText* layout_text = ToLayoutText(span->SlowFirstChild());
+ const NGPhysicalBoxFragment* box = container->CurrentFragment();
+ EXPECT_NE(box, nullptr);
+ const NGFragmentItems* items = box->Items();
+ EXPECT_NE(items, nullptr);
+ EXPECT_EQ(items->Items().size(), 8u);
+
+ Vector<const NGFragmentItem*> items_for_span = ItemsForAsVector(*span);
+ EXPECT_EQ(items_for_span.size(), 2u);
+ const NGFragmentItem* item = items_for_span[0];
+ EXPECT_TRUE(item->IsFirstForNode());
+ EXPECT_FALSE(item->IsLastForNode());
+
+ item = items_for_span[1];
+ EXPECT_FALSE(item->IsFirstForNode());
+ EXPECT_TRUE(item->IsLastForNode());
+
+ Vector<const NGFragmentItem*> items_for_text = ItemsForAsVector(*layout_text);
+ EXPECT_EQ(items_for_text.size(), 4u);
+
+ item = items_for_text[0];
+ EXPECT_EQ(item->Text(*items).ToString(), String("."));
+ EXPECT_TRUE(item->IsFirstForNode());
+ EXPECT_FALSE(item->IsLastForNode());
+
+ item = items_for_text[1];
+ EXPECT_EQ(item->Text(*items).ToString(), String("11111"));
+ EXPECT_FALSE(item->IsFirstForNode());
+ EXPECT_FALSE(item->IsLastForNode());
+
+ item = items_for_text[2];
+ EXPECT_EQ(item->Text(*items).ToString(), String("."));
+ EXPECT_FALSE(item->IsFirstForNode());
+ EXPECT_FALSE(item->IsLastForNode());
+
+ item = items_for_text[3];
+ EXPECT_EQ(item->Text(*items).ToString(), String("22222"));
+ EXPECT_FALSE(item->IsFirstForNode());
+ EXPECT_TRUE(item->IsLastForNode());
+}
+
TEST_F(NGFragmentItemTest, BasicInlineBox) {
LoadAhem();
SetBodyInnerHTML(R"HTML(
@@ -113,6 +226,10 @@ TEST_F(NGFragmentItemTest, BasicInlineBox) {
Vector<const NGFragmentItem*> items_for_span1 = ItemsForAsVector(*span1);
EXPECT_EQ(items_for_span1.size(), 2u);
EXPECT_EQ(IntRect(0, 0, 80, 20), span1->FragmentsVisualRectBoundingBox());
+ EXPECT_TRUE(items_for_span1[0]->IsFirstForNode());
+ EXPECT_FALSE(items_for_span1[0]->IsLastForNode());
+ EXPECT_FALSE(items_for_span1[1]->IsFirstForNode());
+ EXPECT_TRUE(items_for_span1[1]->IsLastForNode());
// "span2" doesn't wrap, produces only one fragment.
const LayoutObject* span2 = GetLayoutObjectByElementId("span2");
@@ -120,10 +237,13 @@ TEST_F(NGFragmentItemTest, BasicInlineBox) {
Vector<const NGFragmentItem*> items_for_span2 = ItemsForAsVector(*span2);
EXPECT_EQ(items_for_span2.size(), 1u);
EXPECT_EQ(IntRect(0, 20, 80, 10), span2->FragmentsVisualRectBoundingBox());
+ EXPECT_TRUE(items_for_span2[0]->IsFirstForNode());
+ EXPECT_TRUE(items_for_span2[0]->IsLastForNode());
}
// Same as |BasicInlineBox| but `<span>`s do not have background.
-// They will not need box fragments, but all operations should work the same.
+// They will not produce fragment items, but all operations should work the
+// same.
TEST_F(NGFragmentItemTest, CulledInlineBox) {
LoadAhem();
SetBodyInnerHTML(R"HTML(
@@ -150,21 +270,440 @@ TEST_F(NGFragmentItemTest, CulledInlineBox) {
const LayoutObject* span1 = GetLayoutObjectByElementId("span1");
ASSERT_NE(span1, nullptr);
Vector<const NGFragmentItem*> items_for_span1 = ItemsForAsVector(*span1);
- EXPECT_EQ(items_for_span1.size(), 2u);
- EXPECT_EQ(IntRect(0, 0, 80, 20), span1->FragmentsVisualRectBoundingBox());
+ EXPECT_EQ(items_for_span1.size(), 0u);
+ EXPECT_EQ(IntRect(0, 0, 80, 20), span1->AbsoluteBoundingBoxRect());
// "span2" doesn't wrap, produces only one fragment.
const LayoutObject* span2 = GetLayoutObjectByElementId("span2");
ASSERT_NE(span2, nullptr);
Vector<const NGFragmentItem*> items_for_span2 = ItemsForAsVector(*span2);
- EXPECT_EQ(items_for_span2.size(), 1u);
- EXPECT_EQ(IntRect(0, 20, 80, 10), span2->FragmentsVisualRectBoundingBox());
+ EXPECT_EQ(items_for_span2.size(), 0u);
+ EXPECT_EQ(IntRect(0, 20, 80, 10), span2->AbsoluteBoundingBoxRect());
+}
+
+// Various nodes/elements to test insertions.
+using CreateNode = Node* (*)(Document&);
+static CreateNode node_creators[] = {
+ [](Document& document) -> Node* { return document.createTextNode("new"); },
+ [](Document& document) -> Node* {
+ return document.CreateRawElement(html_names::kSpanTag);
+ },
+ [](Document& document) -> Node* {
+ Element* element = document.CreateRawElement(html_names::kSpanTag);
+ element->classList().Add("abspos");
+ return element;
+ },
+ [](Document& document) -> Node* {
+ Element* element = document.CreateRawElement(html_names::kSpanTag);
+ element->classList().Add("float");
+ return element;
+ }};
+
+class FragmentItemInsertTest : public NGFragmentItemTest,
+ public testing::WithParamInterface<CreateNode> {
+};
+
+INSTANTIATE_TEST_SUITE_P(NGFragmentItemTest,
+ FragmentItemInsertTest,
+ testing::ValuesIn(node_creators));
+
+// Various nodes/elements to test removals.
+class FragmentItemRemoveTest : public NGFragmentItemTest,
+ public testing::WithParamInterface<const char*> {
+};
+
+INSTANTIATE_TEST_SUITE_P(
+ NGFragmentItemTest,
+ FragmentItemRemoveTest,
+ testing::Values("text",
+ "<span>span</span>",
+ "<span>1234 12345678</span>",
+ "<span style='display: inline-block'>box</span>",
+ "<img>",
+ "<div style='float: left'>float</div>",
+ "<div style='position: absolute'>abs</div>"));
+
+// Test marking line boxes when inserting a span before the first child.
+TEST_P(FragmentItemInsertTest, MarkLineBoxesDirtyOnInsert) {
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ .abspos { position: absolute; }
+ .float { float: left; }
+ </style>
+ <div id=container style="font-size: 10px; width: 10ch">
+ 12345678
+ </div>
+ )HTML");
+ Node* insert = (*GetParam())(GetDocument());
+ Element* container = GetElementById("container");
+ container->insertBefore(insert, container->firstChild());
+ TestFirstDirtyLineIndex("container", 0);
+}
+
+// Test marking line boxes when appending a span.
+TEST_P(FragmentItemInsertTest, MarkLineBoxesDirtyOnAppend) {
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ .abspos { position: absolute; }
+ .float { float: left; }
+ </style>
+ <div id=container style="font-size: 10px; width: 10ch">
+ 12345678
+ </div>
+ )HTML");
+ Node* insert = (*GetParam())(GetDocument());
+ Element* container = GetElementById("container");
+ container->appendChild(insert);
+ TestFirstDirtyLineIndex("container", 0);
+}
+
+// Test marking line boxes when appending a span on 2nd line.
+TEST_P(FragmentItemInsertTest, MarkLineBoxesDirtyOnAppend2) {
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ .abspos { position: absolute; }
+ .float { float: left; }
+ </style>
+ <div id=container style="font-size: 10px; width: 10ch">
+ 12345678
+ 2234
+ </div>
+ )HTML");
+ Node* insert = (*GetParam())(GetDocument());
+ Element* container = GetElementById("container");
+ container->appendChild(insert);
+ TestFirstDirtyLineIndex("container", 1);
+}
+
+// Test marking line boxes when appending a span on 2nd line.
+TEST_P(FragmentItemInsertTest, MarkLineBoxesDirtyOnAppendAfterBR) {
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ .abspos { position: absolute; }
+ .float { float: left; }
+ </style>
+ <div id=container style="font-size: 10px; width: 10ch">
+ <br>
+ <br>
+ </div>
+ )HTML");
+ Node* insert = (*GetParam())(GetDocument());
+ Element* container = GetElementById("container");
+ container->appendChild(insert);
+ TestFirstDirtyLineIndex("container", 1);
+}
+
+// Test marking line boxes when removing a span.
+TEST_F(NGFragmentItemTest, MarkLineBoxesDirtyOnRemove) {
+ SetBodyInnerHTML(R"HTML(
+ <div id=container style="font-size: 10px; width: 10ch">
+ 1234<span id=t>5678</span>
+ </div>
+ )HTML");
+ Element* span = GetElementById("t");
+ span->remove();
+ // TODO(kojii): This can be optimized more.
+ TestFirstDirtyLineIndex("container", 0);
+}
+
+// Test marking line boxes when removing a span.
+TEST_P(FragmentItemRemoveTest, MarkLineBoxesDirtyOnRemoveFirst) {
+ SetBodyInnerHTML(String(R"HTML(
+ <div id=container style="font-size: 10px; width: 10ch">)HTML") +
+ GetParam() + R"HTML(<span>after</span>
+ </div>
+ )HTML");
+
+ Element* container = GetElementById("container");
+ Node* node = container->firstChild();
+ ASSERT_TRUE(node);
+ node->remove();
+ TestFirstDirtyLineIndex("container", 0);
+}
+
+// Test marking line boxes when removing a span on 2nd line.
+TEST_F(NGFragmentItemTest, MarkLineBoxesDirtyOnRemove2) {
+ SetBodyInnerHTML(R"HTML(
+ <div id=container style="font-size: 10px; width: 10ch">
+ 12345678
+ 2234<span id=t>5678 3334</span>
+ </div>
+ )HTML");
+ Element* span = GetElementById("t");
+ span->remove();
+ // TODO(kojii): This can be optimized more.
+ TestFirstDirtyLineIndex("container", 0);
+}
+
+// Test marking line boxes when removing a text node on 2nd line.
+TEST_P(FragmentItemRemoveTest, MarkLineBoxesDirtyOnRemoveAfterBR) {
+ SetBodyInnerHTML(String(R"HTML(
+ <div id=container style="font-size: 10px; width: 10ch">
+ line 1
+ <br>)HTML") + GetParam() +
+ "</div>");
+ Element* container = GetElementById("container");
+ Node* node = container->lastChild();
+ ASSERT_TRUE(node);
+ node->remove();
+ // TODO(kojii): This can be optimized more.
+ TestFirstDirtyLineIndex("container", 0);
+
+ ForceLayout(); // Ensure running layout does not crash.
+}
+
+TEST_F(NGFragmentItemTest, MarkLineBoxesDirtyOnEndSpaceCollapsed) {
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ div {
+ font-size: 10px;
+ width: 8ch;
+ }
+ #empty {
+ background: yellow; /* ensure fragment is created */
+ }
+ #target {
+ display: inline-block;
+ }
+ </style>
+ <div id=container>
+ 1234567890
+ 1234567890
+ <span id=empty> </span>
+ <span id=target></span></div>
+ )HTML");
+ // Removing #target makes the spaces before it to be collapsed.
+ Element* target = GetElementById("target");
+ target->remove();
+ // TODO(kojii): This can be optimized more.
+ TestFirstDirtyLineIndex("container", 1);
+
+ ForceLayout(); // Ensure running layout does not crash.
+}
+
+// Test marking line boxes when the first span has NeedsLayout. The span is
+// culled.
+TEST_F(NGFragmentItemTest, MarkLineBoxesDirtyOnNeedsLayoutFirst) {
+ SetBodyInnerHTML(R"HTML(
+ <div id=container style="font-size: 10px; width: 10ch">
+ <span id=t>1234</span>5678
+ </div>
+ )HTML");
+ LayoutObject* span = GetLayoutObjectByElementId("t");
+ span->SetNeedsLayout("");
+ // TODO(kojii): This can be optimized more.
+ TestFirstDirtyLineIndex("container", 0);
+}
+
+// Test marking line boxes when the first span has NeedsLayout. The span has a
+// box fragment.
+TEST_F(NGFragmentItemTest, MarkLineBoxesDirtyOnNeedsLayoutFirstWithBox) {
+ SetBodyInnerHTML(R"HTML(
+ <div id=container style="font-size: 10px; width: 10ch">
+ <span id=t style="background: blue">1234</span>5678
+ </div>
+ )HTML");
+ LayoutObject* span = GetLayoutObjectByElementId("t");
+ span->SetNeedsLayout("");
+ // TODO(kojii): This can be optimized more.
+ TestFirstDirtyLineIndex("container", 0);
+}
+
+// Test marking line boxes when a span has NeedsLayout. The span is culled.
+TEST_F(NGFragmentItemTest, MarkLineBoxesDirtyOnNeedsLayout) {
+ SetBodyInnerHTML(R"HTML(
+ <div id=container style="font-size: 10px; width: 10ch">
+ 12345678
+ 2234<span id=t>5678 3334</span>
+ </div>
+ )HTML");
+ LayoutObject* span = GetLayoutObjectByElementId("t");
+ span->SetNeedsLayout("");
+ // TODO(kojii): This can be optimized more.
+ TestFirstDirtyLineIndex("container", 0);
+}
+
+// Test marking line boxes when a span has NeedsLayout. The span has a box
+// fragment.
+TEST_F(NGFragmentItemTest, MarkLineBoxesDirtyOnNeedsLayoutWithBox) {
+ SetBodyInnerHTML(R"HTML(
+ <div id=container style="font-size: 10px; width: 10ch">
+ 12345678
+ 2234<span id=t style="background: blue">5678 3334</span>
+ </div>
+ )HTML");
+ LayoutObject* span = GetLayoutObjectByElementId("t");
+ span->SetNeedsLayout("");
+ // TODO(kojii): This can be optimized more.
+ TestFirstDirtyLineIndex("container", 0);
+}
+
+// Test marking line boxes when a span inside a span has NeedsLayout.
+// The parent span has a box fragment, and wraps, so that its fragment
+// is seen earlier in pre-order DFS.
+TEST_F(NGFragmentItemTest, MarkLineBoxesDirtyOnChildOfWrappedBox) {
+ SetBodyInnerHTML(R"HTML(
+ <div id=container style="font-size: 10px">
+ <span style="background: yellow">
+ <span id=t>target</span>
+ <br>
+ 12345678
+ </span>
+ </div>
+ )HTML");
+ LayoutObject* span = GetLayoutObjectByElementId("t");
+ span->SetNeedsLayout("");
+ TestFirstDirtyLineIndex("container", 0);
+}
- // Except that they do not produce box fragments.
- for (const NGFragmentItem* item : items_for_span1)
- EXPECT_EQ(item->BoxFragment(), nullptr);
- for (const NGFragmentItem* item : items_for_span2)
- EXPECT_EQ(item->BoxFragment(), nullptr);
+// Test marking line boxes when a span has NeedsLayout. The span has a box
+// fragment.
+TEST_F(NGFragmentItemTest, MarkLineBoxesDirtyInInlineBlock) {
+ SetBodyInnerHTML(R"HTML(
+ <div id=container style="display: inline-block; font-size: 10px">
+ 12345678<br>
+ 12345678<br>
+ </div>
+ )HTML");
+ Element* container = GetElementById("container");
+ container->appendChild(GetDocument().createTextNode("append"));
+ // TODO(kojii): This can be optimized more.
+ TestFirstDirtyLineIndex("container", 1);
+}
+
+TEST_F(NGFragmentItemTest, MarkLineBoxesDirtyByRemoveChildAfterForcedBreak) {
+ SetBodyInnerHTML(R"HTML(
+ <div id=container>
+ line 1<br>
+ <b id=target>line 2</b><br>
+ line 3<br>
+ </div>
+ )HTML");
+ Element& target = *GetDocument().getElementById("target");
+ target.remove();
+ // TODO(kojii): This can be optimized more.
+ TestFirstDirtyLineIndex("container", 0);
+}
+
+TEST_F(NGFragmentItemTest, MarkLineBoxesDirtyByRemoveForcedBreak) {
+ SetBodyInnerHTML(R"HTML(
+ <div id=container>
+ line 1<br>
+ line 2<br id=target>
+ line 3<br>
+ </div>"
+ )HTML");
+ Element& target = *GetDocument().getElementById("target");
+ target.remove();
+ // TODO(kojii): This can be optimized more.
+ TestFirstDirtyLineIndex("container", 0);
+}
+
+TEST_F(NGFragmentItemTest, MarkLineBoxesDirtyByRemoveSpanWithForcedBreak) {
+ SetBodyInnerHTML(R"HTML(
+ <div id=container>
+ line 1<br>
+ line 2<span id=target><br>
+ </span>line 3<br>
+ </div>
+ )HTML");
+ // |target| is a culled inline box. There is no fragment in fragment tree.
+ Element& target = *GetDocument().getElementById("target");
+ target.remove();
+ // TODO(kojii): This can be optimized more.
+ TestFirstDirtyLineIndex("container", 0);
+}
+
+TEST_F(NGFragmentItemTest, MarkLineBoxesDirtyByInsertAtStart) {
+ SetBodyInnerHTML(R"HTML(
+ <div id=container>
+ line 1<br>
+ <b id=target>line 2</b><br>
+ line 3<br>
+ </div>
+ )HTML");
+ Element& target = *GetDocument().getElementById("target");
+ target.parentNode()->insertBefore(Text::Create(GetDocument(), "XYZ"),
+ &target);
+ GetDocument().UpdateStyleAndLayoutTree();
+ // TODO(kojii): This can be optimized more.
+ TestFirstDirtyLineIndex("container", 0);
+}
+
+TEST_F(NGFragmentItemTest, MarkLineBoxesDirtyByInsertAtLast) {
+ SetBodyInnerHTML(R"HTML(
+ <div id=container>
+ line 1<br>
+ <b id=target>line 2</b><br>
+ line 3<br>
+ </div>
+ )HTML");
+ Element& target = *GetDocument().getElementById("target");
+ target.parentNode()->appendChild(Text::Create(GetDocument(), "XYZ"));
+ GetDocument().UpdateStyleAndLayoutTree();
+ TestFirstDirtyLineIndex("container", 1);
+}
+
+TEST_F(NGFragmentItemTest, MarkLineBoxesDirtyByInsertAtMiddle) {
+ SetBodyInnerHTML(R"HTML(
+ <div id=container>
+ line 1<br>
+ <b id=target>line 2</b><br>
+ line 3<br>
+ </div>
+ )HTML");
+ Element& target = *GetDocument().getElementById("target");
+ target.parentNode()->insertBefore(Text::Create(GetDocument(), "XYZ"),
+ target.nextSibling());
+ GetDocument().UpdateStyleAndLayoutTree();
+ // TODO(kojii): This can be optimized more.
+ TestFirstDirtyLineIndex("container", 0);
+}
+
+TEST_F(NGFragmentItemTest, MarkLineBoxesDirtyByTextSetData) {
+ SetBodyInnerHTML(R"HTML(
+ <div id=container>
+ line 1<br>
+ <b id=target>line 2</b><br>
+ line 3<br>
+ </div>
+ )HTML");
+ Element& target = *GetDocument().getElementById("target");
+ To<Text>(*target.firstChild()).setData("abc");
+ // TODO(kojii): This can be optimized more.
+ TestFirstDirtyLineIndex("container", 0);
+}
+
+TEST_F(NGFragmentItemTest, MarkLineBoxesDirtyWrappedLine) {
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ #container {
+ font-size: 10px;
+ width: 10ch;
+ }
+ </style>
+ <div id=container>
+ 1234567
+ 123456<span id="target">7</span>
+ </div>
+ )HTML");
+ Element& target = *GetDocument().getElementById("target");
+ target.remove();
+ // TODO(kojii): This can be optimized more.
+ TestFirstDirtyLineIndex("container", 0);
+}
+
+TEST_F(NGFragmentItemTest, MarkLineBoxesDirtyInsideInlineBlock) {
+ SetBodyInnerHTML(R"HTML(
+ <div id=container>
+ <div id="inline-block" style="display: inline-block">
+ <span id="target">DELETE ME</span>
+ </div>
+ </div>
+ )HTML");
+ Element& target = *GetDocument().getElementById("target");
+ target.remove();
+ TestFirstDirtyLineIndex("container", 0);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items.cc b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items.cc
index 794995bd7bc..59d6f53c852 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items.cc
@@ -4,43 +4,333 @@
#include "third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items.h"
+#include "third_party/blink/renderer/core/layout/layout_block.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items_builder.h"
+#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.h"
+#include "third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h"
+#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
namespace blink {
+namespace {
+
+inline bool ShouldSetFirstAndLastForNode() {
+ return RuntimeEnabledFeatures::LayoutNGFragmentTraversalEnabled();
+}
+
+} // namespace
+
NGFragmentItems::NGFragmentItems(NGFragmentItemsBuilder* builder)
- : items_(std::move(builder->items_)),
- text_content_(std::move(builder->text_content_)),
- first_line_text_content_(std::move(builder->first_line_text_content_)) {}
+ : text_content_(std::move(builder->text_content_)),
+ first_line_text_content_(std::move(builder->first_line_text_content_)),
+ size_(builder->items_.size()) {
+ NGFragmentItemsBuilder::ItemWithOffsetList& source_items = builder->items_;
+ for (unsigned i = 0; i < size_; ++i) {
+ // Call the move constructor to move without |AddRef|. Items in
+ // |NGFragmentItemsBuilder| are not used after |this| was constructed.
+ DCHECK(source_items[i].item);
+ new (&items_[i])
+ scoped_refptr<const NGFragmentItem>(std::move(source_items[i].item));
+ DCHECK(!source_items[i].item); // Ensure the source was moved.
+ }
+}
-// static
-void NGFragmentItems::AssociateWithLayoutObject(
- Vector<std::unique_ptr<NGFragmentItem>>* items) {
- // items_[0] can be:
- // - kBox for list marker, e.g. <li>abc</li>
- // - kLine for line, e.g. <div>abc</div>
- // Calling get() is necessary below because operator<< in std::unique_ptr is
- // a C++20 feature.
- // TODO(https://crbug.com/980914): Drop .get() once we move to C++20.
- DCHECK(items->IsEmpty() || (*items)[0]->IsContainer()) << (*items)[0].get();
- HashMap<const LayoutObject*, wtf_size_t> last_fragment_map;
- for (wtf_size_t index = 1u; index < items->size(); ++index) {
- const NGFragmentItem& item = *(*items)[index];
- if (item.Type() == NGFragmentItem::kLine)
+NGFragmentItems::~NGFragmentItems() {
+ for (unsigned i = 0; i < size_; ++i)
+ items_[i]->Release();
+}
+
+bool NGFragmentItems::IsSubSpan(const Span& span) const {
+ return span.empty() ||
+ (span.data() >= ItemsData() && &span.back() < ItemsData() + Size());
+}
+
+void NGFragmentItems::FinalizeAfterLayout(
+ const Vector<scoped_refptr<const NGLayoutResult>, 1>& results) {
+ HashMap<const LayoutObject*, const NGFragmentItem*> first_and_last;
+ for (const auto& result : results) {
+ const auto& fragment =
+ To<NGPhysicalBoxFragment>(result->PhysicalFragment());
+ const NGFragmentItems* current = fragment.Items();
+ if (UNLIKELY(!current))
continue;
- LayoutObject* const layout_object = item.GetMutableLayoutObject();
- DCHECK(layout_object->IsInLayoutNGInlineFormattingContext()) << item;
- auto insert_result = last_fragment_map.insert(layout_object, index);
- if (insert_result.is_new_entry) {
- layout_object->SetFirstInlineFragmentItemIndex(index);
+ HashMap<const LayoutObject*, wtf_size_t> last_fragment_map;
+ const Span items = current->Items();
+ wtf_size_t index = 0;
+ for (const scoped_refptr<const NGFragmentItem>& item : items) {
+ ++index;
+ if (item->Type() == NGFragmentItem::kLine) {
+ DCHECK_EQ(item->DeltaToNextForSameLayoutObject(), 0u);
+ continue;
+ }
+ LayoutObject* const layout_object = item->GetMutableLayoutObject();
+ if (UNLIKELY(layout_object->IsFloating())) {
+ DCHECK_EQ(item->DeltaToNextForSameLayoutObject(), 0u);
+ continue;
+ }
+ DCHECK(!layout_object->IsOutOfFlowPositioned());
+ DCHECK(layout_object->IsInLayoutNGInlineFormattingContext()) << *item;
+ item->SetDeltaToNextForSameLayoutObject(0);
+
+ if (ShouldSetFirstAndLastForNode()) {
+ bool is_first_for_node =
+ first_and_last.Set(layout_object, item.get()).is_new_entry;
+ item->SetIsFirstForNode(is_first_for_node);
+ item->SetIsLastForNode(false);
+ }
+
+ // TODO(layout-dev): Make this work for multiple box fragments (block
+ // fragmentation).
+ if (!fragment.IsFirstForNode())
+ continue;
+
+ auto insert_result = last_fragment_map.insert(layout_object, index);
+ if (insert_result.is_new_entry) {
+ DCHECK_EQ(layout_object->FirstInlineFragmentItemIndex(), 0u);
+ layout_object->SetFirstInlineFragmentItemIndex(index);
+ continue;
+ }
+ const wtf_size_t last_index = insert_result.stored_value->value;
+ insert_result.stored_value->value = index;
+ DCHECK_GT(last_index, 0u) << *item;
+ DCHECK_LT(last_index, items.size());
+ DCHECK_LT(last_index, index);
+ DCHECK_EQ(items[last_index - 1]->DeltaToNextForSameLayoutObject(), 0u);
+ items[last_index - 1]->SetDeltaToNextForSameLayoutObject(index -
+ last_index);
+ }
+ }
+ if (!ShouldSetFirstAndLastForNode())
+ return;
+ for (const auto& iter : first_and_last)
+ iter.value->SetIsLastForNode(true);
+}
+
+void NGFragmentItems::ClearAssociatedFragments(LayoutObject* container) {
+ // Clear by traversing |LayoutObject| tree rather than |NGFragmentItem|
+ // because a) we don't need to modify |NGFragmentItem|, and in general the
+ // number of |LayoutObject| is less than the number of |NGFragmentItem|.
+ for (LayoutObject* child = container->SlowFirstChild(); child;
+ child = child->NextSibling()) {
+ if (UNLIKELY(!child->IsInLayoutNGInlineFormattingContext() ||
+ child->IsFloatingOrOutOfFlowPositioned()))
continue;
+ child->ClearFirstInlineFragmentItemIndex();
+
+ // Children of |LayoutInline| are part of this inline formatting context,
+ // but children of other |LayoutObject| (e.g., floats, oof, inline-blocks)
+ // are not.
+ if (child->IsLayoutInline())
+ ClearAssociatedFragments(child);
+ }
+}
+
+// static
+bool NGFragmentItems::CanReuseAll(NGInlineCursor* cursor) {
+ for (; *cursor; cursor->MoveToNext()) {
+ const NGFragmentItem& item = *cursor->Current().Item();
+ if (!item.CanReuse())
+ return false;
+ }
+ return true;
+}
+
+const NGFragmentItem* NGFragmentItems::EndOfReusableItems() const {
+ const NGFragmentItem* last_line_start = &front();
+ for (NGInlineCursor cursor(*this); cursor;) {
+ const NGFragmentItem& item = *cursor.Current();
+ if (item.IsDirty())
+ return &item;
+
+ // Top-level fragments that are not line box cannot be reused; e.g., oof
+ // or list markers.
+ if (item.Type() != NGFragmentItem::kLine)
+ return &item;
+
+ const NGPhysicalLineBoxFragment* line_box_fragment = item.LineBoxFragment();
+ DCHECK(line_box_fragment);
+
+ // If there is a dirty item in the middle of a line, its previous line is
+ // not reusable, because the dirty item may affect the previous line to wrap
+ // differently.
+ NGInlineCursor line = cursor.CursorForDescendants();
+ if (!CanReuseAll(&line))
+ return last_line_start;
+
+ // Abort if the line propagated its descendants to outside of the line.
+ // They are propagated through NGLayoutResult, which we don't cache.
+ if (line_box_fragment->HasPropagatedDescendants())
+ return &item;
+
+ // TODO(kojii): Running the normal layout code at least once for this
+ // child helps reducing the code to setup internal states after the
+ // partial. Remove the last fragment if it is the end of the
+ // fragmentation to do so, but we should figure out how to setup the
+ // states without doing this.
+ const NGBreakToken* break_token = line_box_fragment->BreakToken();
+ DCHECK(break_token);
+ if (break_token->IsFinished())
+ return &item;
+
+ last_line_start = &item;
+ cursor.MoveToNextSkippingChildren();
+ }
+ return nullptr; // all items are reusable.
+}
+
+bool NGFragmentItems::TryDirtyFirstLineFor(
+ const LayoutObject& layout_object) const {
+ DCHECK(layout_object.IsInLayoutNGInlineFormattingContext());
+ DCHECK(!layout_object.IsFloatingOrOutOfFlowPositioned());
+ if (wtf_size_t index = layout_object.FirstInlineFragmentItemIndex()) {
+ const NGFragmentItem& item = *Items()[index - 1];
+ DCHECK_EQ(&layout_object, item.GetLayoutObject());
+ item.SetDirty();
+ return true;
+ }
+ return false;
+}
+
+bool NGFragmentItems::TryDirtyLastLineFor(
+ const LayoutObject& layout_object) const {
+ NGInlineCursor cursor(*this);
+ cursor.MoveTo(layout_object);
+ if (!cursor)
+ return false;
+ cursor.MoveToLastForSameLayoutObject();
+ DCHECK(cursor.Current().Item());
+ const NGFragmentItem& item = *cursor.Current().Item();
+ DCHECK_EQ(&layout_object, item.GetLayoutObject());
+ item.SetDirty();
+ return true;
+}
+
+void NGFragmentItems::DirtyLinesFromChangedChild(
+ const LayoutObject* child) const {
+ if (UNLIKELY(!child)) {
+ front().SetDirty();
+ return;
+ }
+
+ if (child->IsInLayoutNGInlineFormattingContext() &&
+ !child->IsFloatingOrOutOfFlowPositioned() && TryDirtyFirstLineFor(*child))
+ return;
+
+ // If |child| is new, or did not generate fragments, mark the fragments for
+ // previous |LayoutObject| instead.
+ while (true) {
+ if (const LayoutObject* previous = child->PreviousSibling()) {
+ while (const LayoutInline* layout_inline =
+ ToLayoutInlineOrNull(previous)) {
+ if (const LayoutObject* last_child = layout_inline->LastChild())
+ previous = last_child;
+ else
+ break;
+ }
+ child = previous;
+ if (UNLIKELY(child->IsFloatingOrOutOfFlowPositioned()))
+ continue;
+ if (child->IsInLayoutNGInlineFormattingContext() &&
+ TryDirtyLastLineFor(*child))
+ return;
+ continue;
+ }
+
+ child = child->Parent();
+ if (!child || child->IsLayoutBlockFlow()) {
+ front().SetDirty();
+ return;
+ }
+ DCHECK(child->IsLayoutInline());
+ if (child->IsInLayoutNGInlineFormattingContext() &&
+ TryDirtyFirstLineFor(*child))
+ return;
+ }
+}
+
+void NGFragmentItems::DirtyLinesFromNeedsLayout(
+ const LayoutBlockFlow* container) const {
+ DCHECK_EQ(this, container->FragmentItems());
+ for (LayoutObject* layout_object = container->FirstChild(); layout_object;) {
+ if (layout_object->IsText()) {
+ if (layout_object->SelfNeedsLayout()) {
+ DirtyLinesFromChangedChild(layout_object);
+ return;
+ }
+ } else if (auto* layout_inline = ToLayoutInlineOrNull(layout_object)) {
+ if (layout_object->SelfNeedsLayout()) {
+ DirtyLinesFromChangedChild(layout_object);
+ return;
+ }
+ if (layout_object->NormalChildNeedsLayout() ||
+ layout_object->PosChildNeedsLayout()) {
+ if (LayoutObject* child = layout_inline->FirstChild()) {
+ layout_object = child;
+ continue;
+ }
+ }
+ } else {
+ if (layout_object->NeedsLayout()) {
+ DirtyLinesFromChangedChild(layout_object);
+ return;
+ }
+ }
+
+ layout_object = layout_object->NextInPreOrderAfterChildren(container);
+ }
+}
+
+// static
+void NGFragmentItems::LayoutObjectWillBeMoved(
+ const LayoutObject& layout_object) {
+ if (UNLIKELY(layout_object.IsInsideFlowThread())) {
+ // TODO(crbug.com/829028): Make NGInlineCursor handle block
+ // fragmentation. For now, perform a slow walk here manually.
+ const LayoutBlock& container = *layout_object.ContainingBlock();
+ for (wtf_size_t idx = 0; idx < container.PhysicalFragmentCount(); idx++) {
+ const NGPhysicalBoxFragment& fragment =
+ *container.GetPhysicalFragment(idx);
+ DCHECK(fragment.Items());
+ for (const auto& item : fragment.Items()->Items()) {
+ if (item->GetLayoutObject() == &layout_object)
+ item->LayoutObjectWillBeMoved();
+ }
+ }
+ return;
+ }
+
+ NGInlineCursor cursor;
+ cursor.MoveTo(layout_object);
+ for (; cursor; cursor.MoveToNextForSameLayoutObject()) {
+ const NGFragmentItem* item = cursor.Current().Item();
+ item->LayoutObjectWillBeMoved();
+ }
+}
+
+// static
+void NGFragmentItems::LayoutObjectWillBeDestroyed(
+ const LayoutObject& layout_object) {
+ if (UNLIKELY(layout_object.IsInsideFlowThread())) {
+ // TODO(crbug.com/829028): Make NGInlineCursor handle block
+ // fragmentation. For now, perform a slow walk here manually.
+ const LayoutBlock& container = *layout_object.ContainingBlock();
+ for (wtf_size_t idx = 0; idx < container.PhysicalFragmentCount(); idx++) {
+ const NGPhysicalBoxFragment& fragment =
+ *container.GetPhysicalFragment(idx);
+ DCHECK(fragment.Items());
+ for (const auto& item : fragment.Items()->Items()) {
+ if (item->GetLayoutObject() == &layout_object)
+ item->LayoutObjectWillBeDestroyed();
+ }
}
- const wtf_size_t last_index = insert_result.stored_value->value;
- insert_result.stored_value->value = index;
- DCHECK_GT(last_index, 0u) << item;
- DCHECK_LT(last_index, items->size());
- DCHECK_LT(last_index, index);
- (*items)[last_index]->SetDeltaToNextForSameLayoutObject(index - last_index);
+ return;
+ }
+
+ NGInlineCursor cursor;
+ cursor.MoveTo(layout_object);
+ for (; cursor; cursor.MoveToNextForSameLayoutObject()) {
+ const NGFragmentItem* item = cursor.Current().Item();
+ item->LayoutObjectWillBeDestroyed();
}
}
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items.h b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items.h
index 76c95f180a5..eebdb5f616e 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items.h
@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_FRAGMENT_ITEMS_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_FRAGMENT_ITEMS_H_
+#include "base/containers/span.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.h"
@@ -18,24 +19,74 @@ class NGFragmentItemsBuilder;
// transformed to a flat list of |NGFragmentItem| and stored in this class.
class CORE_EXPORT NGFragmentItems {
public:
- NGFragmentItems(NGFragmentItemsBuilder* builder);
+ explicit NGFragmentItems(NGFragmentItemsBuilder* builder);
+ ~NGFragmentItems();
- const Vector<std::unique_ptr<NGFragmentItem>>& Items() const {
- return items_;
+ wtf_size_t Size() const { return size_; }
+
+ using Span = base::span<const scoped_refptr<const NGFragmentItem>>;
+ Span Items() const { return base::make_span(ItemsData(), size_); }
+ bool IsSubSpan(const Span& span) const;
+
+ const NGFragmentItem& front() const {
+ CHECK_GE(size_, 1u);
+ return *items_[0];
}
const String& Text(bool first_line) const {
return UNLIKELY(first_line) ? first_line_text_content_ : text_content_;
}
- static void AssociateWithLayoutObject(
- Vector<std::unique_ptr<NGFragmentItem>>* items);
+ // Associate |NGFragmentItem|s with |LayoutObject|s and finalize the items
+ // (set which ones are the first / last for the LayoutObject).
+ static void FinalizeAfterLayout(
+ const Vector<scoped_refptr<const NGLayoutResult>, 1>&);
+
+ // Disassociate |NGFragmentItem|s with |LayoutObject|s. And more.
+ static void ClearAssociatedFragments(LayoutObject* container);
+
+ // Notify when |LayoutObject| will be destroyed/moved.
+ static void LayoutObjectWillBeDestroyed(const LayoutObject& layout_object);
+ static void LayoutObjectWillBeMoved(const LayoutObject& layout_object);
+
+ // Returns the end (next of the last) item that are reusable. If no items are
+ // reusable, it is the first item.
+ const NGFragmentItem* EndOfReusableItems() const;
+
+ // Mark items dirty when |child| is removed from the tree.
+ void DirtyLinesFromChangedChild(const LayoutObject* child) const;
+
+ // Mark items dirty from |LayoutObject::NeedsLayout| flags.
+ void DirtyLinesFromNeedsLayout(const LayoutBlockFlow* block_flow) const;
+
+ // The byte size of this instance.
+ constexpr static wtf_size_t ByteSizeFor(wtf_size_t count) {
+ return sizeof(NGFragmentItems) + count * sizeof(items_[0]);
+ }
+ wtf_size_t ByteSize() const { return ByteSizeFor(Size()); }
private:
- // TODO(kojii): inline capacity TBD.
- Vector<std::unique_ptr<NGFragmentItem>> items_;
+ const scoped_refptr<const NGFragmentItem>* ItemsData() const {
+ return reinterpret_cast<const scoped_refptr<const NGFragmentItem>*>(items_);
+ }
+
+ static bool CanReuseAll(NGInlineCursor* cursor);
+ bool TryDirtyFirstLineFor(const LayoutObject& layout_object) const;
+ bool TryDirtyLastLineFor(const LayoutObject& layout_object) const;
+
String text_content_;
String first_line_text_content_;
+
+ wtf_size_t size_;
+
+ // Semantically, |items_| is a flexible array of |scoped_refptr<const
+ // NGFragmentItem>|, but |scoped_refptr| has non-trivial destruction which
+ // causes an error in clang. Declare as a flexible array of |NGFragmentItem*|
+ // instead. Please see |ItemsData()|.
+ static_assert(
+ sizeof(NGFragmentItem*) == sizeof(scoped_refptr<const NGFragmentItem>),
+ "scoped_refptr must be the size of a pointer for |ItemsData()| to work");
+ NGFragmentItem* items_[];
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items_builder.cc b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items_builder.cc
index 243c9d3622c..452e1c2f102 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items_builder.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items_builder.cc
@@ -5,17 +5,27 @@
#include "third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items_builder.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items.h"
+#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.h"
#include "third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.h"
#include "third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h"
namespace blink {
-void NGFragmentItemsBuilder::SetTextContent(const NGInlineNode& node) {
+NGFragmentItemsBuilder::NGFragmentItemsBuilder(const NGInlineNode& node) {
const NGInlineItemsData& items_data = node.ItemsData(false);
text_content_ = items_data.text_content;
const NGInlineItemsData& first_line = node.ItemsData(true);
if (&items_data != &first_line)
first_line_text_content_ = first_line.text_content;
+
+ // For a very large inline formatting context, the vector reallocation becomes
+ // hot. Estimate the number of items by assuming 40 characters can fit in a
+ // line, and each line contains 3 items; a line box, an inline box, and a
+ // text. If it will require more than one reallocations, make an initial
+ // reservation here.
+ const wtf_size_t estimated_item_count = text_content_.length() / 40 * 3;
+ if (UNLIKELY(estimated_item_count > items_.capacity() * 2))
+ items_.ReserveInitialCapacity(estimated_item_count);
}
void NGFragmentItemsBuilder::SetCurrentLine(
@@ -29,30 +39,29 @@ void NGFragmentItemsBuilder::SetCurrentLine(
void NGFragmentItemsBuilder::AddLine(const NGPhysicalLineBoxFragment& line,
const LogicalOffset& offset) {
- DCHECK_EQ(items_.size(), offsets_.size());
DCHECK(!is_converted_to_physical_);
#if DCHECK_IS_ON()
DCHECK_EQ(current_line_fragment_, &line);
#endif
// Reserve the capacity for (children + line box item).
- wtf_size_t size_before = items_.size();
- wtf_size_t capacity = size_before + current_line_.size() + 1;
- items_.ReserveCapacity(capacity);
- offsets_.ReserveCapacity(capacity);
+ const wtf_size_t size_before = items_.size();
+ const wtf_size_t estimated_size = size_before + current_line_.size() + 1;
+ const wtf_size_t old_capacity = items_.capacity();
+ if (estimated_size > old_capacity)
+ items_.ReserveCapacity(std::max(estimated_size, old_capacity * 2));
// Add an empty item so that the start of the line can be set later.
- wtf_size_t line_start_index = items_.size();
- items_.Grow(line_start_index + 1);
- offsets_.push_back(offset);
+ const wtf_size_t line_start_index = items_.size();
+ items_.emplace_back(offset);
AddItems(current_line_.begin(), current_line_.end());
// All children are added. Create an item for the start of the line.
- wtf_size_t item_count = items_.size() - line_start_index;
- items_[line_start_index] = std::make_unique<NGFragmentItem>(line, item_count);
- // TODO(kojii): We probably need an end marker too for the reverse-order
- // traversals.
+ const wtf_size_t item_count = items_.size() - line_start_index;
+ DCHECK(!items_[line_start_index].item);
+ items_[line_start_index].item =
+ base::MakeRefCounted<NGFragmentItem>(line, item_count);
// Keep children's offsets relative to |line|. They will be adjusted later in
// |ConvertToPhysical()|.
@@ -61,74 +70,52 @@ void NGFragmentItemsBuilder::AddLine(const NGPhysicalLineBoxFragment& line,
#if DCHECK_IS_ON()
current_line_fragment_ = nullptr;
#endif
+
+ DCHECK_LE(items_.size(), estimated_size);
}
void NGFragmentItemsBuilder::AddItems(Child* child_begin, Child* child_end) {
- DCHECK_EQ(items_.size(), offsets_.size());
DCHECK(!is_converted_to_physical_);
for (Child* child_iter = child_begin; child_iter != child_end;) {
Child& child = *child_iter;
- if (const NGPhysicalTextFragment* text = child.fragment.get()) {
- items_.push_back(std::make_unique<NGFragmentItem>(*text));
- offsets_.push_back(child.rect.offset);
+ // OOF children should have been added to their parent box fragments.
+ DCHECK(!child.out_of_flow_positioned_box);
+ if (!child.fragment_item) {
++child_iter;
continue;
}
- if (child.layout_result || child.inline_item) {
- // Create an item if this box has no inline children.
- std::unique_ptr<NGFragmentItem> item;
- if (child.layout_result) {
- const NGPhysicalBoxFragment& box =
- To<NGPhysicalBoxFragment>(child.layout_result->PhysicalFragment());
- item = std::make_unique<NGFragmentItem>(box, child.ResolvedDirection());
- } else {
- DCHECK(child.inline_item);
- item = std::make_unique<NGFragmentItem>(
- *child.inline_item,
- ToPhysicalSize(child.rect.size,
- child.inline_item->Style()->GetWritingMode()));
- }
-
- // Take the fast path when we know |child| does not have child items.
- if (child.children_count <= 1) {
- items_.push_back(std::move(item));
- offsets_.push_back(child.rect.offset);
- ++child_iter;
- continue;
- }
- DCHECK(!item->IsFloating());
-
- // Children of inline boxes are flattened and added to |items_|, with the
- // count of descendant items to preserve the tree structure.
- //
- // Add an empty item so that the start of the box can be set later.
- wtf_size_t box_start_index = items_.size();
- items_.Grow(box_start_index + 1);
- offsets_.push_back(child.rect.offset);
-
- // Add all children, including their desendants, skipping this item.
- CHECK_GE(child.children_count, 1u); // 0 will loop infinitely.
- Child* end_child_iter = child_iter + child.children_count;
- CHECK_LE(end_child_iter - child_begin, child_end - child_begin);
- AddItems(child_iter + 1, end_child_iter);
- child_iter = end_child_iter;
-
- // All children are added. Compute how many items are actually added. The
- // number of items added maybe different from |child.children_count|.
- wtf_size_t item_count = items_.size() - box_start_index;
-
- // Create an item for the start of the box.
- item->SetDescendantsCount(item_count);
- items_[box_start_index] = std::move(item);
+ if (child.children_count <= 1) {
+ items_.emplace_back(std::move(child.fragment_item), child.rect.offset);
+ ++child_iter;
continue;
}
-
- // OOF children should have been added to their parent box fragments.
- // TODO(kojii): Consider handling them in NGFragmentItem too.
- DCHECK(!child.out_of_flow_positioned_box);
- ++child_iter;
+ DCHECK(child.fragment_item->IsContainer());
+ DCHECK(!child.fragment_item->IsFloating());
+
+ // Children of inline boxes are flattened and added to |items_|, with the
+ // count of descendant items to preserve the tree structure.
+ //
+ // Add an empty item so that the start of the box can be set later.
+ wtf_size_t box_start_index = items_.size();
+ items_.emplace_back(child.rect.offset);
+
+ // Add all children, including their desendants, skipping this item.
+ CHECK_GE(child.children_count, 1u); // 0 will loop infinitely.
+ Child* end_child_iter = child_iter + child.children_count;
+ CHECK_LE(end_child_iter - child_begin, child_end - child_begin);
+ AddItems(child_iter + 1, end_child_iter);
+ child_iter = end_child_iter;
+
+ // All children are added. Compute how many items are actually added. The
+ // number of items added maybe different from |child.children_count|.
+ wtf_size_t item_count = items_.size() - box_start_index;
+
+ // Create an item for the start of the box.
+ child.fragment_item->SetDescendantsCount(item_count);
+ DCHECK(!items_[box_start_index].item);
+ items_[box_start_index].item = std::move(child.fragment_item);
}
}
@@ -140,12 +127,98 @@ void NGFragmentItemsBuilder::AddListMarker(
// Resolved direction matters only for inline items, and outside list markers
// are not inline.
const TextDirection resolved_direction = TextDirection::kLtr;
- items_.push_back(
- std::make_unique<NGFragmentItem>(marker_fragment, resolved_direction));
- offsets_.push_back(offset);
+ items_.emplace_back(
+ base::MakeRefCounted<NGFragmentItem>(marker_fragment, resolved_direction),
+ offset);
+}
+
+NGFragmentItemsBuilder::AddPreviousItemsResult
+NGFragmentItemsBuilder::AddPreviousItems(
+ const NGFragmentItems& items,
+ WritingMode writing_mode,
+ TextDirection direction,
+ const PhysicalSize& container_size,
+ NGBoxFragmentBuilder* container_builder,
+ bool stop_at_dirty) {
+ AddPreviousItemsResult result;
+ if (stop_at_dirty) {
+ DCHECK(container_builder);
+ DCHECK(text_content_);
+ } else {
+ DCHECK(!text_content_);
+ text_content_ = items.Text(false);
+ first_line_text_content_ = items.Text(true);
+ }
+
+ DCHECK(items_.IsEmpty());
+ const NGFragmentItems::Span source_items = items.Items();
+ const wtf_size_t estimated_size = source_items.size();
+ items_.ReserveCapacity(estimated_size);
+
+ // Convert offsets to logical. The logic is opposite to |ConvertToPhysical|.
+ // This is needed because the container size may be different, in that case,
+ // the physical offsets are different when `writing-mode: vertial-rl`.
+ DCHECK(!is_converted_to_physical_);
+ const WritingMode line_writing_mode = ToLineWritingMode(writing_mode);
+
+ const NGFragmentItem* const end_item =
+ stop_at_dirty ? items.EndOfReusableItems() : nullptr;
+ const NGFragmentItem* last_line_start_item = nullptr;
+ LayoutUnit used_block_size;
+
+ for (NGInlineCursor cursor(items); cursor;) {
+ DCHECK(cursor.Current().Item());
+ const NGFragmentItem& item = *cursor.Current().Item();
+ if (&item == end_item)
+ break;
+ DCHECK(!item.IsDirty());
+
+ const LogicalOffset item_offset =
+ item.OffsetInContainerBlock().ConvertToLogical(
+ writing_mode, direction, container_size, item.Size());
+ items_.emplace_back(&item, item_offset);
+
+ if (item.Type() == NGFragmentItem::kLine) {
+ const PhysicalRect line_box_bounds = item.RectInContainerBlock();
+ for (NGInlineCursor line = cursor.CursorForDescendants(); line;
+ line.MoveToNext()) {
+ const NGFragmentItem& line_child = *line.Current().Item();
+ DCHECK(line_child.CanReuse());
+ items_.emplace_back(
+ &line_child,
+ (line_child.OffsetInContainerBlock() - line_box_bounds.offset)
+ .ConvertToLogical(line_writing_mode, TextDirection::kLtr,
+ line_box_bounds.size, line_child.Size()));
+ }
+ cursor.MoveToNextSkippingChildren();
+ DCHECK(item.LineBoxFragment());
+ if (stop_at_dirty) {
+ container_builder->AddChild(*item.LineBoxFragment(), item_offset);
+ last_line_start_item = &item;
+ used_block_size +=
+ item.Size().ConvertToLogical(writing_mode).block_size;
+ }
+ continue;
+ }
+
+ DCHECK_NE(item.Type(), NGFragmentItem::kLine);
+ DCHECK(!stop_at_dirty);
+ cursor.MoveToNext();
+ }
+
+ if (stop_at_dirty && last_line_start_item) {
+ result.inline_break_token = last_line_start_item->InlineBreakToken();
+ DCHECK(result.inline_break_token);
+ DCHECK(!result.inline_break_token->IsFinished());
+ result.used_block_size = used_block_size;
+ result.succeeded = true;
+ }
+
+ DCHECK_LE(items_.size(), estimated_size);
+ return result;
}
-const Vector<std::unique_ptr<NGFragmentItem>>& NGFragmentItemsBuilder::Items(
+const NGFragmentItemsBuilder::ItemWithOffsetList& NGFragmentItemsBuilder::Items(
WritingMode writing_mode,
TextDirection direction,
const PhysicalSize& outer_size) {
@@ -158,7 +231,6 @@ const Vector<std::unique_ptr<NGFragmentItem>>& NGFragmentItemsBuilder::Items(
void NGFragmentItemsBuilder::ConvertToPhysical(WritingMode writing_mode,
TextDirection direction,
const PhysicalSize& outer_size) {
- CHECK_EQ(items_.size(), offsets_.size());
if (is_converted_to_physical_)
return;
@@ -166,13 +238,10 @@ void NGFragmentItemsBuilder::ConvertToPhysical(WritingMode writing_mode,
// convert their logical offsets.
const WritingMode line_writing_mode = ToLineWritingMode(writing_mode);
- std::unique_ptr<NGFragmentItem>* item_iter = items_.begin();
- const LogicalOffset* offset = offsets_.begin();
- for (; item_iter != items_.end(); ++item_iter, ++offset) {
- DCHECK_NE(offset, offsets_.end());
- NGFragmentItem* item = item_iter->get();
- item->SetOffset(offset->ConvertToPhysical(writing_mode, direction,
- outer_size, item->Size()));
+ for (ItemWithOffset* iter = items_.begin(); iter != items_.end(); ++iter) {
+ NGFragmentItem* item = const_cast<NGFragmentItem*>(iter->item.get());
+ item->SetOffset(iter->offset.ConvertToPhysical(writing_mode, direction,
+ outer_size, item->Size()));
// Transform children of lines separately from children of the block,
// because they may have different directions from the block. To do
@@ -183,17 +252,15 @@ void NGFragmentItemsBuilder::ConvertToPhysical(WritingMode writing_mode,
if (descendants_count) {
const PhysicalRect line_box_bounds = item->RectInContainerBlock();
while (--descendants_count) {
- ++offset;
- ++item_iter;
- DCHECK_NE(offset, offsets_.end());
- DCHECK_NE(item_iter, items_.end());
- item = item_iter->get();
+ ++iter;
+ DCHECK_NE(iter, items_.end());
+ item = const_cast<NGFragmentItem*>(iter->item.get());
// Use `kLtr` because inline items are after bidi-reoder, and that
// their offset is visual, not logical.
- item->SetOffset(
- offset->ConvertToPhysical(line_writing_mode, TextDirection::kLtr,
- line_box_bounds.size, item->Size()) +
- line_box_bounds.offset);
+ item->SetOffset(iter->offset.ConvertToPhysical(
+ line_writing_mode, TextDirection::kLtr,
+ line_box_bounds.size, item->Size()) +
+ line_box_bounds.offset);
}
}
}
@@ -204,10 +271,9 @@ void NGFragmentItemsBuilder::ConvertToPhysical(WritingMode writing_mode,
base::Optional<LogicalOffset> NGFragmentItemsBuilder::LogicalOffsetFor(
const LayoutObject& layout_object) const {
- DCHECK_EQ(items_.size(), offsets_.size());
- for (const std::unique_ptr<NGFragmentItem>& item : items_) {
+ for (const ItemWithOffset& item : items_) {
if (item->GetLayoutObject() == &layout_object)
- return offsets_[&item - items_.begin()];
+ return item.offset;
}
return base::nullopt;
}
@@ -216,8 +282,8 @@ void NGFragmentItemsBuilder::ToFragmentItems(WritingMode writing_mode,
TextDirection direction,
const PhysicalSize& outer_size,
void* data) {
+ DCHECK(text_content_);
ConvertToPhysical(writing_mode, direction, outer_size);
- NGFragmentItems::AssociateWithLayoutObject(&items_);
new (data) NGFragmentItems(this);
}
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items_builder.h b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items_builder.h
index 84be85e4132..c161eed2aec 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items_builder.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items_builder.h
@@ -11,7 +11,6 @@
namespace blink {
-class NGBoxFragmentBuilder;
class NGFragmentItem;
class NGFragmentItems;
class NGInlineNode;
@@ -23,7 +22,10 @@ class CORE_EXPORT NGFragmentItemsBuilder {
STACK_ALLOCATED();
public:
- NGFragmentItemsBuilder(NGBoxFragmentBuilder* box_builder) {}
+ NGFragmentItemsBuilder() = default;
+ explicit NGFragmentItemsBuilder(const NGInlineNode& node);
+
+ wtf_size_t Size() const { return items_.size(); }
// Returns true if we have any floating descendants which need to be
// traversed during the float paint phase.
@@ -36,7 +38,6 @@ class CORE_EXPORT NGFragmentItemsBuilder {
? first_line_text_content_
: text_content_;
}
- void SetTextContent(const NGInlineNode& node);
// The caller should create a |ChildList| for a complete line and add to this
// builder.
@@ -59,6 +60,48 @@ class CORE_EXPORT NGFragmentItemsBuilder {
void AddListMarker(const NGPhysicalBoxFragment& marker_fragment,
const LogicalOffset& offset);
+ // See |AddPreviousItems| below.
+ struct AddPreviousItemsResult {
+ STACK_ALLOCATED();
+
+ public:
+ const NGInlineBreakToken* inline_break_token = nullptr;
+ LayoutUnit used_block_size;
+ bool succeeded = false;
+ };
+
+ // Add previously laid out |NGFragmentItems|.
+ //
+ // When |stop_at_dirty| is true, this function checks reusability of previous
+ // items and stops copying before the first dirty line.
+ AddPreviousItemsResult AddPreviousItems(
+ const NGFragmentItems& items,
+ WritingMode writing_mode,
+ TextDirection direction,
+ const PhysicalSize& container_size,
+ NGBoxFragmentBuilder* container_builder = nullptr,
+ bool stop_at_dirty = false);
+
+ struct ItemWithOffset {
+ DISALLOW_NEW();
+
+ public:
+ ItemWithOffset(scoped_refptr<const NGFragmentItem> item,
+ const LogicalOffset& offset)
+ : item(std::move(item)), offset(offset) {}
+ explicit ItemWithOffset(const LogicalOffset& offset) : offset(offset) {}
+
+ const NGFragmentItem& operator*() const { return *item; }
+ const NGFragmentItem* operator->() const { return item.get(); }
+
+ scoped_refptr<const NGFragmentItem> item;
+ LogicalOffset offset;
+ };
+
+ // Give an inline size, the allocation of this vector is hot. "128" is
+ // heuristic. Usually 10-40, some wikipedia pages have >64 items.
+ using ItemWithOffsetList = Vector<ItemWithOffset, 128>;
+
// Find |LogicalOffset| of the first |NGFragmentItem| for |LayoutObject|.
base::Optional<LogicalOffset> LogicalOffsetFor(const LayoutObject&) const;
@@ -67,8 +110,9 @@ class CORE_EXPORT NGFragmentItemsBuilder {
// containing block geometry for OOF-positioned nodes.
//
// Once this method has been called, new items cannot be added.
- const Vector<std::unique_ptr<NGFragmentItem>>&
- Items(WritingMode, TextDirection, const PhysicalSize& outer_size);
+ const ItemWithOffsetList& Items(WritingMode,
+ TextDirection,
+ const PhysicalSize& outer_size);
// Build a |NGFragmentItems|. The builder cannot build twice because data set
// to this builder may be cleared.
@@ -84,8 +128,7 @@ class CORE_EXPORT NGFragmentItemsBuilder {
TextDirection direction,
const PhysicalSize& outer_size);
- Vector<std::unique_ptr<NGFragmentItem>> items_;
- Vector<LogicalOffset> offsets_;
+ ItemWithOffsetList items_;
String text_content_;
String first_line_text_content_;
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.cc b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.cc
index cc0d8d8d3b4..33ba9243ca0 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.cc
@@ -116,8 +116,10 @@ NGInlineBoxState* NGInlineLayoutStateStack::OnBeginPlaceItems(
// For the following lines, clear states that are not shared across lines.
for (NGInlineBoxState& box : stack_) {
box.fragment_start = line_box->size();
- if (&box != stack_.begin())
+ if (box.needs_box_fragment) {
+ DCHECK_NE(&box, stack_.begin());
AddBoxFragmentPlaceholder(&box, line_box, baseline_type);
+ }
if (!line_height_quirk)
box.metrics = box.text_metrics;
else
@@ -158,7 +160,8 @@ NGInlineBoxState* NGInlineLayoutStateStack::OnOpenTag(
NGInlineBoxState* box =
OnOpenTag(item, item_result, baseline_type, *line_box);
box->needs_box_fragment = item.ShouldCreateBoxFragment();
- AddBoxFragmentPlaceholder(box, line_box, baseline_type);
+ if (box->needs_box_fragment)
+ AddBoxFragmentPlaceholder(box, line_box, baseline_type);
return box;
}
@@ -223,13 +226,8 @@ void NGInlineLayoutStateStack::EndBoxState(
NGInlineBoxState* box,
NGLineBoxFragmentBuilder::ChildList* line_box,
FontBaseline baseline_type) {
- if (!RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()) {
- if (box->needs_box_fragment)
- AddBoxData(box, line_box);
- } else {
- if (box->has_box_placeholder)
- AddBoxData(box, line_box);
- }
+ if (box->needs_box_fragment)
+ AddBoxData(box, line_box);
PositionPending position_pending =
ApplyBaselineShift(box, line_box, baseline_type);
@@ -512,10 +510,10 @@ void NGInlineLayoutStateStack::BoxData::UpdateFragmentEdges(
}
LayoutUnit NGInlineLayoutStateStack::ComputeInlinePositions(
- NGLineBoxFragmentBuilder::ChildList* line_box) {
+ NGLineBoxFragmentBuilder::ChildList* line_box,
+ LayoutUnit position) {
// At this point, children are in the visual order, and they have their
// origins at (0, 0). Accumulate inline offset from left to right.
- LayoutUnit position;
for (NGLineBoxFragmentBuilder::Child& child : *line_box) {
child.margin_line_left = child.rect.offset.inline_offset;
child.rect.offset.inline_offset += position;
@@ -658,8 +656,6 @@ NGInlineLayoutStateStack::BoxData::CreateBoxFragment(
// supported today.
box.SetBorderEdges({true, has_line_right_edge, true, has_line_left_edge});
- box.SetIsFirstForNode(has_line_left_edge);
-
for (unsigned i = fragment_start; i < fragment_end; i++) {
NGLineBoxFragmentBuilder::Child& child = (*line_box)[i];
if (child.out_of_flow_positioned_box) {
@@ -700,11 +696,9 @@ NGInlineLayoutStateStack::BoxData::CreateBoxFragment(
}
}
- if (!RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()) {
- // Inline boxes that produce DisplayItemClient should do full paint
- // invalidations.
- item->GetLayoutObject()->SetShouldDoFullPaintInvalidation();
- }
+ // Inline boxes that produce DisplayItemClient should do full paint
+ // invalidations.
+ item->GetLayoutObject()->SetShouldDoFullPaintInvalidation();
box.MoveOutOfFlowDescendantCandidatesToDescendants();
return box.ToInlineBoxFragment();
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.h b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.h
index 2431f010067..6dcee9c380a 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.h
@@ -168,7 +168,8 @@ class CORE_EXPORT NGInlineLayoutStateStack {
void UpdateFragmentedBoxDataEdges();
// Compute inline positions of fragments and boxes.
- LayoutUnit ComputeInlinePositions(NGLineBoxFragmentBuilder::ChildList*);
+ LayoutUnit ComputeInlinePositions(NGLineBoxFragmentBuilder::ChildList*,
+ LayoutUnit position);
// Create box fragments. This function turns a flat list of children into
// a box tree.
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.cc b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.cc
index bb39e1b44f1..88473e916fd 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.cc
@@ -15,7 +15,7 @@
namespace blink {
-void NGInlineCursor::MoveToItem(const ItemsSpan::iterator& iter) {
+inline void NGInlineCursor::MoveToItem(const ItemsSpan::iterator& iter) {
DCHECK(IsItemCursor());
DCHECK(iter >= items_.begin() && iter <= items_.end());
current_.item_iter_ = iter;
@@ -28,8 +28,7 @@ void NGInlineCursor::SetRoot(const NGFragmentItems& fragment_items,
DCHECK(!HasRoot());
fragment_items_ = &fragment_items;
items_ = items;
- DCHECK(items_.empty() || (items_.data() >= fragment_items_->Items().data() &&
- items_.data() < fragment_items_->Items().end()));
+ DCHECK(fragment_items_->IsSubSpan(items_));
MoveToItem(items_.begin());
}
@@ -128,11 +127,11 @@ const LayoutBlockFlow* NGInlineCursor::GetLayoutBlockFlow() const {
return nullptr;
}
-bool NGInlineCursor::HasChildren() const {
- if (current_.paint_fragment_)
- return current_.paint_fragment_->FirstChild();
- if (current_.item_)
- return current_.item_->HasChildren();
+bool NGInlineCursorPosition::HasChildren() const {
+ if (paint_fragment_)
+ return paint_fragment_->FirstChild();
+ if (item_)
+ return item_->HasChildren();
NOTREACHED();
return false;
}
@@ -171,9 +170,9 @@ void NGInlineCursor::ExpandRootToContainingBlock() {
NOTREACHED();
}
-bool NGInlineCursor::HasSoftWrapToNextLine() const {
- DCHECK(Current().IsLineBox());
- const NGInlineBreakToken* break_token = Current().InlineBreakToken();
+bool NGInlineCursorPosition::HasSoftWrapToNextLine() const {
+ DCHECK(IsLineBox());
+ const NGInlineBreakToken* break_token = InlineBreakToken();
DCHECK(break_token);
return !break_token->IsFinished() && !break_token->IsForcedBreak();
}
@@ -218,12 +217,11 @@ bool NGInlineCursorPosition::IsGeneratedText() const {
return false;
}
-bool NGInlineCursorPosition::IsGeneratedTextType() const {
+bool NGInlineCursorPosition::IsLayoutGeneratedText() const {
if (paint_fragment_) {
if (auto* text_fragment = DynamicTo<NGPhysicalTextFragment>(
paint_fragment_->PhysicalFragment())) {
- return text_fragment->TextType() ==
- NGPhysicalTextFragment::kGeneratedText;
+ return text_fragment->TextType() == NGTextType::kLayoutGenerated;
}
return false;
}
@@ -242,27 +240,40 @@ bool NGInlineCursorPosition::IsHiddenForPaint() const {
return false;
}
-bool NGInlineCursor::IsInlineLeaf() const {
- if (Current().IsHiddenForPaint())
+bool NGInlineCursorPosition::IsInlineLeaf() const {
+ if (IsHiddenForPaint())
return false;
- if (Current().IsText())
- return !Current().IsGeneratedTextType();
- if (!Current().IsAtomicInline())
+ if (IsText())
+ return !IsLayoutGeneratedText();
+ if (!IsAtomicInline())
return false;
- return !Current().IsListMarker();
+ return !IsListMarker();
}
-bool NGInlineCursor::IsPartOfCulledInlineBox(
+bool NGInlineCursorPosition::IsPartOfCulledInlineBox(
const LayoutInline& layout_inline) const {
- const LayoutObject* const layout_object = Current().GetLayoutObject();
+ DCHECK(!layout_inline.ShouldCreateBoxFragment());
+ DCHECK(*this);
+ const LayoutObject* const layout_object = GetLayoutObject();
// We use |IsInline()| to exclude floating and out-of-flow objects.
if (!layout_object || !layout_object->IsInline() ||
layout_object->IsAtomicInlineLevel())
return false;
DCHECK(!layout_object->IsFloatingOrOutOfFlowPositioned());
- DCHECK(!Current().BoxFragment() ||
- !Current().BoxFragment()->IsFormattingContextRoot());
- return layout_object->IsDescendantOf(&layout_inline);
+ DCHECK(!BoxFragment() || !BoxFragment()->IsFormattingContextRoot());
+ for (const LayoutObject* parent = layout_object->Parent(); parent;
+ parent = parent->Parent()) {
+ // Children of culled inline should be included.
+ if (parent == &layout_inline)
+ return true;
+ // Grand children should be included only if children are also culled.
+ if (const auto* parent_layout_inline = ToLayoutInlineOrNull(parent)) {
+ if (!parent_layout_inline->ShouldCreateBoxFragment())
+ continue;
+ }
+ return false;
+ }
+ return false;
}
bool NGInlineCursor::IsLastLineInInlineBlock() const {
@@ -271,7 +282,7 @@ bool NGInlineCursor::IsLastLineInInlineBlock() const {
return false;
NGInlineCursor next_sibling(*this);
for (;;) {
- next_sibling.MoveToNextSibling();
+ next_sibling.MoveToNextSkippingChildren();
if (!next_sibling)
return true;
if (next_sibling.Current().IsLineBox())
@@ -338,13 +349,12 @@ bool NGInlineCursor::IsBeforeSoftLineBreak() const {
return line.Current().BaseDirection() == Current().ResolvedDirection();
}
-bool NGInlineCursor::CanHaveChildren() const {
- if (current_.paint_fragment_)
- return current_.paint_fragment_->PhysicalFragment().IsContainer();
- if (current_.item_) {
- return current_.item_->Type() == NGFragmentItem::kLine ||
- (current_.item_->Type() == NGFragmentItem::kBox &&
- !current_.item_->IsAtomicInline());
+bool NGInlineCursorPosition::CanHaveChildren() const {
+ if (paint_fragment_)
+ return paint_fragment_->PhysicalFragment().IsContainer();
+ if (item_) {
+ return item_->Type() == NGFragmentItem::kLine ||
+ (item_->Type() == NGFragmentItem::kBox && !item_->IsAtomicInline());
}
NOTREACHED();
return false;
@@ -385,7 +395,7 @@ TextDirection NGInlineCursorPosition::BaseDirection() const {
UBiDiLevel NGInlineCursorPosition::BidiLevel() const {
if (IsText()) {
- if (IsGeneratedTextType()) {
+ if (IsLayoutGeneratedText()) {
// TODO(yosin): Until we have clients, we don't support bidi-level for
// ellipsis and soft hyphens.
NOTREACHED() << this;
@@ -623,25 +633,23 @@ LayoutUnit NGInlineCursor::InlinePositionForOffset(unsigned offset) const {
return LayoutUnit();
}
-PhysicalOffset NGInlineCursor::LineStartPoint() const {
- DCHECK(Current().IsLineBox()) << this;
+PhysicalOffset NGInlineCursorPosition::LineStartPoint() const {
+ DCHECK(IsLineBox()) << this;
const LogicalOffset logical_start; // (0, 0)
const PhysicalSize pixel_size(LayoutUnit(1), LayoutUnit(1));
- return logical_start.ConvertToPhysical(Current().Style().GetWritingMode(),
- Current().BaseDirection(),
- Current().Size(), pixel_size);
+ return logical_start.ConvertToPhysical(Style().GetWritingMode(),
+ BaseDirection(), Size(), pixel_size);
}
-PhysicalOffset NGInlineCursor::LineEndPoint() const {
- DCHECK(Current().IsLineBox()) << this;
- const WritingMode writing_mode = Current().Style().GetWritingMode();
- const LayoutUnit inline_size = IsHorizontalWritingMode(writing_mode)
- ? Current().Size().width
- : Current().Size().height;
+PhysicalOffset NGInlineCursorPosition::LineEndPoint() const {
+ DCHECK(IsLineBox()) << this;
+ const WritingMode writing_mode = Style().GetWritingMode();
+ const LayoutUnit inline_size =
+ IsHorizontalWritingMode(writing_mode) ? Size().width : Size().height;
const LogicalOffset logical_end(inline_size, LayoutUnit());
const PhysicalSize pixel_size(LayoutUnit(1), LayoutUnit(1));
- return logical_end.ConvertToPhysical(writing_mode, Current().BaseDirection(),
- Current().Size(), pixel_size);
+ return logical_end.ConvertToPhysical(writing_mode, BaseDirection(), Size(),
+ pixel_size);
}
PositionWithAffinity NGInlineCursor::PositionForPointInInlineFormattingContext(
@@ -819,6 +827,25 @@ PositionWithAffinity NGInlineCursor::PositionForPointInInlineBox(
}
}
+ if (container->Type() == NGFragmentItem::kLine) {
+ // There are no inline items to hit in this line box, e.g. <span> with
+ // size and border. We try in lines before |this| line in the block.
+ // See editing/selection/last-empty-inline.html
+ NGInlineCursor cursor;
+ cursor.MoveTo(*this);
+ const PhysicalOffset point_in_line =
+ point - Current().OffsetInContainerBlock();
+ for (;;) {
+ cursor.MoveToPreviousLine();
+ if (!cursor)
+ break;
+ const PhysicalOffset adjusted_point =
+ point_in_line + cursor.Current().OffsetInContainerBlock();
+ if (auto position = cursor.PositionForPointInInlineBox(adjusted_point))
+ return position;
+ }
+ }
+
return PositionWithAffinity();
}
@@ -856,105 +883,47 @@ PositionWithAffinity NGInlineCursor::PositionForPointInChild(
return PositionWithAffinity();
}
-void NGInlineCursor::MakeNull() {
- if (root_paint_fragment_) {
- current_.paint_fragment_ = nullptr;
- return;
- }
- if (fragment_items_)
- return MoveToItem(items_.end());
-}
-
void NGInlineCursor::MoveTo(const NGInlineCursorPosition& position) {
CheckValid(position);
current_ = position;
}
-inline unsigned NGInlineCursor::SpanIndexFromItemIndex(unsigned index) const {
+inline wtf_size_t NGInlineCursor::SpanBeginItemIndex() const {
+ DCHECK(IsItemCursor());
+ DCHECK(!items_.empty());
+ DCHECK(fragment_items_->IsSubSpan(items_));
+ const wtf_size_t delta = items_.data() - fragment_items_->Items().data();
+ DCHECK_LT(delta, fragment_items_->Items().size());
+ return delta;
+}
+
+inline wtf_size_t NGInlineCursor::SpanIndexFromItemIndex(unsigned index) const {
DCHECK(IsItemCursor());
- DCHECK_GE(items_.data(), fragment_items_->Items().data());
- DCHECK_LT(items_.data(), fragment_items_->Items().end());
+ DCHECK(!items_.empty());
+ DCHECK(fragment_items_->IsSubSpan(items_));
if (items_.data() == fragment_items_->Items().data())
return index;
- unsigned span_index = fragment_items_->Items().data() - items_.data() + index;
+ const wtf_size_t span_index =
+ fragment_items_->Items().data() - items_.data() + index;
DCHECK_LT(span_index, items_.size());
return span_index;
}
NGInlineCursor::ItemsSpan::iterator NGInlineCursor::SlowFirstItemIteratorFor(
- const LayoutObject& layout_object) const {
- DCHECK(IsItemCursor());
- for (ItemsSpan::iterator iter = items_.begin(); iter != items_.end();
- ++iter) {
+ const LayoutObject& layout_object,
+ const ItemsSpan& items) {
+ for (ItemsSpan::iterator iter = items.begin(); iter != items.end(); ++iter) {
if ((*iter)->GetLayoutObject() == &layout_object)
return iter;
}
- return items_.end();
+ return items.end();
}
-void NGInlineCursor::InternalMoveTo(const LayoutObject& layout_object) {
- DCHECK(layout_object.IsInLayoutNGInlineFormattingContext());
- // If this cursor is rootless, find the root of the inline formatting context.
- bool had_root = true;
- if (!HasRoot()) {
- had_root = false;
- const LayoutBlockFlow& root = *layout_object.RootInlineFormattingContext();
- DCHECK(&root);
- SetRoot(root);
- if (!HasRoot()) {
- const auto fragments =
- NGPaintFragment::InlineFragmentsFor(&layout_object);
- if (!fragments.IsInLayoutNGInlineFormattingContext() ||
- fragments.IsEmpty())
- return MakeNull();
- // external/wpt/css/css-scroll-anchoring/text-anchor-in-vertical-rl.html
- // reaches here.
- root_paint_fragment_ = fragments.front().Root();
- }
- }
- if (fragment_items_) {
- const wtf_size_t item_index = layout_object.FirstInlineFragmentItemIndex();
- if (!item_index) {
- // TODO(yosin): Once we update all |LayoutObject::FirstInlineFragment()|
- // clients, we should replace to |return MakeNull()|
- MoveToItem(SlowFirstItemIteratorFor(layout_object));
- return;
- }
- const unsigned span_index = SpanIndexFromItemIndex(item_index);
- DCHECK_EQ(span_index,
- static_cast<unsigned>(SlowFirstItemIteratorFor(layout_object) -
- items_.begin()));
- return MoveToItem(items_.begin() + span_index);
- }
- if (root_paint_fragment_) {
- const auto fragments = NGPaintFragment::InlineFragmentsFor(&layout_object);
- if (!fragments.IsInLayoutNGInlineFormattingContext() || fragments.IsEmpty())
- return MakeNull();
- return MoveTo(fragments.front());
- }
-}
-
-void NGInlineCursor::MoveTo(const LayoutObject& layout_object) {
- DCHECK(layout_object.IsInLayoutNGInlineFormattingContext()) << layout_object;
- InternalMoveTo(layout_object);
- if (*this || !HasRoot() ||
- RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()) {
- layout_inline_ = nullptr;
- return;
- }
-
- // This |layout_object| did not produce any fragments.
- if (RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled())
- return;
-
- // Try to find ancestors if this is a culled inline.
- layout_inline_ = ToLayoutInlineOrNull(&layout_object);
- if (!layout_inline_)
- return;
-
- MoveToFirst();
- while (IsNotNull() && !IsPartOfCulledInlineBox(*layout_inline_))
- MoveToNext();
+wtf_size_t NGInlineCursor::SlowFirstItemIndexFor(
+ const LayoutObject& layout_object,
+ const ItemsSpan& items) {
+ ItemsSpan::iterator iter = SlowFirstItemIteratorFor(layout_object, items);
+ return iter - items.begin();
}
void NGInlineCursor::MoveTo(const NGFragmentItem& fragment_item) {
@@ -1019,6 +988,14 @@ void NGInlineCursor::MoveToContainingLine() {
NOTREACHED();
}
+bool NGInlineCursor::IsAtFirst() const {
+ if (const NGPaintFragment* paint_fragment = Current().PaintFragment())
+ return paint_fragment == root_paint_fragment_->FirstChild();
+ if (const NGFragmentItem* item = Current().Item())
+ return item == items_.front().get();
+ return false;
+}
+
void NGInlineCursor::MoveToFirst() {
if (root_paint_fragment_) {
current_.paint_fragment_ = root_paint_fragment_->FirstChild();
@@ -1032,7 +1009,7 @@ void NGInlineCursor::MoveToFirst() {
}
void NGInlineCursor::MoveToFirstChild() {
- DCHECK(CanHaveChildren());
+ DCHECK(Current().CanHaveChildren());
if (!TryToMoveToFirstChild())
MakeNull();
}
@@ -1072,20 +1049,20 @@ void NGInlineCursor::MoveToFirstLogicalLeaf() {
}
void NGInlineCursor::MoveToLastChild() {
- DCHECK(CanHaveChildren());
+ DCHECK(Current().CanHaveChildren());
if (!TryToMoveToLastChild())
MakeNull();
}
-void NGInlineCursor::MoveToLastForSameLayoutObject() {
- if (!Current())
- return;
- NGInlineCursorPosition last;
- do {
- last = Current();
- MoveToNextForSameLayoutObject();
- } while (Current());
- MoveTo(last);
+void NGInlineCursor::MoveToLastLine() {
+ DCHECK(IsItemCursor());
+ auto iter = std::find_if(
+ items_.rbegin(), items_.rend(),
+ [](const auto& item) { return item->Type() == NGFragmentItem::kLine; });
+ if (iter != items_.rend())
+ MoveToItem(std::next(iter).base());
+ else
+ MakeNull();
}
void NGInlineCursor::MoveToLastLogicalLeaf() {
@@ -1109,37 +1086,10 @@ void NGInlineCursor::MoveToNext() {
MoveToNextItem();
}
-void NGInlineCursor::MoveToNextForSameLayoutObject() {
- if (layout_inline_) {
- DCHECK(!RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled());
- // Move to next fragment in culled inline box undef |layout_inline_|.
- do {
- MoveToNext();
- } while (IsNotNull() && !IsPartOfCulledInlineBox(*layout_inline_));
- return;
- }
- if (current_.paint_fragment_) {
- if (auto* paint_fragment =
- current_.paint_fragment_->NextForSameLayoutObject()) {
- // |paint_fragment| can be in another fragment tree rooted by
- // |root_paint_fragment_|, e.g. "multicol-span-all-restyle-002.html"
- root_paint_fragment_ = paint_fragment->Root();
- return MoveTo(*paint_fragment);
- }
- return MakeNull();
- }
- if (current_.item_) {
- const wtf_size_t delta = current_.item_->DeltaToNextForSameLayoutObject();
- if (delta == 0u)
- return MakeNull();
- return MoveToItem(current_.item_iter_ + delta);
- }
-}
-
void NGInlineCursor::MoveToNextInlineLeaf() {
- if (IsNotNull() && IsInlineLeaf())
+ if (Current() && Current().IsInlineLeaf())
MoveToNext();
- while (IsNotNull() && !IsInlineLeaf())
+ while (Current() && !Current().IsInlineLeaf())
MoveToNext();
}
@@ -1158,7 +1108,7 @@ void NGInlineCursor::MoveToNextInlineLeafOnLine() {
NGInlineCursor cursor = CursorForDescendants();
cursor.MoveTo(last_item);
// Note: AX requires this for AccessibilityLayoutTest.NextOnLine.
- if (!cursor.IsInlineLeaf())
+ if (!cursor.Current().IsInlineLeaf())
cursor.MoveToNextInlineLeaf();
cursor.MoveToNextInlineLeaf();
MoveTo(cursor);
@@ -1180,12 +1130,6 @@ void NGInlineCursor::MoveToNextLine() {
NOTREACHED();
}
-void NGInlineCursor::MoveToNextSibling() {
- if (current_.paint_fragment_)
- return MoveToNextSiblingPaintFragment();
- return MoveToNextSiblingItem();
-}
-
void NGInlineCursor::MoveToNextSkippingChildren() {
if (root_paint_fragment_)
return MoveToNextPaintFragmentSkippingChildren();
@@ -1199,9 +1143,9 @@ void NGInlineCursor::MoveToPrevious() {
}
void NGInlineCursor::MoveToPreviousInlineLeaf() {
- if (IsNotNull() && IsInlineLeaf())
+ if (Current() && Current().IsInlineLeaf())
MoveToPrevious();
- while (IsNotNull() && !IsInlineLeaf())
+ while (Current() && !Current().IsInlineLeaf())
MoveToPrevious();
}
@@ -1219,7 +1163,7 @@ void NGInlineCursor::MoveToPreviousInlineLeafOnLine() {
NGInlineCursor cursor = CursorForDescendants();
cursor.MoveTo(first_item);
// Note: AX requires this for AccessibilityLayoutTest.NextOnLine.
- if (!cursor.IsInlineLeaf())
+ if (!cursor.Current().IsInlineLeaf())
cursor.MoveToPreviousInlineLeaf();
cursor.MoveToPreviousInlineLeaf();
MoveTo(cursor);
@@ -1244,7 +1188,7 @@ void NGInlineCursor::MoveToPreviousLine() {
}
bool NGInlineCursor::TryToMoveToFirstChild() {
- if (!HasChildren())
+ if (!Current().HasChildren())
return false;
if (root_paint_fragment_) {
MoveTo(*current_.paint_fragment_->FirstChild());
@@ -1255,18 +1199,23 @@ bool NGInlineCursor::TryToMoveToFirstChild() {
}
bool NGInlineCursor::TryToMoveToLastChild() {
- if (!HasChildren())
+ if (!Current().HasChildren())
return false;
if (root_paint_fragment_) {
MoveTo(current_.paint_fragment_->Children().back());
return true;
}
const auto end = current_.item_iter_ + CurrentItem()->DescendantsCount();
- MoveToNextItem();
+ MoveToNextItem(); // Move to the first child.
DCHECK(!IsNull());
- for (auto it = current_.item_iter_ + 1; it != end; ++it) {
- if (CurrentItem()->IsSiblingOf(**it))
- MoveToItem(it);
+ while (true) {
+ ItemsSpan::iterator previous = Current().item_iter_;
+ DCHECK(previous < end);
+ MoveToNextSkippingChildren();
+ if (!Current() || Current().item_iter_ == end) {
+ MoveToItem(previous);
+ break;
+ }
}
return true;
}
@@ -1276,8 +1225,11 @@ void NGInlineCursor::MoveToNextItem() {
if (UNLIKELY(!current_.item_))
return;
DCHECK(current_.item_iter_ != items_.end());
- ++current_.item_iter_;
- MoveToItem(current_.item_iter_);
+ if (++current_.item_iter_ != items_.end()) {
+ current_.item_ = current_.item_iter_->get();
+ return;
+ }
+ MakeNull();
}
void NGInlineCursor::MoveToNextItemSkippingChildren() {
@@ -1291,17 +1243,6 @@ void NGInlineCursor::MoveToNextItemSkippingChildren() {
return MoveToNextItem();
}
-void NGInlineCursor::MoveToNextSiblingItem() {
- DCHECK(IsItemCursor());
- if (UNLIKELY(!current_.item_))
- return;
- const NGFragmentItem& item = *CurrentItem();
- MoveToNextItemSkippingChildren();
- if (IsNull() || item.IsSiblingOf(*CurrentItem()))
- return;
- MakeNull();
-}
-
void NGInlineCursor::MoveToPreviousItem() {
DCHECK(IsItemCursor());
if (UNLIKELY(!current_.item_))
@@ -1375,13 +1316,136 @@ void NGInlineCursor::MoveToPreviousSiblingPaintFragment() {
NOTREACHED();
}
+void NGInlineCursor::MoveTo(const LayoutObject& layout_object) {
+ DCHECK(layout_object.IsInLayoutNGInlineFormattingContext());
+ DCHECK(!layout_object.IsFloatingOrOutOfFlowPositioned());
+ // If this cursor is rootless, find the root of the inline formatting context.
+ bool had_root = true;
+ if (!HasRoot()) {
+ had_root = false;
+ const LayoutBlockFlow& root = *layout_object.RootInlineFormattingContext();
+ DCHECK(&root);
+ SetRoot(root);
+ if (!HasRoot()) {
+ if (RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()) {
+ MakeNull();
+ return;
+ }
+ const auto fragments =
+ NGPaintFragment::InlineFragmentsFor(&layout_object);
+ if (!fragments.IsInLayoutNGInlineFormattingContext() ||
+ fragments.IsEmpty())
+ return MakeNull();
+ // external/wpt/css/css-scroll-anchoring/text-anchor-in-vertical-rl.html
+ // reaches here.
+ root_paint_fragment_ = fragments.front().Root();
+ }
+ }
+ if (fragment_items_) {
+ wtf_size_t item_index = layout_object.FirstInlineFragmentItemIndex();
+ if (!item_index) {
+ DCHECK_EQ(SlowFirstItemIndexFor(layout_object, fragment_items_->Items()),
+ fragment_items_->Size());
+ MakeNull();
+ return;
+ }
+ // |FirstInlineFragmentItemIndex| is 1-based. Convert to 0-based index.
+ --item_index;
+ DCHECK_EQ(SlowFirstItemIndexFor(layout_object, fragment_items_->Items()),
+ item_index);
+
+ // Skip items before |items_|, in case |this| is part of IFC.
+ const wtf_size_t span_begin_item_index = SpanBeginItemIndex();
+ while (item_index < span_begin_item_index) {
+ const NGFragmentItem& item = *fragment_items_->Items()[item_index];
+ const wtf_size_t next_delta = item.DeltaToNextForSameLayoutObject();
+ if (!next_delta) {
+ MakeNull();
+ return;
+ }
+ item_index += next_delta;
+ }
+ if (item_index >= span_begin_item_index + items_.size()) {
+ MakeNull();
+ return;
+ }
+
+ const wtf_size_t span_index = item_index - span_begin_item_index;
+ DCHECK_LT(span_index, items_.size());
+ return MoveToItem(items_.begin() + span_index);
+ }
+ if (root_paint_fragment_) {
+ const auto fragments = NGPaintFragment::InlineFragmentsFor(&layout_object);
+ if (!fragments.IsInLayoutNGInlineFormattingContext() || fragments.IsEmpty())
+ return MakeNull();
+ return MoveTo(fragments.front());
+ }
+}
+
+void NGInlineCursor::MoveToIncludingCulledInline(
+ const LayoutObject& layout_object) {
+ DCHECK(layout_object.IsInLayoutNGInlineFormattingContext()) << layout_object;
+ MoveTo(layout_object);
+ if (*this || !HasRoot()) {
+ layout_inline_ = nullptr;
+ return;
+ }
+
+ // Try to find ancestors if this is a culled inline.
+ layout_inline_ = ToLayoutInlineOrNull(&layout_object);
+ if (!layout_inline_)
+ return;
+
+ MoveToFirst();
+ while (Current() && !Current().IsPartOfCulledInlineBox(*layout_inline_))
+ MoveToNext();
+}
+
+void NGInlineCursor::MoveToNextForSameLayoutObject() {
+ if (layout_inline_) {
+ // Move to next fragment in culled inline box undef |layout_inline_|.
+ do {
+ MoveToNext();
+ } while (Current() && !Current().IsPartOfCulledInlineBox(*layout_inline_));
+ return;
+ }
+ if (current_.paint_fragment_) {
+ if (auto* paint_fragment =
+ current_.paint_fragment_->NextForSameLayoutObject()) {
+ // |paint_fragment| can be in another fragment tree rooted by
+ // |root_paint_fragment_|, e.g. "multicol-span-all-restyle-002.html"
+ root_paint_fragment_ = paint_fragment->Root();
+ return MoveTo(*paint_fragment);
+ }
+ return MakeNull();
+ }
+ if (current_.item_) {
+ const wtf_size_t delta = current_.item_->DeltaToNextForSameLayoutObject();
+ if (delta == 0u)
+ return MakeNull();
+ return MoveToItem(current_.item_iter_ + delta);
+ }
+}
+
+void NGInlineCursor::MoveToLastForSameLayoutObject() {
+ if (!Current())
+ return;
+ NGInlineCursorPosition last;
+ do {
+ last = Current();
+ MoveToNextForSameLayoutObject();
+ } while (Current());
+ MoveTo(last);
+}
+
NGInlineBackwardCursor::NGInlineBackwardCursor(const NGInlineCursor& cursor)
: cursor_(cursor) {
if (cursor.root_paint_fragment_) {
DCHECK(!cursor.CurrentPaintFragment() ||
cursor.CurrentPaintFragment()->Parent()->FirstChild() ==
cursor.CurrentPaintFragment());
- for (NGInlineCursor sibling(cursor); sibling; sibling.MoveToNextSibling())
+ for (NGInlineCursor sibling(cursor); sibling;
+ sibling.MoveToNextSiblingPaintFragment())
sibling_paint_fragments_.push_back(sibling.CurrentPaintFragment());
current_index_ = sibling_paint_fragments_.size();
if (current_index_)
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.h b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.h
index c9626d87b5e..6e2b0d842c2 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.h
@@ -42,10 +42,8 @@ struct PhysicalSize;
// 2. Allows to save |Current()|, and can move back later. Moving to |Position|
// is faster than moving to |NGFragmentItem|.
class CORE_EXPORT NGInlineCursorPosition {
- STACK_ALLOCATED();
-
public:
- using ItemsSpan = base::span<const std::unique_ptr<NGFragmentItem>>;
+ using ItemsSpan = base::span<const scoped_refptr<const NGFragmentItem>>;
const NGPaintFragment* PaintFragment() const { return paint_fragment_; }
const NGFragmentItem* Item() const { return item_; }
@@ -65,13 +63,13 @@ class CORE_EXPORT NGInlineCursorPosition {
bool IsText() const;
// True if the current position is a generatd text. It is error to call at
- // end.
+ // end. This includes both style-generated (e.g., `content` property, see
+ // |IsStyleGenerated()|) and layout-generated (hyphens and ellipsis, see
+ // |IsLayoutGeneratedText()|.)
bool IsGeneratedText() const;
- // True if fragment is |NGFragmentItem::kGeneratedText| or
- // |NGPhysicalTextFragment::kGeneratedText|.
- // TODO(yosin): We should rename |IsGeneratedTextType()| to another name.
- bool IsGeneratedTextType() const;
+ // True if fragment is layout-generated (hyphens and ellipsis.)
+ bool IsLayoutGeneratedText() const;
// True if the current position is a line break. It is error to call at end.
bool IsLineBreak() const;
@@ -112,6 +110,12 @@ class CORE_EXPORT NGInlineCursorPosition {
const Node* GetNode() const;
const DisplayItemClient* GetDisplayItemClient() const;
+ // True if fragment at the current position can have children.
+ bool CanHaveChildren() const;
+
+ // True if fragment at the current position has children.
+ bool HasChildren() const;
+
// Returns break token for line box. It is error to call other than line box.
const NGInlineBreakToken* InlineBreakToken() const;
@@ -150,7 +154,30 @@ class CORE_EXPORT NGInlineCursorPosition {
// line.
TextDirection BaseDirection() const;
+ // True if the current position is text or atomic inline box.
+ // Note: Because of this function is used for caret rect, hit testing, etc,
+ // this function returns false for hidden for paint, text overflow ellipsis,
+ // and line break hyphen.
+ bool IsInlineLeaf() const;
+
+ // True if current position has soft wrap to next line. It is error to call
+ // other than line.
+ bool HasSoftWrapToNextLine() const;
+
+ // Returns a point at the visual start/end of the line.
+ // Encapsulates the handling of text direction and writing mode.
+ PhysicalOffset LineStartPoint() const;
+ PhysicalOffset LineEndPoint() const;
+
private:
+ void Clear() {
+ paint_fragment_ = nullptr;
+ item_ = nullptr;
+ }
+
+ // True if current position is part of culled inline box |layout_inline|.
+ bool IsPartOfCulledInlineBox(const LayoutInline& layout_inline) const;
+
const NGPaintFragment* paint_fragment_ = nullptr;
const NGFragmentItem* item_ = nullptr;
ItemsSpan::iterator item_iter_;
@@ -170,15 +197,15 @@ class CORE_EXPORT NGInlineCursor {
STACK_ALLOCATED();
public:
- using ItemsSpan = base::span<const std::unique_ptr<NGFragmentItem>>;
+ using ItemsSpan = base::span<const scoped_refptr<const NGFragmentItem>>;
explicit NGInlineCursor(const LayoutBlockFlow& block_flow);
explicit NGInlineCursor(const NGFragmentItems& items);
explicit NGInlineCursor(const NGFragmentItems& fragment_items,
ItemsSpan items);
explicit NGInlineCursor(const NGPaintFragment& root_paint_fragment);
+ explicit NGInlineCursor(const NGInlineBackwardCursor& backward_cursor);
NGInlineCursor(const NGInlineCursor& other) = default;
- NGInlineCursor(const NGInlineBackwardCursor& backward_cursor);
// Creates an |NGInlineCursor| without the root. Even when callers don't know
// the root of the inline formatting context, this cursor can |MoveTo()|
@@ -216,11 +243,8 @@ class CORE_EXPORT NGInlineCursor {
bool IsNotNull() const { return Current(); }
operator bool() const { return Current(); }
- // True if fragment at the current position can have children.
- bool CanHaveChildren() const;
-
- // True if fragment at the current position has children.
- bool HasChildren() const;
+ // True if |Current()| is at the first fragment. See |MoveToFirst()|.
+ bool IsAtFirst() const;
// Returns a new |NGInlineCursor| whose root is the current item. The returned
// cursor can traverse descendants of the current item. If the current item
@@ -233,20 +257,10 @@ class CORE_EXPORT NGInlineCursor {
// context.
void ExpandRootToContainingBlock();
- // True if current position has soft wrap to next line. It is error to call
- // other than line.
- bool HasSoftWrapToNextLine() const;
-
// True if the current position is before soft line break. It is error to call
// at end.
bool IsBeforeSoftLineBreak() const;
- // True if the current position is text or atomic inline box.
- // Note: Because of this function is used for caret rect, hit testing, etc,
- // this function returns false for hidden for paint, text overflow ellipsis,
- // and line break hyphen.
- bool IsInlineLeaf() const;
-
// |Current*| functions return an object for the current position.
const NGFragmentItem* CurrentItem() const { return Current().Item(); }
const NGPaintFragment* CurrentPaintFragment() const {
@@ -270,11 +284,6 @@ class CORE_EXPORT NGInlineCursor {
// than text.
LayoutUnit InlinePositionForOffset(unsigned offset) const;
- // Returns a point at the visual start/end of the line.
- // Encapsulates the handling of text direction and writing mode.
- PhysicalOffset LineStartPoint() const;
- PhysicalOffset LineEndPoint() const;
-
// Converts the given point, relative to the fragment itself, into a position
// in DOM tree within the range of |this|. This variation ignores the inline
// offset, and snaps to the nearest line in the block direction.
@@ -304,11 +313,6 @@ class CORE_EXPORT NGInlineCursor {
void MoveTo(const NGPaintFragment& paint_fragment);
void MoveTo(const NGPaintFragment* paint_fragment);
- // Move to first |NGFragmentItem| or |NGPaintFragment| associated to
- // |layout_object|. When |layout_object| has no associated fragments, this
- // cursor points nothing.
- void MoveTo(const LayoutObject& layout_object);
-
// Move to containing line box. It is error if the current position is line.
void MoveToContainingLine();
@@ -329,8 +333,9 @@ class CORE_EXPORT NGInlineCursor {
// See also |TryToMoveToFirstChild()|.
void MoveToLastChild();
- // Move the current position to the last fragment on same layout object.
- void MoveToLastForSameLayoutObject();
+ // Move to the last line item. If there are no line items, the cursor becomes
+ // null.
+ void MoveToLastLine();
// Move to last logical leaf of current line box. If current line box has
// no children, curosr becomes null.
@@ -340,17 +345,10 @@ class CORE_EXPORT NGInlineCursor {
// the current position is at last fragment, this cursor points nothing.
void MoveToNext();
- // Move the current position to next fragment on same layout object.
- void MoveToNextForSameLayoutObject();
-
// Move the current position to next line. It is error to call other than line
// box.
void MoveToNextLine();
- // Move the current position to next sibling fragment.
- // |MoveToNextSibling()| is deprecated. New code should not be used.
- void MoveToNextSibling();
-
// Same as |MoveToNext| except that this skips children even if they exist.
void MoveToNextSkippingChildren();
@@ -381,8 +379,17 @@ class CORE_EXPORT NGInlineCursor {
// Returns true if the current position moves to last child.
bool TryToMoveToLastChild();
- // TODO(kojii): Add more variations as needed, NextSibling,
- // NextSkippingChildren, Previous, etc.
+ // Move to first |NGFragmentItem| or |NGPaintFragment| associated to
+ // |layout_object|. When |layout_object| has no associated fragments, this
+ // cursor points nothing.
+ void MoveTo(const LayoutObject& layout_object);
+ void MoveToIncludingCulledInline(const LayoutObject& layout_object);
+
+ // Move the current position to next fragment on same layout object.
+ void MoveToNextForSameLayoutObject();
+
+ // Move the current position to the last fragment on same layout object.
+ void MoveToLastForSameLayoutObject();
#if DCHECK_IS_ON()
void CheckValid(const NGInlineCursorPosition& position) const;
@@ -391,23 +398,17 @@ class CORE_EXPORT NGInlineCursor {
#endif
private:
- // True if current position is part of culled inline box |layout_inline|.
- bool IsPartOfCulledInlineBox(const LayoutInline& layout_inline) const;
-
// True if the current position is a last line in inline block. It is error
// to call at end or the current position is not line.
bool IsLastLineInInlineBlock() const;
// Make the current position points nothing, e.g. cursor moves over start/end
// fragment, cursor moves to first/last child to parent has no children.
- void MakeNull();
+ void MakeNull() { current_.Clear(); }
// Move the cursor position to the first fragment in tree.
void MoveToFirst();
- // Same as |MoveTo()| but not support culled inline.
- void InternalMoveTo(const LayoutObject& layout_object);
-
void SetRoot(const NGFragmentItems& items);
void SetRoot(const NGFragmentItems& fragment_items, ItemsSpan items);
void SetRoot(const NGPaintFragment& root_paint_fragment);
@@ -416,7 +417,6 @@ class CORE_EXPORT NGInlineCursor {
void MoveToItem(const ItemsSpan::iterator& iter);
void MoveToNextItem();
void MoveToNextItemSkippingChildren();
- void MoveToNextSiblingItem();
void MoveToPreviousItem();
void MoveToParentPaintFragment();
@@ -426,9 +426,13 @@ class CORE_EXPORT NGInlineCursor {
void MoveToPreviousPaintFragment();
void MoveToPreviousSiblingPaintFragment();
- ItemsSpan::iterator SlowFirstItemIteratorFor(
- const LayoutObject& layout_object) const;
- unsigned SpanIndexFromItemIndex(unsigned index) const;
+ static ItemsSpan::iterator SlowFirstItemIteratorFor(
+ const LayoutObject& layout_object,
+ const ItemsSpan& items);
+ static wtf_size_t SlowFirstItemIndexFor(const LayoutObject& layout_object,
+ const ItemsSpan& items);
+ wtf_size_t SpanBeginItemIndex() const;
+ wtf_size_t SpanIndexFromItemIndex(unsigned index) const;
PositionWithAffinity PositionForPointInChild(
const PhysicalOffset& point,
@@ -455,7 +459,7 @@ class CORE_EXPORT NGInlineBackwardCursor {
public:
// |cursor| should be the first child of root or descendants, e.g. the first
// item in |NGInlineCursor::items_|.
- NGInlineBackwardCursor(const NGInlineCursor& cursor);
+ explicit NGInlineBackwardCursor(const NGInlineCursor& cursor);
const NGInlineCursorPosition& Current() const { return current_; }
operator bool() const { return Current(); }
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor_test.cc b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor_test.cc
index 8398da81ecb..580588369e4 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor_test.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor_test.cc
@@ -38,7 +38,8 @@ class NGInlineCursorTest : public NGLayoutTest,
Vector<String> SiblingsToDebugStringList(const NGInlineCursor& start) {
Vector<String> list;
- for (NGInlineCursor cursor(start); cursor; cursor.MoveToNextSibling())
+ for (NGInlineCursor cursor(start); cursor;
+ cursor.MoveToNextSkippingChildren())
list.push_back(ToDebugString(cursor));
return list;
}
@@ -48,7 +49,8 @@ class NGInlineCursorTest : public NGLayoutTest,
void TestPrevoiusSibling(const NGInlineCursor& start) {
if (start.IsPaintFragmentCursor()) {
Vector<const NGPaintFragment*> forwards;
- for (NGInlineCursor cursor(start); cursor; cursor.MoveToNextSibling())
+ for (NGInlineCursor cursor(start); cursor;
+ cursor.MoveToNextSkippingChildren())
forwards.push_back(cursor.CurrentPaintFragment());
Vector<const NGPaintFragment*> backwards;
for (NGInlineBackwardCursor cursor(start); cursor;
@@ -60,7 +62,8 @@ class NGInlineCursorTest : public NGLayoutTest,
}
DCHECK(start.IsItemCursor());
Vector<const NGFragmentItem*> forwards;
- for (NGInlineCursor cursor(start); cursor; cursor.MoveToNextSibling())
+ for (NGInlineCursor cursor(start); cursor;
+ cursor.MoveToNextSkippingChildren())
forwards.push_back(cursor.CurrentItem());
Vector<const NGFragmentItem*> backwards;
for (NGInlineBackwardCursor cursor(start); cursor;
@@ -74,7 +77,7 @@ class NGInlineCursorTest : public NGLayoutTest,
if (cursor.Current().IsLineBox())
return "#linebox";
- if (cursor.Current().IsGeneratedTextType()) {
+ if (cursor.Current().IsLayoutGeneratedText()) {
StringBuilder result;
result.Append("#'");
result.Append(cursor.CurrentText());
@@ -183,7 +186,7 @@ TEST_P(NGInlineCursorTest, ContainingLine) {
ASSERT_TRUE(line1.Current().IsLineBox());
NGInlineCursor line2(line1);
- line2.MoveToNextSibling();
+ line2.MoveToNextSkippingChildren();
ASSERT_TRUE(line2.Current().IsLineBox());
cursor.MoveTo(*block_flow.FirstChild());
@@ -211,16 +214,13 @@ TEST_P(NGInlineCursorTest, CulledInlineWithAtomicInline) {
"<b id=culled>abc<div style=display:inline>ABC<br>XYZ</div>xyz</b>"
"</div>");
NGInlineCursor cursor;
- cursor.MoveTo(*GetLayoutObjectByElementId("culled"));
+ cursor.MoveToIncludingCulledInline(*GetLayoutObjectByElementId("culled"));
Vector<String> list;
while (cursor) {
list.push_back(ToDebugString(cursor));
cursor.MoveToNextForSameLayoutObject();
}
- if (RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled())
- EXPECT_THAT(list, ElementsAre("#culled", "#culled"));
- else
- EXPECT_THAT(list, ElementsAre("abc", "ABC", "", "XYZ", "xyz"));
+ EXPECT_THAT(list, ElementsAre("abc", "ABC", "", "XYZ", "xyz"));
}
// We should not have float:right fragment, because it isn't in-flow in
@@ -232,16 +232,13 @@ TEST_P(NGInlineCursorTest, CulledInlineWithFloat) {
"<b id=culled>abc<div style=float:right></div>xyz</b>"
"</div>");
NGInlineCursor cursor;
- cursor.MoveTo(*GetLayoutObjectByElementId("culled"));
+ cursor.MoveToIncludingCulledInline(*GetLayoutObjectByElementId("culled"));
Vector<String> list;
while (cursor) {
list.push_back(ToDebugString(cursor));
cursor.MoveToNextForSameLayoutObject();
}
- if (RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled())
- EXPECT_THAT(list, ElementsAre("#culled"));
- else
- EXPECT_THAT(list, ElementsAre("abc", "xyz"));
+ EXPECT_THAT(list, ElementsAre("abc", "xyz"));
}
TEST_P(NGInlineCursorTest, CulledInlineWithRoot) {
@@ -249,16 +246,13 @@ TEST_P(NGInlineCursorTest, CulledInlineWithRoot) {
<div id="root"><a id="a"><b>abc</b><br><i>xyz</i></a></div>
)HTML");
const LayoutObject* layout_inline_a = GetLayoutObjectByElementId("a");
- cursor.MoveTo(*layout_inline_a);
+ cursor.MoveToIncludingCulledInline(*layout_inline_a);
Vector<String> list;
while (cursor) {
list.push_back(ToDebugString(cursor));
cursor.MoveToNextForSameLayoutObject();
}
- if (RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled())
- EXPECT_THAT(list, ElementsAre("#a", "#a"));
- else
- EXPECT_THAT(list, ElementsAre("abc", "", "xyz"));
+ EXPECT_THAT(list, ElementsAre("abc", "", "xyz"));
}
TEST_P(NGInlineCursorTest, CulledInlineWithoutRoot) {
@@ -267,16 +261,13 @@ TEST_P(NGInlineCursorTest, CulledInlineWithoutRoot) {
)HTML");
const LayoutObject* layout_inline_a = GetLayoutObjectByElementId("a");
NGInlineCursor cursor;
- cursor.MoveTo(*layout_inline_a);
+ cursor.MoveToIncludingCulledInline(*layout_inline_a);
Vector<String> list;
while (cursor) {
list.push_back(ToDebugString(cursor));
cursor.MoveToNextForSameLayoutObject();
}
- if (RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled())
- EXPECT_THAT(list, ElementsAre("#a", "#a"));
- else
- EXPECT_THAT(list, ElementsAre("abc", "", "xyz"));
+ EXPECT_THAT(list, ElementsAre("abc", "", "xyz"));
}
TEST_P(NGInlineCursorTest, FirstChild) {
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item.cc b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item.cc
index bb809f51b2b..eae7589942b 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item.cc
@@ -12,6 +12,15 @@
namespace blink {
namespace {
+struct SameSizeAsNGInlineItem {
+ void* pointers[2];
+ unsigned integers[3];
+ unsigned bit_fields : 32;
+};
+
+static_assert(sizeof(NGInlineItem) == sizeof(SameSizeAsNGInlineItem),
+ "NGInlineItem should stay small");
+
const char* kNGInlineItemTypeStrings[] = {
"Text", "Control", "AtomicInline", "OpenTag",
"CloseTag", "Floating", "OutOfFlowPositioned", "BidiControl"};
@@ -60,23 +69,20 @@ bool IsInlineBoxEndEmpty(const ComputedStyle& style,
NGInlineItem::NGInlineItem(NGInlineItemType type,
unsigned start,
unsigned end,
- LayoutObject* layout_object,
- bool is_first_for_node)
+ LayoutObject* layout_object)
: start_offset_(start),
end_offset_(end),
layout_object_(layout_object),
type_(type),
- segment_data_(0),
+ text_type_(static_cast<unsigned>(NGTextType::kNormal)),
+ style_variant_(static_cast<unsigned>(NGStyleVariant::kStandard)),
+ end_collapse_type_(kNotCollapsible),
bidi_level_(UBIDI_LTR),
- shape_options_(kPreContext | kPostContext),
+ segment_data_(0),
is_empty_item_(false),
is_block_level_(false),
- style_variant_(static_cast<unsigned>(NGStyleVariant::kStandard)),
- end_collapse_type_(kNotCollapsible),
is_end_collapsible_newline_(false),
- is_symbol_marker_(false),
- is_generated_for_line_break_(false),
- is_first_for_node_(is_first_for_node) {
+ is_generated_for_line_break_(false) {
DCHECK_GE(end, start);
ComputeBoxProperties();
}
@@ -90,17 +96,15 @@ NGInlineItem::NGInlineItem(const NGInlineItem& other,
shape_result_(shape_result),
layout_object_(other.layout_object_),
type_(other.type_),
- segment_data_(other.segment_data_),
+ text_type_(other.text_type_),
+ style_variant_(other.style_variant_),
+ end_collapse_type_(other.end_collapse_type_),
bidi_level_(other.bidi_level_),
- shape_options_(other.shape_options_),
+ segment_data_(other.segment_data_),
is_empty_item_(other.is_empty_item_),
is_block_level_(other.is_block_level_),
- style_variant_(other.style_variant_),
- end_collapse_type_(other.end_collapse_type_),
is_end_collapsible_newline_(other.is_end_collapsible_newline_),
- is_symbol_marker_(other.is_symbol_marker_),
- is_generated_for_line_break_(other.is_generated_for_line_break_),
- is_first_for_node_(other.is_first_for_node_) {
+ is_generated_for_line_break_(other.is_generated_for_line_break_) {
DCHECK_GE(end, start);
}
@@ -200,7 +204,6 @@ void NGInlineItem::Split(Vector<NGInlineItem>& items,
items.insert(index + 1, items[index]);
items[index].end_offset_ = offset;
items[index + 1].start_offset_ = offset;
- items[index + 1].is_first_for_node_ = false;
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item.h b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item.h
index 5a8575d3a51..531527710c8 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item.h
@@ -9,6 +9,7 @@
#include "third_party/blink/renderer/core/layout/layout_inline.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_item_segment.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_offset_mapping.h"
+#include "third_party/blink/renderer/core/layout/ng/inline/ng_text_type.h"
#include "third_party/blink/renderer/core/layout/ng/ng_style_variant.h"
#include "third_party/blink/renderer/core/style/computed_style.h"
#include "third_party/blink/renderer/platform/fonts/shaping/run_segmenter.h"
@@ -43,13 +44,6 @@ class CORE_EXPORT NGInlineItem {
kBidiControl
};
- // Whether pre- and post-context should be used for shaping.
- enum NGLayoutInlineShapeOptions {
- kNoContext = 0,
- kPreContext = 1,
- kPostContext = 2
- };
-
enum NGCollapseType {
// No collapsible spaces.
kNotCollapsible,
@@ -66,8 +60,7 @@ class CORE_EXPORT NGInlineItem {
NGInlineItem(NGInlineItemType type,
unsigned start,
unsigned end,
- LayoutObject* layout_object,
- bool is_first_for_node);
+ LayoutObject* layout_object);
~NGInlineItem();
// Copy constructor adjusting start/end and shape results.
@@ -79,11 +72,21 @@ class CORE_EXPORT NGInlineItem {
NGInlineItemType Type() const { return type_; }
const char* NGInlineItemTypeToString(int val) const;
- const ShapeResult* TextShapeResult() const { return shape_result_.get(); }
- NGLayoutInlineShapeOptions ShapeOptions() const {
- return static_cast<NGLayoutInlineShapeOptions>(shape_options_);
+ NGTextType TextType() const { return static_cast<NGTextType>(text_type_); }
+ void SetTextType(NGTextType text_type) {
+ text_type_ = static_cast<unsigned>(text_type);
+ }
+ bool IsSymbolMarker() const {
+ return TextType() == NGTextType::kSymbolMarker;
+ }
+ void SetIsSymbolMarker() {
+ DCHECK(TextType() == NGTextType::kNormal ||
+ TextType() == NGTextType::kSymbolMarker);
+ SetTextType(NGTextType::kSymbolMarker);
}
+ const ShapeResult* TextShapeResult() const { return shape_result_.get(); }
+
// If this item is "empty" for the purpose of empty block calculation.
bool IsEmptyItem() const { return is_empty_item_; }
void SetIsEmptyItem(bool value) { is_empty_item_ = value; }
@@ -200,11 +203,6 @@ class CORE_EXPORT NGInlineItem {
static void Split(Vector<NGInlineItem>&, unsigned index, unsigned offset);
- // Return true if this is the first item created for the node. A node may be
- // split into multiple inline items due e.g. hard line breaks or bidi
- // segments.
- bool IsFirstForNode() const { return is_first_for_node_; }
-
// RunSegmenter properties.
unsigned SegmentData() const { return segment_data_; }
static void SetSegmentData(const RunSegmenter::RunSegmenterRange& range,
@@ -234,9 +232,6 @@ class CORE_EXPORT NGInlineItem {
void AssertOffset(unsigned offset) const;
void AssertEndOffset(unsigned offset) const;
- bool IsSymbolMarker() const { return is_symbol_marker_; }
- void SetIsSymbolMarker(bool b) { is_symbol_marker_ = b; }
-
String ToString() const;
private:
@@ -248,18 +243,16 @@ class CORE_EXPORT NGInlineItem {
LayoutObject* layout_object_;
NGInlineItemType type_;
+ unsigned text_type_ : 3; // NGTextType
+ unsigned style_variant_ : 2; // NGStyleVariant
+ unsigned end_collapse_type_ : 2; // NGCollapseType
+ unsigned bidi_level_ : 8; // UBiDiLevel is defined as uint8_t.
// |segment_data_| is valid only for |type_ == NGInlineItem::kText|.
unsigned segment_data_ : NGInlineItemSegment::kSegmentDataBits;
- unsigned bidi_level_ : 8; // UBiDiLevel is defined as uint8_t.
- unsigned shape_options_ : 2;
unsigned is_empty_item_ : 1;
unsigned is_block_level_ : 1;
- unsigned style_variant_ : 2;
- unsigned end_collapse_type_ : 2; // NGCollapseType
unsigned is_end_collapsible_newline_ : 1;
- unsigned is_symbol_marker_ : 1;
unsigned is_generated_for_line_break_ : 1;
- unsigned is_first_for_node_ : 1;
friend class NGInlineNode;
friend class NGInlineNodeDataEditor;
};
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item_result.cc b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item_result.cc
index b6e4388cefb..4fa2ff96298 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item_result.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item_result.cc
@@ -195,6 +195,8 @@ LayoutUnit NGLineInfo::ComputeTrailingSpaceWidth(
// not safe-to-break. We avoid reshaping in this case because the cost
// is high and the difference is subtle for the purpose of this
// function.
+ // TODO(kojii): This does not compute correctly for RTL. Need to re-work
+ // when we support UAX#9 L1.
// TODO(kojii): Compute this without |CreateShapeResult|.
scoped_refptr<ShapeResult> shape_result =
item_result.shape_result->CreateShapeResult();
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item_result.h b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item_result.h
index 2015830ed2c..66adbd9e850 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item_result.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item_result.h
@@ -6,6 +6,7 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_INLINE_ITEM_RESULT_H_
#include "third_party/blink/renderer/core/layout/ng/geometry/ng_box_strut.h"
+#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_item.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_physical_text_fragment.h"
#include "third_party/blink/renderer/core/layout/ng/ng_layout_result.h"
#include "third_party/blink/renderer/core/layout/ng/ng_positioned_float.h"
@@ -31,6 +32,7 @@ struct CORE_EXPORT NGInlineItemResult {
DISALLOW_NEW();
public:
+ NGTextOffset TextOffset() const { return {start_offset, end_offset}; }
unsigned Length() const {
DCHECK_GT(end_offset, start_offset);
return end_offset - start_offset;
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item_segment.cc b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item_segment.cc
index a0a671d3aa6..238c856b478 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item_segment.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item_segment.cc
@@ -143,15 +143,6 @@ NGInlineItemSegments::Iterator NGInlineItemSegments::Ranges(
return Iterator(start_offset, end_offset, segment);
}
-void NGInlineItemSegments::ComputeSegments(
- RunSegmenter* segmenter,
- RunSegmenter::RunSegmenterRange* range) {
- segments_.Shrink(0);
- do {
- segments_.emplace_back(*range);
- } while (segmenter->Consume(range));
-}
-
unsigned NGInlineItemSegments::AppendMixedFontOrientation(
const String& text_content,
unsigned start_offset,
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item_segment.h b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item_segment.h
index f011dfa9aa1..dd9e38afec0 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item_segment.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item_segment.h
@@ -88,10 +88,6 @@ class CORE_EXPORT NGInlineItemSegments {
segments_.emplace_back(std::forward<Args>(args)...);
}
- // Compute segments from the given |RunSegmenter|.
- void ComputeSegments(RunSegmenter* segmenter,
- RunSegmenter::RunSegmenterRange* range);
-
// Append mixed-vertical font orientation segments for the specified range.
// This is separated from |ComputeSegments| because this result depends on
// fonts.
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_items_builder.cc b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_items_builder.cc
index 84d422cbc20..6e66ff045ba 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_items_builder.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_items_builder.cc
@@ -9,7 +9,6 @@
#include "third_party/blink/renderer/core/layout/layout_inline.h"
#include "third_party/blink/renderer/core/layout/layout_text.h"
#include "third_party/blink/renderer/core/layout/ng/inline/layout_ng_text.h"
-#include "third_party/blink/renderer/core/layout/ng/inline/ng_dirty_lines.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_node_data.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_offset_mapping_builder.h"
@@ -124,14 +123,12 @@ bool ShouldRemoveNewline(const StringBuilder& before,
after_style);
}
-void AppendItem(Vector<NGInlineItem>* items,
- NGInlineItem::NGInlineItemType type,
- unsigned start,
- unsigned end,
- LayoutObject* layout_object,
- bool is_first_for_node = true) {
- items->push_back(
- NGInlineItem(type, start, end, layout_object, is_first_for_node));
+inline NGInlineItem& AppendItem(Vector<NGInlineItem>* items,
+ NGInlineItem::NGInlineItemType type,
+ unsigned start,
+ unsigned end,
+ LayoutObject* layout_object) {
+ return items->emplace_back(type, start, end, layout_object);
}
inline bool ShouldIgnore(UChar c) {
@@ -233,28 +230,28 @@ void NGInlineItemsBuilderTemplate<OffsetMappingBuilder>::BoxInfo::
template <typename OffsetMappingBuilder>
void NGInlineItemsBuilderTemplate<OffsetMappingBuilder>::AppendTextItem(
const StringView string,
- LayoutText* layout_object,
- bool is_first_for_node) {
+ LayoutText* layout_object) {
DCHECK(layout_object);
- AppendTextItem(NGInlineItem::kText, string, layout_object, is_first_for_node);
+ AppendTextItem(NGInlineItem::kText, string, layout_object);
}
template <typename OffsetMappingBuilder>
-void NGInlineItemsBuilderTemplate<OffsetMappingBuilder>::AppendTextItem(
+NGInlineItem&
+NGInlineItemsBuilderTemplate<OffsetMappingBuilder>::AppendTextItem(
NGInlineItem::NGInlineItemType type,
const StringView string,
- LayoutText* layout_object,
- bool is_first_for_node) {
+ LayoutText* layout_object) {
DCHECK(layout_object);
unsigned start_offset = text_.length();
text_.Append(string);
mapping_builder_.AppendIdentityMapping(string.length());
- AppendItem(items_, type, start_offset, text_.length(), layout_object,
- is_first_for_node);
- DCHECK(!items_->back().IsEmptyItem());
+ NGInlineItem& item =
+ AppendItem(items_, type, start_offset, text_.length(), layout_object);
+ DCHECK(!item.IsEmptyItem());
// text item is not empty.
is_empty_inline_ = false;
is_block_level_ = false;
+ return item;
}
// Empty text items are not needed for the layout purposes, but all LayoutObject
@@ -265,8 +262,8 @@ void NGInlineItemsBuilderTemplate<OffsetMappingBuilder>::AppendEmptyTextItem(
LayoutText* layout_object) {
DCHECK(layout_object);
unsigned offset = text_.length();
- AppendItem(items_, NGInlineItem::kText, offset, offset, layout_object);
- NGInlineItem& item = items_->back();
+ NGInlineItem& item =
+ AppendItem(items_, NGInlineItem::kText, offset, offset, layout_object);
item.SetEndCollapseType(NGInlineItem::kOpaqueToCollapsing);
item.SetIsEmptyItem(true);
item.SetIsBlockLevel(true);
@@ -279,10 +276,9 @@ void NGInlineItemsBuilderTemplate<OffsetMappingBuilder>::
DCHECK(layout_object);
typename OffsetMappingBuilder::SourceNodeScope scope(&mapping_builder_,
nullptr);
- AppendBreakOpportunity(layout_object);
- NGInlineItem* item = &items_->back();
- item->SetIsGeneratedForLineBreak();
- item->SetEndCollapseType(NGInlineItem::kOpaqueToCollapsing);
+ NGInlineItem& item = AppendBreakOpportunity(layout_object);
+ item.SetIsGeneratedForLineBreak();
+ item.SetEndCollapseType(NGInlineItem::kOpaqueToCollapsing);
}
template <typename OffsetMappingBuilder>
@@ -451,10 +447,6 @@ template <typename OffsetMappingBuilder>
void NGInlineItemsBuilderTemplate<OffsetMappingBuilder>::AppendText(
LayoutText* layout_text,
const NGInlineNodeData* previous_data) {
- // Mark dirty lines. Clear if marked, only the first dirty line is relevant.
- if (dirty_lines_ && dirty_lines_->HandleText(layout_text))
- dirty_lines_ = nullptr;
-
// If the LayoutText element hasn't changed, reuse the existing items.
if (previous_data && layout_text->HasValidInlineItems()) {
if (AppendTextReusing(*previous_data, layout_text)) {
@@ -506,8 +498,7 @@ template <typename OffsetMappingBuilder>
void NGInlineItemsBuilderTemplate<
OffsetMappingBuilder>::AppendCollapseWhitespace(const StringView string,
const ComputedStyle* style,
- LayoutText* layout_object,
- bool is_first_for_node) {
+ LayoutText* layout_object) {
DCHECK(!string.IsEmpty());
// This algorithm segments the input string at the collapsible space, and
@@ -534,7 +525,7 @@ void NGInlineItemsBuilderTemplate<
// LayoutBR does not set preserve_newline, but should be preserved.
if (UNLIKELY(space_run_has_newline && string.length() == 1 &&
layout_object && layout_object->IsBR())) {
- AppendForcedBreakCollapseWhitespace(layout_object, is_first_for_node);
+ AppendForcedBreakCollapseWhitespace(layout_object);
return;
}
@@ -690,9 +681,8 @@ void NGInlineItemsBuilderTemplate<
return;
}
- AppendItem(items_, NGInlineItem::kText, start_offset, text_.length(),
- layout_object, is_first_for_node);
- NGInlineItem& item = items_->back();
+ NGInlineItem& item = AppendItem(items_, NGInlineItem::kText, start_offset,
+ text_.length(), layout_object);
item.SetEndCollapseType(end_collapse, space_run_has_newline);
DCHECK(!item.IsEmptyItem());
// text item is not empty.
@@ -733,8 +723,7 @@ void NGInlineItemsBuilderTemplate<OffsetMappingBuilder>::
do {
++end;
} while (end < string.length() && string[end] == kSpaceCharacter);
- AppendTextItem(StringView(string, *start, end - *start), layout_object,
- /* is_first_for_node */ false);
+ AppendTextItem(StringView(string, *start, end - *start), layout_object);
AppendGeneratedBreakOpportunity(layout_object);
*start = end;
}
@@ -759,12 +748,11 @@ void NGInlineItemsBuilderTemplate<
unsigned start = 0;
InsertBreakOpportunityAfterLeadingPreservedSpaces(string, *style,
layout_object, &start);
- bool is_first_for_node = true;
- for (; start < string.length(); is_first_for_node = false) {
+ for (; start < string.length();) {
UChar c = string[start];
if (IsControlItemCharacter(c)) {
if (c == kNewlineCharacter) {
- AppendForcedBreak(layout_object, is_first_for_node);
+ AppendForcedBreak(layout_object);
start++;
// A forced break is not a collapsible space, but following collapsible
// spaces are leading spaces and they need a special code in the line
@@ -778,15 +766,17 @@ void NGInlineItemsBuilderTemplate<
[](UChar c) { return c != kTabulationCharacter; }, start + 1);
if (end == kNotFound)
end = string.length();
- AppendTextItem(NGInlineItem::kControl,
- StringView(string, start, end - start), layout_object,
- is_first_for_node);
+ NGInlineItem& item = AppendTextItem(
+ NGInlineItem::kControl, StringView(string, start, end - start),
+ layout_object);
+ item.SetTextType(NGTextType::kFlowControl);
start = end;
continue;
}
// ZWNJ splits item, but it should be text.
if (c != kZeroWidthNonJoinerCharacter) {
- Append(NGInlineItem::kControl, c, layout_object, is_first_for_node);
+ NGInlineItem& item = Append(NGInlineItem::kControl, c, layout_object);
+ item.SetTextType(NGTextType::kFlowControl);
start++;
continue;
}
@@ -795,8 +785,7 @@ void NGInlineItemsBuilderTemplate<
wtf_size_t end = string.Find(IsControlItemCharacter, start + 1);
if (end == kNotFound)
end = string.length();
- AppendTextItem(StringView(string, start, end - start), layout_object,
- is_first_for_node);
+ AppendTextItem(StringView(string, start, end - start), layout_object);
start = end;
}
}
@@ -806,10 +795,9 @@ void NGInlineItemsBuilderTemplate<OffsetMappingBuilder>::AppendPreserveNewline(
const String& string,
const ComputedStyle* style,
LayoutText* layout_object) {
- bool is_first_for_node = true;
- for (unsigned start = 0; start < string.length(); is_first_for_node = false) {
+ for (unsigned start = 0; start < string.length();) {
if (string[start] == kNewlineCharacter) {
- AppendForcedBreakCollapseWhitespace(layout_object, is_first_for_node);
+ AppendForcedBreakCollapseWhitespace(layout_object);
start++;
continue;
}
@@ -819,15 +807,14 @@ void NGInlineItemsBuilderTemplate<OffsetMappingBuilder>::AppendPreserveNewline(
end = string.length();
DCHECK_GE(end, start);
AppendCollapseWhitespace(StringView(string, start, end - start), style,
- layout_object, is_first_for_node);
+ layout_object);
start = end;
}
}
template <typename OffsetMappingBuilder>
void NGInlineItemsBuilderTemplate<OffsetMappingBuilder>::AppendForcedBreak(
- LayoutObject* layout_object,
- bool is_first_for_node) {
+ LayoutObject* layout_object) {
DCHECK(layout_object);
// At the forced break, add bidi controls to pop all contexts.
// https://drafts.csswg.org/css-writing-modes-3/#bidi-embedding-breaks
@@ -841,14 +828,15 @@ void NGInlineItemsBuilderTemplate<OffsetMappingBuilder>::AppendForcedBreak(
}
}
- Append(NGInlineItem::kControl, kNewlineCharacter, layout_object,
- is_first_for_node);
+ NGInlineItem& item =
+ Append(NGInlineItem::kControl, kNewlineCharacter, layout_object);
+ item.SetTextType(NGTextType::kForcedLineBreak);
// A forced break is not a collapsible space, but following collapsible spaces
// are leading spaces and that they should be collapsed.
// Pretend that this item ends with a collapsible space, so that following
// collapsible spaces can be collapsed.
- items_->back().SetEndCollapseType(NGInlineItem::kCollapsible, false);
+ item.SetEndCollapseType(NGInlineItem::kCollapsible, false);
// Then re-add bidi controls to restore the bidi context.
if (!bidi_context_.IsEmpty()) {
@@ -862,37 +850,39 @@ void NGInlineItemsBuilderTemplate<OffsetMappingBuilder>::AppendForcedBreak(
template <typename OffsetMappingBuilder>
void NGInlineItemsBuilderTemplate<OffsetMappingBuilder>::
- AppendForcedBreakCollapseWhitespace(LayoutObject* layout_object,
- bool is_first_for_node) {
+ AppendForcedBreakCollapseWhitespace(LayoutObject* layout_object) {
// Remove collapsible spaces immediately before a preserved newline.
RemoveTrailingCollapsibleSpaceIfExists();
- AppendForcedBreak(layout_object, is_first_for_node);
+ AppendForcedBreak(layout_object);
}
template <typename OffsetMappingBuilder>
-void NGInlineItemsBuilderTemplate<OffsetMappingBuilder>::AppendBreakOpportunity(
+NGInlineItem&
+NGInlineItemsBuilderTemplate<OffsetMappingBuilder>::AppendBreakOpportunity(
LayoutObject* layout_object) {
DCHECK(layout_object);
- AppendOpaque(NGInlineItem::kControl, kZeroWidthSpaceCharacter, layout_object);
+ NGInlineItem& item = AppendOpaque(NGInlineItem::kControl,
+ kZeroWidthSpaceCharacter, layout_object);
+ item.SetTextType(NGTextType::kFlowControl);
+ return item;
}
template <typename OffsetMappingBuilder>
-void NGInlineItemsBuilderTemplate<OffsetMappingBuilder>::Append(
+NGInlineItem& NGInlineItemsBuilderTemplate<OffsetMappingBuilder>::Append(
NGInlineItem::NGInlineItemType type,
UChar character,
- LayoutObject* layout_object,
- bool is_first_for_node) {
+ LayoutObject* layout_object) {
DCHECK_NE(character, kSpaceCharacter);
text_.Append(character);
mapping_builder_.AppendIdentityMapping(1);
unsigned end_offset = text_.length();
- AppendItem(items_, type, end_offset - 1, end_offset, layout_object,
- is_first_for_node);
-
- is_empty_inline_ &= items_->back().IsEmptyItem();
- is_block_level_ &= items_->back().IsBlockLevel();
+ NGInlineItem& item =
+ AppendItem(items_, type, end_offset - 1, end_offset, layout_object);
+ is_empty_inline_ &= item.IsEmptyItem();
+ is_block_level_ &= item.IsBlockLevel();
+ return item;
}
template <typename OffsetMappingBuilder>
@@ -903,12 +893,7 @@ void NGInlineItemsBuilderTemplate<OffsetMappingBuilder>::AppendAtomicInline(
layout_object);
RestoreTrailingCollapsibleSpaceIfRemoved();
Append(NGInlineItem::kAtomicInline, kObjectReplacementCharacter,
- layout_object, /* is_first_for_node */ true);
-
- // Mark dirty lines. Clear if marked, only the first dirty line is relevant.
- if (dirty_lines_ &&
- dirty_lines_->HandleAtomicInline(ToLayoutBox(layout_object)))
- dirty_lines_ = nullptr;
+ layout_object);
// When this atomic inline is inside of an inline box, the height of the
// inline box can be different from the height of the atomic inline. Ensure
@@ -926,11 +911,6 @@ void NGInlineItemsBuilderTemplate<OffsetMappingBuilder>::AppendFloating(
LayoutObject* layout_object) {
AppendOpaque(NGInlineItem::kFloating, kObjectReplacementCharacter,
layout_object);
-
- // Mark dirty lines. Clear if marked, only the first dirty line is relevant.
- if (dirty_lines_ &&
- dirty_lines_->HandleFloatingOrOutOfFlowPositioned(layout_object))
- dirty_lines_ = nullptr;
}
template <typename OffsetMappingBuilder>
@@ -938,27 +918,22 @@ void NGInlineItemsBuilderTemplate<OffsetMappingBuilder>::
AppendOutOfFlowPositioned(LayoutObject* layout_object) {
AppendOpaque(NGInlineItem::kOutOfFlowPositioned, kObjectReplacementCharacter,
layout_object);
-
- // Mark dirty lines. Clear if marked, only the first dirty line is relevant.
- if (dirty_lines_ &&
- dirty_lines_->HandleFloatingOrOutOfFlowPositioned(layout_object))
- dirty_lines_ = nullptr;
}
template <typename OffsetMappingBuilder>
-void NGInlineItemsBuilderTemplate<OffsetMappingBuilder>::AppendOpaque(
+NGInlineItem& NGInlineItemsBuilderTemplate<OffsetMappingBuilder>::AppendOpaque(
NGInlineItem::NGInlineItemType type,
UChar character,
LayoutObject* layout_object) {
text_.Append(character);
mapping_builder_.AppendIdentityMapping(1);
unsigned end_offset = text_.length();
- AppendItem(items_, type, end_offset - 1, end_offset, layout_object);
-
- NGInlineItem& item = items_->back();
+ NGInlineItem& item =
+ AppendItem(items_, type, end_offset - 1, end_offset, layout_object);
item.SetEndCollapseType(NGInlineItem::kOpaqueToCollapsing);
is_empty_inline_ &= item.IsEmptyItem();
is_block_level_ &= item.IsBlockLevel();
+ return item;
}
template <typename OffsetMappingBuilder>
@@ -966,9 +941,8 @@ void NGInlineItemsBuilderTemplate<OffsetMappingBuilder>::AppendOpaque(
NGInlineItem::NGInlineItemType type,
LayoutObject* layout_object) {
unsigned end_offset = text_.length();
- AppendItem(items_, type, end_offset, end_offset, layout_object);
-
- NGInlineItem& item = items_->back();
+ NGInlineItem& item =
+ AppendItem(items_, type, end_offset, end_offset, layout_object);
item.SetEndCollapseType(NGInlineItem::kOpaqueToCollapsing);
is_empty_inline_ &= item.IsEmptyItem();
is_block_level_ &= item.IsBlockLevel();
@@ -1004,12 +978,6 @@ void NGInlineItemsBuilderTemplate<
text_.erase(space_offset);
mapping_builder_.CollapseTrailingSpace(space_offset);
- // Mark dirty lines. Clear if marked, only the first dirty line is relevant.
- if (dirty_lines_) {
- dirty_lines_->MarkAtTextOffset(space_offset);
- dirty_lines_ = nullptr;
- }
-
// Keep the item even if the length became zero. This is not needed for
// the layout purposes, but needed to maintain LayoutObject states. See
// |AddEmptyTextItem()|.
@@ -1171,10 +1139,6 @@ void NGInlineItemsBuilderTemplate<OffsetMappingBuilder>::EnterInline(
AppendOpaque(NGInlineItem::kOpenTag, node);
- // Mark dirty lines. Clear if marked, only the first dirty line is relevant.
- if (dirty_lines_ && dirty_lines_->HandleInlineBox(node))
- dirty_lines_ = nullptr;
-
if (!NeedsBoxInfo())
return;
@@ -1268,10 +1232,9 @@ void NGInlineItemsBuilderTemplate<
}
template <typename OffsetMappingBuilder>
-void NGInlineItemsBuilderTemplate<OffsetMappingBuilder>::SetIsSymbolMarker(
- bool b) {
+void NGInlineItemsBuilderTemplate<OffsetMappingBuilder>::SetIsSymbolMarker() {
DCHECK(!items_->IsEmpty());
- items_->back().SetIsSymbolMarker(b);
+ items_->back().SetIsSymbolMarker();
}
// Ensure this LayoutObject IsInLayoutNGInlineFormattingContext and does not
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_items_builder.h b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_items_builder.h
index eb58909de1d..a8e6d3f5907 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_items_builder.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_items_builder.h
@@ -22,7 +22,6 @@ class LayoutInline;
class LayoutObject;
class LayoutText;
struct NGInlineNodeData;
-class NGDirtyLines;
// NGInlineItemsBuilder builds a string and a list of NGInlineItem from inlines.
//
@@ -45,12 +44,8 @@ class NGInlineItemsBuilderTemplate {
public:
// Create a builder that appends items to |items|.
- //
- // If |dirty_lines| is given, this builder calls its functions to mark lines
- // dirty.
- explicit NGInlineItemsBuilderTemplate(Vector<NGInlineItem>* items,
- NGDirtyLines* dirty_lines = nullptr)
- : items_(items), dirty_lines_(dirty_lines) {}
+ explicit NGInlineItemsBuilderTemplate(Vector<NGInlineItem>* items)
+ : items_(items) {}
~NGInlineItemsBuilderTemplate();
String ToString();
@@ -97,7 +92,7 @@ class NGInlineItemsBuilderTemplate {
void AppendText(const String& text, LayoutText* layout_text);
// Append a break opportunity; e.g., <wbr> element.
- void AppendBreakOpportunity(LayoutObject* layout_object);
+ NGInlineItem& AppendBreakOpportunity(LayoutObject* layout_object);
// Append a unicode "object replacement character" for an atomic inline,
// signaling the presence of a non-text object to the unicode bidi algorithm.
@@ -113,9 +108,9 @@ class NGInlineItemsBuilderTemplate {
// The character is opaque to space collapsing; i.e., spaces before this
// character and after this character can collapse as if this character does
// not exist.
- void AppendOpaque(NGInlineItem::NGInlineItemType,
- UChar,
- LayoutObject* = nullptr);
+ NGInlineItem& AppendOpaque(NGInlineItem::NGInlineItemType,
+ UChar,
+ LayoutObject* = nullptr);
// Append a non-character item that is opaque to space collapsing.
void AppendOpaque(NGInlineItem::NGInlineItemType,
@@ -139,7 +134,7 @@ class NGInlineItemsBuilderTemplate {
OffsetMappingBuilder& GetOffsetMappingBuilder() { return mapping_builder_; }
- void SetIsSymbolMarker(bool b);
+ void SetIsSymbolMarker();
bool ShouldAbort() const { return false; }
@@ -154,8 +149,6 @@ class NGInlineItemsBuilderTemplate {
Vector<NGInlineItem>* items_;
StringBuilder text_;
- NGDirtyLines* dirty_lines_;
-
// |mapping_builder_| builds the whitespace-collapsed offset mapping
// during inline collection. It is updated whenever |text_| is modified or a
// white space is collapsed.
@@ -194,23 +187,18 @@ class NGInlineItemsBuilderTemplate {
// as its String version does.
// See the String version for using nullptr for ComputedStyle and
// LayoutObject.
- void Append(NGInlineItem::NGInlineItemType,
- UChar,
- LayoutObject*,
- bool is_first_for_node);
+ NGInlineItem& Append(NGInlineItem::NGInlineItemType, UChar, LayoutObject*);
void AppendCollapseWhitespace(const StringView,
const ComputedStyle*,
- LayoutText*,
- bool is_first_for_node = true);
+ LayoutText*);
void AppendPreserveWhitespace(const String&,
const ComputedStyle*,
LayoutText*);
void AppendPreserveNewline(const String&, const ComputedStyle*, LayoutText*);
- void AppendForcedBreakCollapseWhitespace(LayoutObject*,
- bool is_first_for_node);
- void AppendForcedBreak(LayoutObject*, bool is_first_for_node);
+ void AppendForcedBreakCollapseWhitespace(LayoutObject*);
+ void AppendForcedBreak(LayoutObject*);
void RemoveTrailingCollapsibleSpaceIfExists();
void RemoveTrailingCollapsibleSpace(NGInlineItem*);
@@ -218,13 +206,10 @@ class NGInlineItemsBuilderTemplate {
void RestoreTrailingCollapsibleSpaceIfRemoved();
void RestoreTrailingCollapsibleSpace(NGInlineItem*);
- void AppendTextItem(const StringView,
- LayoutText* layout_object,
- bool is_first_for_node);
- void AppendTextItem(NGInlineItem::NGInlineItemType type,
- const StringView,
- LayoutText* layout_object,
- bool is_first_for_node);
+ void AppendTextItem(const StringView, LayoutText* layout_object);
+ NGInlineItem& AppendTextItem(NGInlineItem::NGInlineItemType type,
+ const StringView,
+ LayoutText* layout_object);
void AppendEmptyTextItem(LayoutText* layout_object);
void AppendGeneratedBreakOpportunity(LayoutObject*);
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_layout_algorithm.cc b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_layout_algorithm.cc
index 76a67f7e9eb..0ab10f3f371 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_layout_algorithm.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_layout_algorithm.cc
@@ -67,9 +67,7 @@ NGInlineLayoutAlgorithm::NGInlineLayoutAlgorithm(
context_(context),
baseline_type_(container_builder_.Style().GetFontBaseline()),
is_horizontal_writing_mode_(
- blink::IsHorizontalWritingMode(space.GetWritingMode())),
- truncate_type_(
- static_cast<unsigned>(TruncateTypeFromConstraintSpace(space))) {
+ blink::IsHorizontalWritingMode(space.GetWritingMode())) {
DCHECK(context);
quirks_mode_ = inline_node.InLineHeightQuirksMode();
}
@@ -109,14 +107,10 @@ NGInlineBoxState* NGInlineLayoutAlgorithm::HandleCloseTag(
box->EnsureTextMetrics(*item.Style(), baseline_type_);
box = box_states_->OnCloseTag(&line_box_, box, baseline_type_,
item.HasEndEdge());
- if (!RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()) {
- // Just clear |NeedsLayout| flags. Culled inline boxes do not need paint
- // invalidations. If this object produces box fragments,
- // |NGInlineBoxStateStack| takes care of invalidations.
- item.GetLayoutObject()->ClearNeedsLayoutWithoutPaintInvalidation();
- } else {
- item.GetLayoutObject()->ClearNeedsLayout();
- }
+ // Just clear |NeedsLayout| flags. Culled inline boxes do not need paint
+ // invalidations. If this object produces box fragments,
+ // |NGInlineBoxStateStack| takes care of invalidations.
+ item.GetLayoutObject()->ClearNeedsLayoutWithoutPaintInvalidation();
return box;
}
@@ -206,8 +200,6 @@ void NGInlineLayoutAlgorithm::CreateLine(
// of items, which are needed to compute inline static positions.
LayoutUnit line_offset_for_text_align = ApplyTextAlign(line_info);
- NGTextFragmentBuilder text_builder(ConstraintSpace().GetWritingMode());
-
// Compute heights of all inline items by placing the dominant baseline at 0.
// The baseline is adjusted after the height of the line box is computed.
const ComputedStyle& line_style = line_info->LineStyle();
@@ -229,6 +221,7 @@ void NGInlineLayoutAlgorithm::CreateLine(
if (quirks_mode_ && line_style.Display() == EDisplay::kListItem)
box->ComputeTextMetrics(line_style, baseline_type_);
+ bool has_logical_text_items = false;
for (NGInlineItemResult& item_result : *line_items) {
DCHECK(item_result.item);
const NGInlineItem& item = *item_result.item;
@@ -238,8 +231,6 @@ void NGInlineLayoutAlgorithm::CreateLine(
item.GetLayoutObject()->IsLayoutNGListItem());
DCHECK(item_result.shape_result);
- text_builder.SetIsFirstForNode(IsFirstForNode(item, BreakToken()));
-
if (UNLIKELY(quirks_mode_))
box->EnsureTextMetrics(*item.Style(), baseline_type_);
@@ -249,25 +240,20 @@ void NGInlineLayoutAlgorithm::CreateLine(
baseline_type_);
}
- if (UNLIKELY(item.IsSymbolMarker())) {
- text_builder.SetItem(NGPhysicalTextFragment::kSymbolMarker,
- line_info->ItemsData(), &item_result,
- box->text_height);
- } else {
- text_builder.SetItem(NGPhysicalTextFragment::kNormalText,
- line_info->ItemsData(), &item_result,
- box->text_height);
- }
+ DCHECK(item.TextType() == NGTextType::kNormal ||
+ item.TextType() == NGTextType::kSymbolMarker);
if (UNLIKELY(item_result.hyphen_shape_result)) {
LayoutUnit hyphen_inline_size = item_result.HyphenInlineSize();
- line_box_.AddChild(text_builder.ToTextFragment(), box->text_top,
+ line_box_.AddChild(&item_result, box->text_top,
item_result.inline_size - hyphen_inline_size,
- item.BidiLevel());
+ box->text_height, item.BidiLevel());
PlaceHyphen(item_result, hyphen_inline_size, box);
} else {
- line_box_.AddChild(text_builder.ToTextFragment(), box->text_top,
- item_result.inline_size, item.BidiLevel());
+ line_box_.AddChild(&item_result, box->text_top, item_result.inline_size,
+ box->text_height, item.BidiLevel());
}
+ has_logical_text_items = true;
+
// Text boxes always need full paint invalidations.
item.GetLayoutObject()->ClearNeedsLayoutWithFullPaintInvalidation();
@@ -312,22 +298,34 @@ void NGInlineLayoutAlgorithm::CreateLine(
box_states_->PrepareForReorder(&line_box_);
BidiReorder(line_info->BaseDirection());
box_states_->UpdateAfterReorder(&line_box_);
+ } else {
+ DCHECK(IsLtr(line_info->BaseDirection()));
+ }
+ const LayoutUnit hang_width = line_info->HangWidth();
+ LayoutUnit inline_size;
+ if (IsLtr(line_info->BaseDirection())) {
+ inline_size = box_states_->ComputeInlinePositions(&line_box_, LayoutUnit());
+ } else {
+ inline_size = box_states_->ComputeInlinePositions(&line_box_, -hang_width);
+ inline_size += hang_width;
}
- LayoutUnit inline_size = box_states_->ComputeInlinePositions(&line_box_);
- if (LayoutUnit hang_width = line_info->HangWidth()) {
+ if (UNLIKELY(hang_width)) {
inline_size -= hang_width;
container_builder_.SetHangInlineSize(hang_width);
-
- if (IsRtl(line_info->BaseDirection())) {
- line_box_.MoveInInlineDirection(-hang_width);
- }
}
// Truncate the line if 'text-overflow: ellipsis' is set, or for line-clamp.
if (UNLIKELY((inline_size >
line_info->AvailableWidth() - line_info->TextIndent() &&
node_.GetLayoutBlockFlow()->ShouldTruncateOverflowingText()) ||
- ShouldTruncateForLineClamp(*line_info))) {
+ ConstraintSpace().LinesUntilClamp() == 1)) {
+ // TODO(kojii): |NGLineTruncator| does not support |Child|-based truncation
+ // yet, so create |NGPhysicalTextFragment| first.
+ if (has_logical_text_items) {
+ line_box_.CreateTextFragments(ConstraintSpace().GetWritingMode(),
+ line_info->ItemsData().text_content);
+ has_logical_text_items = false;
+ }
NGLineTruncator truncator(*line_info);
auto* input =
DynamicTo<HTMLInputElement>(node_.GetLayoutBlockFlow()->GetNode());
@@ -340,6 +338,12 @@ void NGInlineLayoutAlgorithm::CreateLine(
}
}
+ if (has_logical_text_items &&
+ !RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()) {
+ line_box_.CreateTextFragments(ConstraintSpace().GetWritingMode(),
+ line_info->ItemsData().text_content);
+ }
+
// Negative margins can make the position negative, but the inline size is
// always positive or 0.
inline_size = inline_size.ClampNegativeToZero();
@@ -385,6 +389,11 @@ void NGInlineLayoutAlgorithm::CreateLine(
context_->SetItemIndex(line_info->ItemsData().items,
line_info->EndItemIndex());
+ if (UNLIKELY(RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled())) {
+ NGFragmentItem::Create(&line_box_, line_info->ItemsData().text_content,
+ ConstraintSpace().GetWritingMode());
+ }
+
// Even if we have something in-flow, it may just be empty items that
// shouldn't trigger creation of a line. Exit now if that's the case.
if (line_info->IsEmptyLine()) {
@@ -416,26 +425,31 @@ void NGInlineLayoutAlgorithm::PlaceControlItem(const NGInlineItem& item,
DCHECK_EQ(item.Type(), NGInlineItem::kControl);
DCHECK_GE(item.Length(), 1u);
DCHECK(!item.TextShapeResult());
+#if DCHECK_IS_ON()
UChar character = line_info.ItemsData().text_content[item.StartOffset()];
- NGPhysicalTextFragment::NGTextType type;
+ NGTextType text_type;
switch (character) {
case kNewlineCharacter:
- type = NGPhysicalTextFragment::kForcedLineBreak;
+ text_type = NGTextType::kForcedLineBreak;
break;
case kTabulationCharacter:
- type = NGPhysicalTextFragment::kFlowControl;
+ text_type = NGTextType::kFlowControl;
break;
case kZeroWidthSpaceCharacter:
- // Don't generate fragments if this is a generated (not in DOM) break
- // opportunity during the white space collapsing in NGInlineItemBuilder.
- if (item.IsGeneratedForLineBreak())
- return;
- type = NGPhysicalTextFragment::kFlowControl;
+ text_type = NGTextType::kFlowControl;
break;
default:
NOTREACHED();
return;
}
+ DCHECK_EQ(item.TextType(), text_type);
+#endif
+
+ // Don't generate fragments if this is a generated (not in DOM) break
+ // opportunity during the white space collapsing in NGInlineItemBuilder.
+ if (UNLIKELY(item.IsGeneratedForLineBreak()))
+ return;
+
DCHECK(item.GetLayoutObject());
DCHECK(item.GetLayoutObject()->IsText());
ClearNeedsLayoutIfNeeded(item.GetLayoutObject());
@@ -444,9 +458,8 @@ void NGInlineLayoutAlgorithm::PlaceControlItem(const NGInlineItem& item,
box->EnsureTextMetrics(*item.Style(), baseline_type_);
NGTextFragmentBuilder text_builder(ConstraintSpace().GetWritingMode());
- text_builder.SetItem(type, line_info.ItemsData(), item_result,
+ text_builder.SetItem(line_info.ItemsData().text_content, item_result,
box->text_height);
- text_builder.SetIsFirstForNode(IsFirstForNode(item, BreakToken()));
line_box_.AddChild(text_builder.ToTextFragment(), box->text_top,
item_result->inline_size, item.BidiLevel());
}
@@ -1003,8 +1016,6 @@ scoped_refptr<const NGLayoutResult> NGInlineLayoutAlgorithm::Layout() {
container_builder_.PropagateChildrenData(line_box_);
scoped_refptr<const NGLayoutResult> layout_result =
container_builder_.ToLineBoxFragment();
- if (items_builder->TextContent(false).IsNull())
- items_builder->SetTextContent(Node());
items_builder->SetCurrentLine(
To<NGPhysicalLineBoxFragment>(layout_result->PhysicalFragment()),
std::move(line_box_));
@@ -1129,28 +1140,12 @@ void NGInlineLayoutAlgorithm::BidiReorder(TextDirection base_direction) {
visual_items.ReserveInitialCapacity(line_box_.size());
for (unsigned logical_index : indices_in_visual_order) {
visual_items.AddChild(std::move(line_box_[logical_index]));
- DCHECK(!line_box_[logical_index].HasInFlowFragment());
+ DCHECK(!line_box_[logical_index].HasInFlowFragment() ||
+ // |item_result| will not be null by moving.
+ line_box_[logical_index].item_result);
}
DCHECK_EQ(line_box_.size(), visual_items.size());
line_box_ = std::move(visual_items);
}
-// static
-NGInlineLayoutAlgorithm::TruncateType
-NGInlineLayoutAlgorithm::TruncateTypeFromConstraintSpace(
- const NGConstraintSpace& space) {
- if (space.LinesUntilClamp() != 1)
- return TruncateType::kDefault;
- return space.ForceTruncateAtLineClamp() ? TruncateType::kAlways
- : TruncateType::kIfNotLastLine;
-}
-
-bool NGInlineLayoutAlgorithm::ShouldTruncateForLineClamp(
- const NGLineInfo& line_info) const {
- const TruncateType truncate_type = static_cast<TruncateType>(truncate_type_);
- return truncate_type == TruncateType::kAlways ||
- (truncate_type == TruncateType::kIfNotLastLine &&
- !line_info.IsLastLine());
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_layout_algorithm.h b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_layout_algorithm.h
index 604eefb4041..23722eca460 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_layout_algorithm.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_layout_algorithm.h
@@ -51,20 +51,12 @@ class CORE_EXPORT NGInlineLayoutAlgorithm final
scoped_refptr<const NGLayoutResult> Layout() override;
- private:
- enum class TruncateType {
- // Indicates default behavior. The default truncates if the text doesn't
- // fit and ShouldTruncateOverflowingText() returns true.
- kDefault,
-
- // Truncate if NGLineInfo has more lines.
- kIfNotLastLine,
-
- // Forces truncation. This is used when line-clamp is set and there are
- // blocks after this.
- kAlways,
- };
+ MinMaxSizesResult ComputeMinMaxSizes(const MinMaxSizesInput&) const override {
+ NOTREACHED();
+ return {MinMaxSizes(), true};
+ }
+ private:
unsigned PositionLeadingFloats(NGExclusionSpace*, NGPositionedFloatVector*);
NGPositionedFloat PositionFloat(LayoutUnit origin_block_bfc_offset,
LayoutObject* floating_object,
@@ -119,13 +111,6 @@ class CORE_EXPORT NGInlineLayoutAlgorithm final
const NGExclusionSpace&,
LayoutUnit line_height);
- static TruncateType TruncateTypeFromConstraintSpace(
- const NGConstraintSpace& space);
-
- // Returns true if truncuation should happen as a result of line-clamp for
- // |line_info|.
- bool ShouldTruncateForLineClamp(const NGLineInfo& line_info) const;
-
NGLineBoxFragmentBuilder::ChildList line_box_;
NGInlineLayoutStateStack* box_states_;
NGInlineChildLayoutContext* context_;
@@ -134,7 +119,6 @@ class CORE_EXPORT NGInlineLayoutAlgorithm final
unsigned is_horizontal_writing_mode_ : 1;
unsigned quirks_mode_ : 1;
- unsigned truncate_type_ : 2;
#if DCHECK_IS_ON()
// True if |box_states_| is taken from |context_|, to check the |box_states_|
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_layout_algorithm_test.cc b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_layout_algorithm_test.cc
index fbb4e323541..9bd25a79215 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_layout_algorithm_test.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_layout_algorithm_test.cc
@@ -55,7 +55,7 @@ TEST_F(NGInlineLayoutAlgorithmTest, BreakToken) {
NGBoxFragmentBuilder container_builder(block_flow, block_flow->Style(),
block_flow->Style()->GetWritingMode(),
block_flow->Style()->Direction());
- NGFragmentItemsBuilder items_builder(&container_builder);
+ NGFragmentItemsBuilder items_builder(inline_node);
if (RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()) {
container_builder.SetItemsBuilder(&items_builder);
context.SetItemsBuilder(&items_builder);
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.cc b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.cc
index 740ab5a243f..075cd9ebf3b 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.cc
@@ -15,7 +15,6 @@
#include "third_party/blink/renderer/core/layout/layout_text.h"
#include "third_party/blink/renderer/core/layout/ng/inline/layout_ng_text.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_bidi_paragraph.h"
-#include "third_party/blink/renderer/core/layout/ng/inline/ng_dirty_lines.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_break_token.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_item.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_items_builder.h"
@@ -63,74 +62,6 @@ unsigned EstimateOffsetMappingItemsCount(const LayoutBlockFlow& block) {
return EstimateInlineItemsCount(block) / 4;
}
-// This class has the same interface as NGInlineItemsBuilder but does nothing
-// except tracking if floating or out-of-flow objects are added.
-//
-// |MarkLineBoxesDirty| uses this class to traverse tree without buildling
-// |NGInlineItem|.
-class ItemsBuilderForMarkLineBoxesDirty {
- STACK_ALLOCATED();
-
- public:
- ItemsBuilderForMarkLineBoxesDirty(NGDirtyLines* dirty_lines)
- : dirty_lines_(dirty_lines) {}
- void AppendText(LayoutText* layout_text, const NGInlineItemsData*) {
- if (dirty_lines_ && dirty_lines_->HandleText(layout_text))
- dirty_lines_ = nullptr;
- }
- void AppendOpaque(NGInlineItem::NGInlineItemType,
- LayoutObject*) {}
- void AppendAtomicInline(LayoutObject* layout_object) {
- if (dirty_lines_ &&
- dirty_lines_->HandleAtomicInline(ToLayoutBox(layout_object)))
- dirty_lines_ = nullptr;
- }
- void AppendFloating(LayoutObject*) {
- has_floating_or_out_of_flow_positioned_ = true;
- }
- void AppendOutOfFlowPositioned(LayoutObject*) {
- has_floating_or_out_of_flow_positioned_ = true;
- }
- void SetIsSymbolMarker(bool) {}
- void EnterBlock(const ComputedStyle*) {}
- void ExitBlock() {}
- void EnterInline(LayoutInline* layout_inline) {
- if (dirty_lines_ && dirty_lines_->HandleInlineBox(layout_inline))
- dirty_lines_ = nullptr;
- }
- void ExitInline(LayoutObject*) {}
-
- bool ShouldAbort() const {
- // Aborting in the middle of the traversal is safe because this function
- // ClearNeedsLayout() on text and LayoutInline, but since an inline
- // formatting context is laid out as a whole, these flags don't matter.
- // For that reason, the traversal should not ClearNeedsLayout() atomic
- // inlines, floats, or OOF -- objects that need to be laid out separately
- // from the inline formatting context.
- // TODO(kojii): This looks a bit tricky, better to come up with clearner
- // solution if any.
- return has_floating_or_out_of_flow_positioned_;
- }
-
- void ClearInlineFragment(LayoutObject* object) {
- DCHECK(object->IsInLayoutNGInlineFormattingContext());
- }
-
- void ClearNeedsLayout(LayoutObject* object) {
- object->ClearNeedsLayout();
- DCHECK(!object->NeedsCollectInlines());
- ClearInlineFragment(object);
- }
-
- void UpdateShouldCreateBoxFragment(LayoutInline* object) {
- object->UpdateShouldCreateBoxFragment();
- }
-
- private:
- NGDirtyLines* dirty_lines_;
- bool has_floating_or_out_of_flow_positioned_ = false;
-};
-
// Wrapper over ShapeText that re-uses existing shape results for items that
// haven't changed.
class ReusingTextShaper final {
@@ -265,7 +196,7 @@ void CollectInlinesInternal(LayoutBlockFlow* block,
builder->AppendText(layout_text, previous_data);
if (symbol == layout_text)
- builder->SetIsSymbolMarker(true);
+ builder->SetIsSymbolMarker();
builder->ClearNeedsLayout(layout_text);
@@ -453,24 +384,16 @@ void NGInlineNode::PrepareLayoutIfNeeded() {
block_flow->ResetNGInlineNodeData();
}
- if (RuntimeEnabledFeatures::LayoutNGLineCacheEnabled()) {
- if (const NGPaintFragment* fragment = block_flow->PaintFragment()) {
- NGDirtyLines dirty_lines(fragment);
- PrepareLayout(std::move(previous_data), &dirty_lines);
- return;
- }
- }
- PrepareLayout(std::move(previous_data), /* dirty_lines */ nullptr);
+ PrepareLayout(std::move(previous_data));
}
void NGInlineNode::PrepareLayout(
- std::unique_ptr<NGInlineNodeData> previous_data,
- NGDirtyLines* dirty_lines) {
+ std::unique_ptr<NGInlineNodeData> previous_data) {
// Scan list of siblings collecting all in-flow non-atomic inlines. A single
// NGInlineNode represent a collection of adjacent non-atomic inlines.
NGInlineNodeData* data = MutableData();
DCHECK(data);
- CollectInlines(data, previous_data.get(), dirty_lines);
+ CollectInlines(data, previous_data.get());
SegmentText(data);
ShapeText(data, previous_data ? &previous_data->text_content : nullptr);
ShapeTextForFirstLineIfNeeded(data);
@@ -765,7 +688,7 @@ bool NGInlineNode::SetTextWithOffset(LayoutText* layout_text,
NGInlineNode node(editor.GetLayoutBlockFlow());
NGInlineNodeData* data = node.MutableData();
data->items.ReserveCapacity(previous_data->items.size());
- NGInlineItemsBuilder builder(&data->items, nullptr);
+ NGInlineItemsBuilder builder(&data->items);
// TODO(yosin): We should reuse before/after |layout_text| during collecting
// inline items.
layout_text->ClearInlineItems();
@@ -868,15 +791,14 @@ const NGOffsetMapping* NGInlineNode::GetOffsetMapping(
// parent LayoutInline where possible, and joining all text content in a single
// string to allow bidi resolution and shaping of the entire block.
void NGInlineNode::CollectInlines(NGInlineNodeData* data,
- NGInlineNodeData* previous_data,
- NGDirtyLines* dirty_lines) {
+ NGInlineNodeData* previous_data) {
DCHECK(data->text_content.IsNull());
DCHECK(data->items.IsEmpty());
LayoutBlockFlow* block = GetLayoutBlockFlow();
block->WillCollectInlines();
data->items.ReserveCapacity(EstimateInlineItemsCount(*block));
- NGInlineItemsBuilder builder(&data->items, dirty_lines);
+ NGInlineItemsBuilder builder(&data->items);
CollectInlinesInternal(block, &builder, previous_data);
builder.DidFinishCollectInlines(data);
}
@@ -891,41 +813,85 @@ void NGInlineNode::SegmentText(NGInlineNodeData* data) {
// Segment NGInlineItem by script, Emoji, and orientation using RunSegmenter.
void NGInlineNode::SegmentScriptRuns(NGInlineNodeData* data) {
+ DCHECK_EQ(data->segments, nullptr);
+
String& text_content = data->text_content;
if (text_content.IsEmpty()) {
- data->segments = nullptr;
+ return;
+ }
+
+ Vector<NGInlineItem>& items = data->items;
+ if (items.IsEmpty()) {
return;
}
if (text_content.Is8Bit() && !data->is_bidi_enabled_) {
- if (data->items.size()) {
- RunSegmenter::RunSegmenterRange range = {
- 0u, data->text_content.length(), USCRIPT_LATIN,
- OrientationIterator::kOrientationKeep, FontFallbackPriority::kText};
- NGInlineItem::SetSegmentData(range, &data->items);
- }
- data->segments = nullptr;
+ RunSegmenter::RunSegmenterRange range = {
+ 0u, data->text_content.length(), USCRIPT_LATIN,
+ OrientationIterator::kOrientationKeep, FontFallbackPriority::kText};
+ NGInlineItem::SetSegmentData(range, &items);
return;
}
// Segment by script and Emoji.
// Orientation is segmented separately, because it may vary by items.
text_content.Ensure16Bit();
- RunSegmenter segmenter(text_content.Characters16(), text_content.length(),
- FontOrientation::kHorizontal);
+
+ NGInlineItem* current_item = &items.front();
+ unsigned range_length = current_item->Length();
+
RunSegmenter::RunSegmenterRange range = RunSegmenter::NullRange();
+ if (data->is_bidi_enabled_) {
+ // run RunSegmenter for each bidi run
+ for (wtf_size_t idx = 1; idx < items.size(); idx++) {
+ NGInlineItem& item = items[idx];
+ if (item.BidiLevel() == current_item->BidiLevel()) {
+ // same bidi level as the previous item. We can merge
+ range_length += item.Length();
+ continue;
+ }
+
+ // We have reached the boundary of a bidi run. We need to run the script
+ // segmenter.
+ if (!data->segments) {
+ data->segments = std::make_unique<NGInlineItemSegments>();
+ }
+ RunSegmenter segmenter(text_content.Characters16(), range_length,
+ FontOrientation::kHorizontal,
+ current_item->StartOffset());
+ while (segmenter.Consume(&range)) {
+ data->segments->Append(range);
+ }
+ range_length = item.Length();
+ current_item = &item;
+ }
+ } else {
+ range_length = text_content.length();
+ }
+
+ // We will now handle the last item. If the text is not bidirectional, it
+ // will be the only one.
+
+ if (range_length == 0) {
+ return;
+ }
+
+ RunSegmenter segmenter(text_content.Characters16(), range_length,
+ FontOrientation::kHorizontal,
+ current_item->StartOffset());
bool consumed = segmenter.Consume(&range);
DCHECK(consumed);
- if (range.end == text_content.length()) {
- NGInlineItem::SetSegmentData(range, &data->items);
- data->segments = nullptr;
+ if (range.start == 0 && range.end == text_content.length()) {
+ NGInlineItem::SetSegmentData(range, &items);
return;
}
- // This node has multiple segments.
- if (!data->segments)
+ if (!data->segments) {
data->segments = std::make_unique<NGInlineItemSegments>();
- data->segments->ComputeSegments(&segmenter, &range);
+ }
+ do {
+ data->segments->Append(range);
+ } while (segmenter.Consume(&range));
DCHECK_EQ(range.end, text_content.length());
}
@@ -1342,84 +1308,6 @@ scoped_refptr<const NGLayoutResult> NGInlineNode::Layout(
return layout_result;
}
-const NGPaintFragment* NGInlineNode::ReusableLineBoxContainer(
- const NGConstraintSpace& constraint_space) {
- DCHECK(RuntimeEnabledFeatures::LayoutNGLineCacheEnabled());
- // |SelfNeedsLayout()| is the most common reason that we check it earlier.
- LayoutBlockFlow* block_flow = GetLayoutBlockFlow();
- DCHECK(!block_flow->SelfNeedsLayout());
- DCHECK(block_flow->EverHadLayout());
-
- if (!IsPrepareLayoutFinished())
- return nullptr;
-
- if (MaybeDirtyData().changes_may_affect_earlier_lines_)
- return nullptr;
-
- const NGLayoutResult* cached_layout_result =
- block_flow->GetCachedLayoutResult();
- if (!cached_layout_result)
- return nullptr;
-
- const NGConstraintSpace& old_space =
- cached_layout_result->GetConstraintSpaceForCaching();
- if (constraint_space.AvailableSize().inline_size !=
- old_space.AvailableSize().inline_size)
- return nullptr;
-
- // Floats in either cached or new constraint space prevents reusing cached
- // lines.
- if (constraint_space.HasFloats() || old_space.HasFloats())
- return nullptr;
-
- // Any floats might need to move, causing lines to wrap differently, needing
- // re-layout.
- if (!cached_layout_result->ExclusionSpace().IsEmpty())
- return nullptr;
-
- // Propagating OOF needs re-layout.
- if (cached_layout_result->PhysicalFragment()
- .HasOutOfFlowPositionedDescendants())
- return nullptr;
-
- // Block fragmentation is not supported yet.
- if (constraint_space.HasBlockFragmentation())
- return nullptr;
-
- const NGPaintFragment* paint_fragment = block_flow->PaintFragment();
- if (!paint_fragment)
- return nullptr;
-
- if (!MarkLineBoxesDirty(block_flow, paint_fragment))
- return nullptr;
-
- if (Data().changes_may_affect_earlier_lines_)
- return nullptr;
-
- return paint_fragment;
-}
-
-// Mark the first line box that have |NeedsLayout()| dirty.
-//
-// Removals of LayoutObject already marks relevant line boxes dirty by calling
-// |DirtyLinesFromChangedChild()|, but insertions and style changes are not
-// marked yet.
-bool NGInlineNode::MarkLineBoxesDirty(LayoutBlockFlow* block_flow,
- const NGPaintFragment* paint_fragment) {
- DCHECK(RuntimeEnabledFeatures::LayoutNGLineCacheEnabled());
- NGDirtyLines dirty_lines(paint_fragment);
- if (block_flow->NeedsCollectInlines()) {
- std::unique_ptr<NGInlineNodeData> previous_data;
- previous_data.reset(block_flow->TakeNGInlineNodeData());
- block_flow->ResetNGInlineNodeData();
- PrepareLayout(std::move(previous_data), &dirty_lines);
- return true;
- }
- ItemsBuilderForMarkLineBoxesDirty builder(&dirty_lines);
- CollectInlinesInternal(block_flow, &builder, nullptr);
- return !builder.ShouldAbort();
-}
-
namespace {
template <typename CharType>
@@ -1470,7 +1358,8 @@ static LayoutUnit ComputeContentSize(
const MinMaxSizesInput& input,
NGLineBreakerMode mode,
NGLineBreaker::MaxSizeCache* max_size_cache,
- base::Optional<LayoutUnit>* max_size_out) {
+ base::Optional<LayoutUnit>* max_size_out,
+ bool* depends_on_percentage_block_size_out) {
const ComputedStyle& style = node.Style();
WritingMode writing_mode = style.GetWritingMode();
LayoutUnit available_inline_size =
@@ -1493,7 +1382,8 @@ static LayoutUnit ComputeContentSize(
empty_leading_floats,
/* handled_leading_floats_index */ 0u,
/* break_token */ nullptr, &empty_exclusion_space);
- line_breaker.SetMaxSizeCache(max_size_cache);
+ line_breaker.SetIntrinsicSizeOutputs(max_size_cache,
+ depends_on_percentage_block_size_out);
const NGInlineItemsData& items_data = line_breaker.ItemsData();
// Computes max-size for floats in inline formatting context.
@@ -1698,16 +1588,23 @@ static LayoutUnit ComputeContentSize(
// Floats don't intrude into floats.
MinMaxSizesInput float_input(input.percentage_resolution_block_size);
- MinMaxSizes child_sizes =
+ MinMaxSizesResult child_result =
ComputeMinAndMaxContentContribution(style, float_node, float_input);
LayoutUnit child_inline_margins =
ComputeMinMaxMargins(style, float_node).InlineSum();
+ if (depends_on_percentage_block_size_out) {
+ *depends_on_percentage_block_size_out |=
+ child_result.depends_on_percentage_block_size;
+ }
+
if (mode == NGLineBreakerMode::kMinContent) {
- result = std::max(result, child_sizes.min_size + child_inline_margins);
+ result = std::max(result,
+ child_result.sizes.min_size + child_inline_margins);
}
- floats_max_size.AddFloat(float_style, style,
- child_sizes.max_size + child_inline_margins);
+ floats_max_size.AddFloat(
+ float_style, style,
+ child_result.sizes.max_size + child_inline_margins);
}
if (mode == NGLineBreakerMode::kMinContent) {
@@ -1724,7 +1621,7 @@ static LayoutUnit ComputeContentSize(
#if DCHECK_IS_ON()
LayoutUnit content_size = ComputeContentSize(
node, container_writing_mode, input, NGLineBreakerMode::kMaxContent,
- max_size_cache, nullptr);
+ max_size_cache, nullptr, nullptr);
bool values_might_be_saturated =
(*max_size_out)->MightBeSaturated() || content_size.MightBeSaturated();
if (!values_might_be_saturated) {
@@ -1737,7 +1634,7 @@ static LayoutUnit ComputeContentSize(
return result;
}
-MinMaxSizes NGInlineNode::ComputeMinMaxSizes(
+MinMaxSizesResult NGInlineNode::ComputeMinMaxSizes(
WritingMode container_writing_mode,
const MinMaxSizesInput& input,
const NGConstraintSpace* constraint_space) {
@@ -1749,16 +1646,17 @@ MinMaxSizes NGInlineNode::ComputeMinMaxSizes(
NGLineBreaker::MaxSizeCache max_size_cache;
MinMaxSizes sizes;
base::Optional<LayoutUnit> max_size;
- sizes.min_size = ComputeContentSize(*this, container_writing_mode, input,
- NGLineBreakerMode::kMinContent,
- &max_size_cache, &max_size);
+ bool depends_on_percentage_block_size = false;
+ sizes.min_size = ComputeContentSize(
+ *this, container_writing_mode, input, NGLineBreakerMode::kMinContent,
+ &max_size_cache, &max_size, &depends_on_percentage_block_size);
DCHECK(max_size.has_value());
sizes.max_size = *max_size;
// Negative text-indent can make min > max. Ensure min is the minimum size.
sizes.min_size = std::min(sizes.min_size, sizes.max_size);
- return sizes;
+ return {sizes, depends_on_percentage_block_size};
}
bool NGInlineNode::UseFirstLineStyle() const {
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.h b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.h
index 72a5dd5fa81..c14ef2b3644 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.h
@@ -17,7 +17,6 @@ namespace blink {
class NGBlockBreakToken;
class NGConstraintSpace;
-class NGDirtyLines;
class NGInlineChildLayoutContext;
class NGInlineNodeLegacy;
class NGLayoutResult;
@@ -47,16 +46,12 @@ class CORE_EXPORT NGInlineNode : public NGLayoutInputNode {
const NGBreakToken*,
NGInlineChildLayoutContext* context);
- // Find the container of reusable line boxes. Returns nullptr if there are no
- // reusable line boxes.
- const NGPaintFragment* ReusableLineBoxContainer(const NGConstraintSpace&);
-
// Computes the value of min-content and max-content for this anonymous block
// box. min-content is the inline size when lines wrap at every break
// opportunity, and max-content is when lines do not wrap at all.
- MinMaxSizes ComputeMinMaxSizes(WritingMode container_writing_mode,
- const MinMaxSizesInput&,
- const NGConstraintSpace* = nullptr);
+ MinMaxSizesResult ComputeMinMaxSizes(WritingMode container_writing_mode,
+ const MinMaxSizesInput&,
+ const NGConstraintSpace* = nullptr);
// Instruct to re-compute |PrepareLayout| on the next layout.
void InvalidatePrepareLayoutForTest() {
@@ -145,12 +140,10 @@ class CORE_EXPORT NGInlineNode : public NGLayoutInputNode {
// Prepare inline and text content for layout. Must be called before
// calling the Layout method.
void PrepareLayoutIfNeeded();
- void PrepareLayout(std::unique_ptr<NGInlineNodeData> previous_data,
- NGDirtyLines* dirty_lines);
+ void PrepareLayout(std::unique_ptr<NGInlineNodeData> previous_data);
void CollectInlines(NGInlineNodeData*,
- NGInlineNodeData* previous_data = nullptr,
- NGDirtyLines* dirty_lines = nullptr);
+ NGInlineNodeData* previous_data = nullptr);
void SegmentText(NGInlineNodeData*);
void SegmentScriptRuns(NGInlineNodeData*);
void SegmentFontOrientation(NGInlineNodeData*);
@@ -161,8 +154,6 @@ class CORE_EXPORT NGInlineNode : public NGLayoutInputNode {
void ShapeTextForFirstLineIfNeeded(NGInlineNodeData*);
void AssociateItemsWithInlines(NGInlineNodeData*);
- bool MarkLineBoxesDirty(LayoutBlockFlow*, const NGPaintFragment*);
-
NGInlineNodeData* MutableData() {
return To<LayoutBlockFlow>(box_)->GetNGInlineNodeData();
}
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node_test.cc b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node_test.cc
index 8d6cc679213..92ef98f42be 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node_test.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node_test.cc
@@ -49,8 +49,7 @@ class NGInlineNodeForTest : public NGInlineNode {
unsigned start = data->text_content.length();
data->text_content = data->text_content + text;
data->items.push_back(NGInlineItem(NGInlineItem::kText, start,
- start + text.length(), layout_object,
- /* is_first_for_node */ true));
+ start + text.length(), layout_object));
data->is_empty_inline_ = false;
}
@@ -58,9 +57,8 @@ class NGInlineNodeForTest : public NGInlineNode {
NGInlineNodeData* data = MutableData();
data->text_content = data->text_content + character;
unsigned end = data->text_content.length();
- data->items.push_back(NGInlineItem(NGInlineItem::kBidiControl, end - 1, end,
- nullptr,
- /* is_first_for_node */ true));
+ data->items.push_back(
+ NGInlineItem(NGInlineItem::kBidiControl, end - 1, end, nullptr));
data->is_bidi_enabled_ = true;
data->is_empty_inline_ = false;
}
@@ -80,12 +78,6 @@ class NGInlineNodeForTest : public NGInlineNode {
void CollectInlines() { NGInlineNode::CollectInlines(MutableData()); }
void ShapeText() { NGInlineNode::ShapeText(MutableData()); }
-
- bool MarkLineBoxesDirty() {
- LayoutBlockFlow* block_flow = GetLayoutBlockFlow();
- return NGInlineNode::MarkLineBoxesDirty(block_flow,
- block_flow->PaintFragment());
- }
};
class NGInlineNodeTest : public NGLayoutTest {
@@ -118,9 +110,12 @@ class NGInlineNodeTest : public NGLayoutTest {
}
MinMaxSizes ComputeMinMaxSizes(NGInlineNode node) {
- return node.ComputeMinMaxSizes(
- node.Style().GetWritingMode(),
- MinMaxSizesInput(/* percentage_resolution_block_size */ LayoutUnit()));
+ return node
+ .ComputeMinMaxSizes(
+ node.Style().GetWritingMode(),
+ MinMaxSizesInput(
+ /* percentage_resolution_block_size */ LayoutUnit()))
+ .sizes;
}
const String& GetText() const {
@@ -129,24 +124,6 @@ class NGInlineNodeTest : public NGLayoutTest {
return data->text_content;
}
- // Mark line boxes dirty and returns child paint fragments of
- // |layout_block_flow_|.
- Vector<NGPaintFragment*, 16> MarkLineBoxesDirty() const {
- // Attach new LayoutObjects if there were any, but do not run layout,
- // because running layout will re-create fragments.
- GetDocument().UpdateStyleAndLayoutTree();
-
- NGInlineNodeForTest node(layout_block_flow_);
- EXPECT_TRUE(node.MarkLineBoxesDirty());
-
- scoped_refptr<const NGPaintFragment> fragment =
- layout_block_flow_->PaintFragment();
- EXPECT_TRUE(fragment);
- Vector<NGPaintFragment*, 16> children;
- fragment->Children().ToList(&children);
- return children;
- }
-
Vector<NGInlineItem>& Items() {
NGInlineNodeData* data = layout_block_flow_->GetNGInlineNodeData();
CHECK(data);
@@ -163,26 +140,21 @@ class NGInlineNodeTest : public NGLayoutTest {
return end_offsets;
}
+ void TestFirstLineIsDirty(LayoutBlockFlow* block_flow, bool expected) {
+ const NGFragmentItems* items = block_flow->FragmentItems();
+ items->DirtyLinesFromNeedsLayout(block_flow);
+ const NGFragmentItem* end_reusable_item = items->EndOfReusableItems();
+ NGInlineCursor cursor(*items);
+ cursor.MoveToFirstLine();
+ EXPECT_EQ(cursor.Current().Item() == end_reusable_item, expected);
+ }
+
scoped_refptr<const ComputedStyle> style_;
LayoutNGBlockFlow* layout_block_flow_ = nullptr;
LayoutObject* layout_object_ = nullptr;
FontCachePurgePreventer purge_preventer_;
};
-class NodeParameterTest : public NGInlineNodeTest,
- public testing::WithParamInterface<const char*> {};
-
-INSTANTIATE_TEST_SUITE_P(
- NGInlineNodeTest,
- NodeParameterTest,
- testing::Values("text",
- "<span>span</span>",
- "<span>1234 12345678</span>",
- "<span style='display: inline-block'>box</span>",
- "<img>",
- "<div style='float: left'>float</div>",
- "<div style='position: absolute'>abs</div>"));
-
#define TEST_ITEM_TYPE_OFFSET(item, type, start, end) \
EXPECT_EQ(NGInlineItem::type, item.Type()); \
EXPECT_EQ(start, item.StartOffset()); \
@@ -663,10 +635,9 @@ TEST_P(StyleChangeTest, NeedsCollectInlinesOnStyle) {
EXPECT_FALSE(next->GetLayoutObject()->NeedsCollectInlines());
if (data.is_line_dirty &&
- RuntimeEnabledFeatures::LayoutNGLineCacheEnabled()) {
- layout_block_flow_ = ToLayoutNGBlockFlow(container->GetLayoutObject());
- auto lines = MarkLineBoxesDirty();
- EXPECT_EQ(*data.is_line_dirty, lines[0]->IsDirty());
+ RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()) {
+ TestFirstLineIsDirty(To<LayoutBlockFlow>(container->GetLayoutObject()),
+ *data.is_line_dirty);
}
ForceLayout(); // Ensure running layout does not crash.
@@ -1018,331 +989,6 @@ TEST_F(NGInlineNodeTest, SpaceRestoredByInsertingWord) {
EXPECT_EQ(String("before mid after"), GetText());
}
-// Test marking line boxes when inserting a span before the first child.
-TEST_P(NodeInsertTest, MarkLineBoxesDirtyOnInsert) {
- if (!RuntimeEnabledFeatures::LayoutNGLineCacheEnabled())
- return;
- SetupHtml("container", R"HTML(
- <style>
- .abspos { position: absolute; }
- .float { float: left; }
- </style>
- <div id=container style="font-size: 10px; width: 10ch">
- 12345678
- </div>
- )HTML");
-
- Node* insert = (*GetParam())(GetDocument());
- Element* container = GetElementById("container");
- container->insertBefore(insert, container->firstChild());
-
- auto lines = MarkLineBoxesDirty();
- EXPECT_TRUE(lines[0]->IsDirty());
-}
-
-// Test marking line boxes when appending a span.
-TEST_P(NodeInsertTest, MarkLineBoxesDirtyOnAppend) {
- if (!RuntimeEnabledFeatures::LayoutNGLineCacheEnabled())
- return;
- SetupHtml("container", R"HTML(
- <style>
- .abspos { position: absolute; }
- .float { float: left; }
- </style>
- <div id=container style="font-size: 10px; width: 10ch">
- 12345678
- </div>
- )HTML");
-
- Node* insert = (*GetParam())(GetDocument());
- layout_block_flow_->GetNode()->appendChild(insert);
-
- auto lines = MarkLineBoxesDirty();
- EXPECT_TRUE(lines[0]->IsDirty());
-}
-
-// Test marking line boxes when appending a span on 2nd line.
-TEST_P(NodeInsertTest, MarkLineBoxesDirtyOnAppend2) {
- if (!RuntimeEnabledFeatures::LayoutNGLineCacheEnabled())
- return;
- SetupHtml("container", R"HTML(
- <style>
- .abspos { position: absolute; }
- .float { float: left; }
- </style>
- <div id=container style="font-size: 10px; width: 10ch">
- 12345678
- 2234
- </div>
- )HTML");
-
- Node* insert = (*GetParam())(GetDocument());
- layout_block_flow_->GetNode()->appendChild(insert);
-
- auto lines = MarkLineBoxesDirty();
- EXPECT_FALSE(lines[0]->IsDirty());
- EXPECT_TRUE(lines[1]->IsDirty());
-}
-
-// Test marking line boxes when appending a span on 2nd line.
-TEST_P(NodeInsertTest, MarkLineBoxesDirtyOnAppendAfterBR) {
- if (!RuntimeEnabledFeatures::LayoutNGLineCacheEnabled())
- return;
- SetupHtml("container", R"HTML(
- <style>
- .abspos { position: absolute; }
- .float { float: left; }
- </style>
- <div id=container style="font-size: 10px; width: 10ch">
- <br>
- <br>
- </div>
- )HTML");
-
- Node* insert = (*GetParam())(GetDocument());
- layout_block_flow_->GetNode()->appendChild(insert);
-
- auto lines = MarkLineBoxesDirty();
- EXPECT_FALSE(lines[0]->IsDirty());
- EXPECT_TRUE(lines[1]->IsDirty());
-}
-
-// Test marking line boxes when removing a span.
-TEST_F(NGInlineNodeTest, MarkLineBoxesDirtyOnRemove) {
- if (!RuntimeEnabledFeatures::LayoutNGLineCacheEnabled())
- return;
- SetupHtml("container", R"HTML(
- <div id=container style="font-size: 10px; width: 10ch">
- 1234<span id=t>5678</span>
- </div>
- )HTML");
-
- Element* span = GetElementById("t");
- span->remove();
-
- auto lines = MarkLineBoxesDirty();
- EXPECT_TRUE(lines[0]->IsDirty());
-}
-
-// Test marking line boxes when removing a span.
-TEST_P(NodeParameterTest, MarkLineBoxesDirtyOnRemoveFirst) {
- if (!RuntimeEnabledFeatures::LayoutNGLineCacheEnabled())
- return;
- SetupHtml("container", String(R"HTML(
- <div id=container style="font-size: 10px; width: 10ch">)HTML") +
- GetParam() + R"HTML(<span>after</span>
- </div>
- )HTML");
-
- Element* container = GetElementById("container");
- Node* node = container->firstChild();
- ASSERT_TRUE(node);
- node->remove();
-
- auto lines = MarkLineBoxesDirty();
- EXPECT_TRUE(lines[0]->IsDirty());
-}
-
-// Test marking line boxes when removing a span on 2nd line.
-TEST_F(NGInlineNodeTest, MarkLineBoxesDirtyOnRemove2) {
- if (!RuntimeEnabledFeatures::LayoutNGLineCacheEnabled())
- return;
- SetupHtml("container", R"HTML(
- <div id=container style="font-size: 10px; width: 10ch">
- 12345678
- 2234<span id=t>5678 3334</span>
- </div>
- )HTML");
-
- Element* span = GetElementById("t");
- span->remove();
-
- auto lines = MarkLineBoxesDirty();
- EXPECT_FALSE(lines[0]->IsDirty());
- EXPECT_TRUE(lines[1]->IsDirty());
-}
-
-// Test marking line boxes when removing a text node on 2nd line.
-TEST_P(NodeParameterTest, MarkLineBoxesDirtyOnRemoveAfterBR) {
- if (!RuntimeEnabledFeatures::LayoutNGLineCacheEnabled())
- return;
- SetupHtml("container", String(R"HTML(
- <div id=container style="font-size: 10px; width: 10ch">
- line 1
- <br>)HTML") + GetParam() +
- "</div>");
-
- Element* container = GetElementById("container");
- Node* node = container->lastChild();
- ASSERT_TRUE(node);
- node->remove();
-
- auto lines = MarkLineBoxesDirty();
- EXPECT_TRUE(lines[0]->IsDirty());
- // Currently, only the first dirty line is marked.
- EXPECT_FALSE(lines[1]->IsDirty());
-
- ForceLayout(); // Ensure running layout does not crash.
-}
-
-TEST_F(NGInlineNodeTest, MarkLineBoxesDirtyOnEndSpaceCollapsed) {
- if (!RuntimeEnabledFeatures::LayoutNGLineCacheEnabled())
- return;
- SetupHtml("container", R"HTML(
- <style>
- div {
- font-size: 10px;
- width: 8ch;
- }
- #empty {
- background: yellow; /* ensure fragment is created */
- }
- #target {
- display: inline-block;
- }
- </style>
- <div id=container>
- 1234567890
- 1234567890
- <span id=empty> </span>
- <span id=target></span></div>
- )HTML");
-
- // Removing #target makes the spaces before it to be collapsed.
- Element* target = GetElementById("target");
- target->remove();
-
- auto lines = MarkLineBoxesDirty();
- EXPECT_FALSE(lines[0]->IsDirty());
- EXPECT_TRUE(lines[1]->IsDirty());
-
- ForceLayout(); // Ensure running layout does not crash.
-}
-
-// Test marking line boxes when the first span has NeedsLayout. The span is
-// culled.
-TEST_F(NGInlineNodeTest, MarkLineBoxesDirtyOnNeedsLayoutFirst) {
- if (!RuntimeEnabledFeatures::LayoutNGLineCacheEnabled())
- return;
- SetupHtml("container", R"HTML(
- <div id=container style="font-size: 10px; width: 10ch">
- <span id=t>1234</span>5678
- </div>
- )HTML");
-
- LayoutObject* span = GetLayoutObjectByElementId("t");
- span->SetNeedsLayout("");
-
- auto lines = MarkLineBoxesDirty();
- EXPECT_TRUE(lines[0]->IsDirty());
-}
-
-// Test marking line boxes when the first span has NeedsLayout. The span has a
-// box fragment.
-TEST_F(NGInlineNodeTest, MarkLineBoxesDirtyOnNeedsLayoutFirstWithBox) {
- if (!RuntimeEnabledFeatures::LayoutNGLineCacheEnabled())
- return;
- SetupHtml("container", R"HTML(
- <div id=container style="font-size: 10px; width: 10ch">
- <span id=t style="background: blue">1234</span>5678
- </div>
- )HTML");
-
- LayoutObject* span = GetLayoutObjectByElementId("t");
- span->SetNeedsLayout("");
-
- auto lines = MarkLineBoxesDirty();
- EXPECT_TRUE(lines[0]->IsDirty());
-}
-
-// Test marking line boxes when a span has NeedsLayout. The span is culled.
-TEST_F(NGInlineNodeTest, MarkLineBoxesDirtyOnNeedsLayout) {
- if (!RuntimeEnabledFeatures::LayoutNGLineCacheEnabled())
- return;
- SetupHtml("container", R"HTML(
- <div id=container style="font-size: 10px; width: 10ch">
- 12345678
- 2234<span id=t>5678 3334</span>
- </div>
- )HTML");
-
- LayoutObject* span = GetLayoutObjectByElementId("t");
- span->SetNeedsLayout("");
-
- auto lines = MarkLineBoxesDirty();
- EXPECT_FALSE(lines[0]->IsDirty());
- EXPECT_TRUE(lines[1]->IsDirty());
-}
-
-// Test marking line boxes when a span has NeedsLayout. The span has a box
-// fragment.
-TEST_F(NGInlineNodeTest, MarkLineBoxesDirtyOnNeedsLayoutWithBox) {
- if (!RuntimeEnabledFeatures::LayoutNGLineCacheEnabled())
- return;
- SetupHtml("container", R"HTML(
- <div id=container style="font-size: 10px; width: 10ch">
- 12345678
- 2234<span id=t style="background: blue">5678 3334</span>
- </div>
- )HTML");
-
- LayoutObject* span = GetLayoutObjectByElementId("t");
- span->SetNeedsLayout("");
-
- auto lines = MarkLineBoxesDirty();
- EXPECT_FALSE(lines[0]->IsDirty());
- EXPECT_TRUE(lines[1]->IsDirty());
-}
-
-// Test marking line boxes when a span inside a span has NeedsLayout.
-// The parent span has a box fragment, and wraps, so that its fragment
-// is seen earlier in pre-order DFS.
-TEST_F(NGInlineNodeTest, MarkLineBoxesDirtyOnChildOfWrappedBox) {
- if (!RuntimeEnabledFeatures::LayoutNGLineCacheEnabled())
- return;
- SetupHtml("container", R"HTML(
- <div id=container style="font-size: 10px">
- <span style="background: yellow">
- <span id=t>target</span>
- <br>
- 12345678
- </span>
- </div>
- )HTML");
-
- LayoutObject* span = GetLayoutObjectByElementId("t");
- span->SetNeedsLayout("");
-
- auto lines = MarkLineBoxesDirty();
- EXPECT_TRUE(lines[0]->IsDirty());
-}
-
-// Test marking line boxes when a span has NeedsLayout. The span has a box
-// fragment.
-TEST_F(NGInlineNodeTest, MarkLineBoxesDirtyInInlineBlock) {
- if (!RuntimeEnabledFeatures::LayoutNGLineCacheEnabled())
- return;
- SetupHtml("container", R"HTML(
- <div id=container style="display: inline-block; font-size: 10px">
- 12345678<br>
- 12345678<br>
- </div>
- )HTML");
-
- Element* container = GetElementById("container");
- container->appendChild(GetDocument().createTextNode("append"));
-
- // Inline block with auto-size calls |ComputeMinMaxSize|, which may call
- // |CollectInlines|. Emulate it to ensure it does not let tests to fail.
- GetDocument().UpdateStyleAndLayoutTree();
- ComputeMinMaxSizes(NGInlineNode(layout_block_flow_));
-
- auto lines = MarkLineBoxesDirty();
- // TODO(kojii): Ideally, 0 should be false, or even 1 as well.
- EXPECT_TRUE(lines[0]->IsDirty());
- EXPECT_TRUE(lines[1]->IsDirty());
-}
-
TEST_F(NGInlineNodeTest, RemoveInlineNodeDataIfBlockBecomesEmpty1) {
SetupHtml("container", "<div id=container><b id=remove><i>foo</i></b></div>");
ASSERT_TRUE(layout_block_flow_->HasNGInlineNodeData());
@@ -1389,9 +1035,9 @@ TEST_F(NGInlineNodeTest, ClearFirstInlineFragmentOnSplitFlow) {
// Keep the text fragment to compare later.
Element* inner_span = GetElementById("inner_span");
Node* text = inner_span->firstChild();
- NGInlineCursor text_fragment_before_split;
- text_fragment_before_split.MoveTo(*text->GetLayoutObject());
- EXPECT_TRUE(text_fragment_before_split);
+ scoped_refptr<NGPaintFragment> text_fragment_before_split =
+ text->GetLayoutObject()->FirstInlineFragment();
+ EXPECT_NE(text_fragment_before_split.get(), nullptr);
// Append <div> to <span>. causing SplitFlow().
Element* outer_span = GetElementById("outer_span");
@@ -1407,21 +1053,23 @@ TEST_F(NGInlineNodeTest, ClearFirstInlineFragmentOnSplitFlow) {
// destroyed, and should not be accessible.
GetDocument().UpdateStyleAndLayoutTree();
EXPECT_FALSE(text->GetLayoutObject()->IsInLayoutNGInlineFormattingContext());
+ scoped_refptr<NGPaintFragment> text_fragment_before_layout =
+ text->GetLayoutObject()->FirstInlineFragment();
+ EXPECT_EQ(text_fragment_before_layout, nullptr);
// Update layout. There should be a different instance of the text fragment.
UpdateAllLifecyclePhasesForTest();
- NGInlineCursor text_fragment_after_layout;
- text_fragment_after_layout.MoveTo(*text->GetLayoutObject());
- EXPECT_NE(text_fragment_before_split.Current(),
- text_fragment_after_layout.Current());
+ scoped_refptr<NGPaintFragment> text_fragment_after_layout =
+ text->GetLayoutObject()->FirstInlineFragment();
+ EXPECT_NE(text_fragment_before_split, text_fragment_after_layout);
// Check it is the one owned by the new root inline formatting context.
LayoutBlock* anonymous_block =
inner_span->GetLayoutObject()->ContainingBlock();
EXPECT_TRUE(anonymous_block->IsAnonymous());
- EXPECT_EQ(anonymous_block, text_fragment_after_layout.Current()
- .GetLayoutObject()
- ->ContainingBlock());
+ const NGPaintFragment* block_fragment = anonymous_block->PaintFragment();
+ const NGPaintFragment* line_box_fragment = block_fragment->FirstChild();
+ EXPECT_EQ(line_box_fragment->FirstChild(), text_fragment_after_layout);
}
TEST_F(NGInlineNodeTest, AddChildToSVGRoot) {
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_line_box_fragment_builder.cc b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_line_box_fragment_builder.cc
index acddeab0eaf..3ec775afee2 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_line_box_fragment_builder.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_line_box_fragment_builder.cc
@@ -6,8 +6,10 @@
#include "third_party/blink/renderer/core/layout/ng/exclusions/ng_exclusion_space.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_break_token.h"
+#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_item_result.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_physical_line_box_fragment.h"
+#include "third_party/blink/renderer/core/layout/ng/inline/ng_text_fragment_builder.h"
#include "third_party/blink/renderer/core/layout/ng/ng_fragment.h"
#include "third_party/blink/renderer/core/layout/ng/ng_layout_result.h"
#include "third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h"
@@ -38,6 +40,26 @@ void NGLineBoxFragmentBuilder::SetIsEmptyLineBox() {
line_box_type_ = NGPhysicalLineBoxFragment::kEmptyLineBox;
}
+void NGLineBoxFragmentBuilder::ChildList::CreateTextFragments(
+ WritingMode writing_mode,
+ const String& text_content) {
+ NGTextFragmentBuilder text_builder(writing_mode);
+ for (auto& child : *this) {
+ if (NGInlineItemResult* item_result = child.item_result) {
+ DCHECK(item_result->item);
+ const NGInlineItem& item = *item_result->item;
+ DCHECK(item.Type() == NGInlineItem::kText ||
+ item.Type() == NGInlineItem::kControl);
+ DCHECK(item.TextType() == NGTextType::kNormal ||
+ item.TextType() == NGTextType::kSymbolMarker);
+ text_builder.SetItem(text_content, item_result,
+ child.rect.size.block_size);
+ DCHECK(!child.fragment);
+ child.fragment = text_builder.ToTextFragment();
+ }
+ }
+}
+
NGLineBoxFragmentBuilder::Child*
NGLineBoxFragmentBuilder::ChildList::FirstInFlowChild() {
for (auto& child : *this) {
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_line_box_fragment_builder.h b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_line_box_fragment_builder.h
index 93550d8b80f..8c3dc2cd273 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_line_box_fragment_builder.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_line_box_fragment_builder.h
@@ -21,6 +21,7 @@ namespace blink {
class ComputedStyle;
class NGInlineBreakToken;
+struct NGInlineItemResult;
class CORE_EXPORT NGLineBoxFragmentBuilder final
: public NGContainerFragmentBuilder {
@@ -75,9 +76,12 @@ class CORE_EXPORT NGLineBoxFragmentBuilder final
struct Child {
DISALLOW_NEW();
+ scoped_refptr<NGFragmentItem> fragment_item;
scoped_refptr<const NGLayoutResult> layout_result;
scoped_refptr<const NGPhysicalTextFragment> fragment;
const NGInlineItem* inline_item = nullptr;
+ // |NGInlineItemResult| to create a text fragment from.
+ NGInlineItemResult* item_result = nullptr;
LayoutObject* out_of_flow_positioned_box = nullptr;
LayoutObject* unpositioned_float = nullptr;
// The offset of the border box, initially in this child coordinate system.
@@ -134,7 +138,16 @@ class CORE_EXPORT NGLineBoxFragmentBuilder final
inline_size(inline_size),
children_count(children_count),
bidi_level(bidi_level) {}
- // Create an in-flow |NGPhysicalTextFragment|.
+ // Create an in-flow text fragment.
+ Child(NGInlineItemResult* item_result,
+ LayoutUnit block_offset,
+ LayoutUnit inline_size,
+ LayoutUnit text_height,
+ UBiDiLevel bidi_level)
+ : item_result(item_result),
+ rect(LayoutUnit(), block_offset, LayoutUnit(), text_height),
+ inline_size(inline_size),
+ bidi_level(bidi_level) {}
Child(scoped_refptr<const NGPhysicalTextFragment> fragment,
LogicalOffset offset,
LayoutUnit inline_size,
@@ -170,9 +183,12 @@ class CORE_EXPORT NGLineBoxFragmentBuilder final
bidi_level(bidi_level) {}
bool HasInFlowFragment() const {
+ if (fragment_item)
+ return true;
if (fragment)
return true;
-
+ if (item_result)
+ return true;
if (layout_result && !layout_result->PhysicalFragment().IsFloating())
return true;
@@ -280,6 +296,10 @@ class CORE_EXPORT NGLineBoxFragmentBuilder final
void MoveInBlockDirection(LayoutUnit);
void MoveInBlockDirection(LayoutUnit, unsigned start, unsigned end);
+ // Create |NGPhysicalTextFragment| for all text children.
+ void CreateTextFragments(WritingMode writing_mode,
+ const String& text_content);
+
private:
void WillInsertChild(unsigned index);
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.cc b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.cc
index 494d7ae3167..1964973a226 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.cc
@@ -253,10 +253,13 @@ inline bool NGLineBreaker::HandleOverflowIfNeeded(NGLineInfo* line_info) {
return false;
}
-void NGLineBreaker::SetMaxSizeCache(MaxSizeCache* max_size_cache) {
+void NGLineBreaker::SetIntrinsicSizeOutputs(
+ MaxSizeCache* max_size_cache,
+ bool* depends_on_percentage_block_size_out) {
DCHECK_NE(mode_, NGLineBreakerMode::kContent);
DCHECK(max_size_cache);
max_size_cache_ = max_size_cache;
+ depends_on_percentage_block_size_out_ = depends_on_percentage_block_size_out;
}
// Compute the base direction for bidi algorithm for this line.
@@ -1176,9 +1179,10 @@ void NGLineBreaker::ComputeTrailingCollapsibleSpace(NGLineInfo* line_info) {
return;
}
if (item.Type() == NGInlineItem::kControl) {
- UChar character = text[item.StartOffset()];
- if (character == kNewlineCharacter)
+ if (item.TextType() == NGTextType::kForcedLineBreak) {
+ DCHECK_EQ(text[item.StartOffset()], kNewlineCharacter);
continue;
+ }
trailing_whitespace_ = WhitespaceState::kPreserved;
trailing_collapsible_space_.reset();
return;
@@ -1194,39 +1198,42 @@ void NGLineBreaker::ComputeTrailingCollapsibleSpace(NGLineInfo* line_info) {
void NGLineBreaker::HandleControlItem(const NGInlineItem& item,
NGLineInfo* line_info) {
DCHECK_GE(item.Length(), 1u);
- UChar character = Text()[item.StartOffset()];
- switch (character) {
- case kNewlineCharacter: {
- // Check overflow, because the last item may have overflowed.
- if (HandleOverflowIfNeeded(line_info))
- return;
+ if (item.TextType() == NGTextType::kForcedLineBreak) {
+ DCHECK_EQ(Text()[item.StartOffset()], kNewlineCharacter);
- NGInlineItemResult* item_result = AddItem(item, line_info);
- item_result->should_create_line_box = true;
- item_result->has_only_trailing_spaces = true;
- MoveToNextOf(item);
+ // Check overflow, because the last item may have overflowed.
+ if (HandleOverflowIfNeeded(line_info))
+ return;
- // Include following close tags. The difference is visible when they have
- // margin/border/padding.
- //
- // This is not a defined behavior, but legacy/WebKit do this for preserved
- // newlines and <br>s. Gecko does this only for preserved newlines (but
- // not for <br>s).
- const Vector<NGInlineItem>& items = Items();
- while (item_index_ < items.size()) {
- const NGInlineItem& next_item = items[item_index_];
- if (next_item.Type() == NGInlineItem::kCloseTag) {
- HandleCloseTag(next_item, line_info);
- continue;
- }
- break;
- }
+ NGInlineItemResult* item_result = AddItem(item, line_info);
+ item_result->should_create_line_box = true;
+ item_result->has_only_trailing_spaces = true;
+ MoveToNextOf(item);
- is_after_forced_break_ = true;
- line_info->SetIsLastLine(true);
- state_ = LineBreakState::kDone;
- return;
+ // Include following close tags. The difference is visible when they have
+ // margin/border/padding.
+ //
+ // This is not a defined behavior, but legacy/WebKit do this for preserved
+ // newlines and <br>s. Gecko does this only for preserved newlines (but
+ // not for <br>s).
+ const Vector<NGInlineItem>& items = Items();
+ while (item_index_ < items.size()) {
+ const NGInlineItem& next_item = items[item_index_];
+ if (next_item.Type() == NGInlineItem::kCloseTag) {
+ HandleCloseTag(next_item, line_info);
+ continue;
+ }
+ break;
}
+
+ is_after_forced_break_ = true;
+ line_info->SetIsLastLine(true);
+ state_ = LineBreakState::kDone;
+ return;
+ }
+ DCHECK_EQ(item.TextType(), NGTextType::kFlowControl);
+ UChar character = Text()[item.StartOffset()];
+ switch (character) {
case kTabulationCharacter: {
DCHECK(item.Style());
const ComputedStyle& style = *item.Style();
@@ -1371,18 +1378,22 @@ void NGLineBreaker::HandleAtomicInline(
DCHECK(mode_ == NGLineBreakerMode::kMinContent || !max_size_cache_);
NGBlockNode child(ToLayoutBox(item.GetLayoutObject()));
MinMaxSizesInput input(percentage_resolution_block_size_for_min_max);
- MinMaxSizes sizes =
+ MinMaxSizesResult result =
ComputeMinAndMaxContentContribution(node_.Style(), child, input);
if (mode_ == NGLineBreakerMode::kMinContent) {
- item_result->inline_size = sizes.min_size + inline_margins;
+ item_result->inline_size = result.sizes.min_size + inline_margins;
+ if (depends_on_percentage_block_size_out_) {
+ *depends_on_percentage_block_size_out_ |=
+ result.depends_on_percentage_block_size;
+ }
if (max_size_cache_) {
if (max_size_cache_->IsEmpty())
max_size_cache_->resize(Items().size());
unsigned item_index = &item - Items().begin();
- (*max_size_cache_)[item_index] = sizes.max_size + inline_margins;
+ (*max_size_cache_)[item_index] = result.sizes.max_size + inline_margins;
}
} else {
- item_result->inline_size = sizes.max_size + inline_margins;
+ item_result->inline_size = result.sizes.max_size + inline_margins;
}
}
@@ -1808,9 +1819,8 @@ void NGLineBreaker::RewindOverflow(unsigned new_end, NGLineInfo* line_info) {
if (ComputedStyle::AutoWrap(white_space) &&
white_space != EWhiteSpace::kBreakSpaces &&
IsBreakableSpace(text[item_result.start_offset])) {
- // If more items left and all characters are trailable spaces, check
- // the next item.
- if (item_result.shape_result && index < item_results.size() - 1 &&
+ // If all characters are trailable spaces, check the next item.
+ if (item_result.shape_result &&
IsAllBreakableSpaces(text, item_result.start_offset + 1,
item_result.end_offset)) {
continue;
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.h b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.h
index ac8685caad5..05481028298 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.h
@@ -67,7 +67,8 @@ class CORE_EXPORT NGLineBreaker {
// information that can help computing |kMaxContent|. It is recommended to set
// this when computing both |kMinContent| and |kMaxContent|.
using MaxSizeCache = Vector<LayoutUnit, 64>;
- void SetMaxSizeCache(MaxSizeCache* max_size_cache);
+ void SetIntrinsicSizeOutputs(MaxSizeCache* max_size_cache,
+ bool* depends_on_percentage_block_size_out);
// Compute NGInlineItemResult for an open tag item.
// Returns true if this item has edge and may have non-zero inline size.
@@ -294,6 +295,8 @@ class CORE_EXPORT NGLineBreaker {
// Cache for computing |MinMaxSize|. See |MaxSizeCache|.
MaxSizeCache* max_size_cache_ = nullptr;
+ bool* depends_on_percentage_block_size_out_ = nullptr;
+
// Keep the last item |HandleTextForFastMinContent()| has handled. This is
// used to fallback the last word to |HandleText()|.
const NGInlineItem* fast_min_content_item_ = nullptr;
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker_test.cc b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker_test.cc
index 4e53d79afa3..38160e6e800 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker_test.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker_test.cc
@@ -535,11 +535,13 @@ TEST_F(NGLineBreakerTest, MinMaxWithTrailingSpaces) {
<div id=container>12345 6789 </div>
)HTML");
- auto size = node.ComputeMinMaxSizes(
- WritingMode::kHorizontalTb,
- MinMaxSizesInput(/* percentage_resolution_block_size */ (LayoutUnit())));
- EXPECT_EQ(size.min_size, LayoutUnit(60));
- EXPECT_EQ(size.max_size, LayoutUnit(110));
+ auto sizes = node.ComputeMinMaxSizes(
+ WritingMode::kHorizontalTb,
+ MinMaxSizesInput(/* percentage_resolution_block_size */ (
+ LayoutUnit())))
+ .sizes;
+ EXPECT_EQ(sizes.min_size, LayoutUnit(60));
+ EXPECT_EQ(sizes.max_size, LayoutUnit(110));
}
TEST_F(NGLineBreakerTest, TableCellWidthCalculationQuirkOutOfFlow) {
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_offset_mapping.cc b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_offset_mapping.cc
index a17617b0d31..5fb2fef7142 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_offset_mapping.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_offset_mapping.cc
@@ -138,7 +138,7 @@ const Node& NGOffsetMappingUnit::GetOwner() const {
bool NGOffsetMappingUnit::Concatenate(const NGOffsetMappingUnit& other) {
if (layout_object_ != other.layout_object_)
return false;
- if (type_ != other.type_ || type_ == NGOffsetMappingUnitType::kExpanded)
+ if (type_ != other.type_)
return false;
if (dom_end_ != other.dom_start_)
return false;
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_offset_mapping.h b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_offset_mapping.h
index 13b2eb52bbb..d5869ad6ea9 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_offset_mapping.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_offset_mapping.h
@@ -21,7 +21,7 @@ namespace blink {
class LayoutBlockFlow;
class LayoutObject;
-enum class NGOffsetMappingUnitType { kIdentity, kCollapsed, kExpanded };
+enum class NGOffsetMappingUnitType { kIdentity, kCollapsed };
// An NGOffsetMappingUnit indicates a "simple" offset mapping between dom offset
// range [dom_start, dom_end] on node |owner| and text content offset range
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_offset_mapping_test.cc b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_offset_mapping_test.cc
index 3e2c8f22e7d..da14a44e464 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_offset_mapping_test.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_offset_mapping_test.cc
@@ -92,7 +92,6 @@ class NGOffsetMappingTest : public NGLayoutTest {
protected:
static const auto kCollapsed = NGOffsetMappingUnitType::kCollapsed;
static const auto kIdentity = NGOffsetMappingUnitType::kIdentity;
- static const auto kExpanded = NGOffsetMappingUnitType::kExpanded;
void SetUp() override {
NGLayoutTest::SetUp();
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_physical_text_fragment.cc b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_physical_text_fragment.cc
index a15a5429402..f7993f84dd7 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_physical_text_fragment.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_physical_text_fragment.cc
@@ -44,7 +44,7 @@ NGPhysicalTextFragment::NGPhysicalTextFragment(
? PhysicalSize{shape_result->SnappedWidth(), source.Size().height}
: PhysicalSize{source.Size().width, shape_result->SnappedWidth()},
kFragmentText,
- source.TextType()),
+ static_cast<unsigned>(source.TextType())),
text_(source.text_),
text_offset_(start_offset, end_offset),
shape_result_(std::move(shape_result)) {
@@ -52,31 +52,36 @@ NGPhysicalTextFragment::NGPhysicalTextFragment(
DCHECK_LE(text_offset_.end, source.EndOffset());
DCHECK(shape_result_ || IsFlowControl()) << *this;
base_or_resolved_direction_ = source.base_or_resolved_direction_;
- is_generated_text_or_math_fraction_ =
- source.is_generated_text_or_math_fraction_;
ink_overflow_computed_ = false;
- is_first_for_node_ = source.is_first_for_node_;
}
NGPhysicalTextFragment::NGPhysicalTextFragment(NGTextFragmentBuilder* builder)
- : NGPhysicalFragment(builder, kFragmentText, builder->text_type_),
+ : NGPhysicalFragment(builder,
+ kFragmentText,
+ static_cast<unsigned>(builder->text_type_)),
text_(builder->text_),
text_offset_({builder->start_offset_, builder->end_offset_}),
shape_result_(std::move(builder->shape_result_)) {
DCHECK(shape_result_ || IsFlowControl()) << *this;
base_or_resolved_direction_ =
static_cast<unsigned>(builder->ResolvedDirection());
- is_generated_text_or_math_fraction_ = builder->IsGeneratedText();
ink_overflow_computed_ = false;
- is_first_for_node_ = builder->is_first_for_node_;
+}
+
+bool NGPhysicalTextFragment::IsGeneratedText() const {
+ if (UNLIKELY(TextType() == NGTextType::kLayoutGenerated))
+ return true;
+ return GetLayoutObject()->IsStyleGenerated();
}
LayoutUnit NGPhysicalTextFragment::InlinePositionForOffset(
unsigned offset,
LayoutUnit (*round_function)(float),
AdjustMidCluster adjust_mid_cluster) const {
- return NGFragmentItem(*this).InlinePositionForOffset(
- Text(), offset, round_function, adjust_mid_cluster);
+ scoped_refptr<NGFragmentItem> item =
+ base::MakeRefCounted<NGFragmentItem>(*this);
+ return item->InlinePositionForOffset(Text(), offset, round_function,
+ adjust_mid_cluster);
}
// TODO(yosin): We should move |NGFragmentItem::InlinePositionForOffset" to
@@ -120,14 +125,17 @@ LayoutUnit NGFragmentItem::InlinePositionForOffset(StringView text,
LayoutUnit NGPhysicalTextFragment::InlinePositionForOffset(
unsigned offset) const {
- return NGFragmentItem(*this).InlinePositionForOffset(Text(), offset);
+ scoped_refptr<NGFragmentItem> item =
+ base::MakeRefCounted<NGFragmentItem>(*this);
+ return item->InlinePositionForOffset(Text(), offset);
}
std::pair<LayoutUnit, LayoutUnit>
NGPhysicalTextFragment::LineLeftAndRightForOffsets(unsigned start_offset,
unsigned end_offset) const {
- return NGFragmentItem(*this).LineLeftAndRightForOffsets(Text(), start_offset,
- end_offset);
+ scoped_refptr<NGFragmentItem> item =
+ base::MakeRefCounted<NGFragmentItem>(*this);
+ return item->LineLeftAndRightForOffsets(Text(), start_offset, end_offset);
}
// TODO(yosin): We should move |NGFragmentItem::InlinePositionForOffset" to
@@ -154,7 +162,9 @@ std::pair<LayoutUnit, LayoutUnit> NGFragmentItem::LineLeftAndRightForOffsets(
PhysicalRect NGPhysicalTextFragment::LocalRect(unsigned start_offset,
unsigned end_offset) const {
- return NGFragmentItem(*this).LocalRect(Text(), start_offset, end_offset);
+ scoped_refptr<NGFragmentItem> item =
+ base::MakeRefCounted<NGFragmentItem>(*this);
+ return item->LocalRect(Text(), start_offset, end_offset);
}
// TODO(yosin): We should move |NGFragmentItem::InlinePositionForOffset" to
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_physical_text_fragment.h b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_physical_text_fragment.h
index dbd1bae97af..dee9056d093 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_physical_text_fragment.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_physical_text_fragment.h
@@ -7,6 +7,7 @@
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_text_offset.h"
+#include "third_party/blink/renderer/core/layout/ng/inline/ng_text_type.h"
#include "third_party/blink/renderer/core/layout/ng/ng_ink_overflow.h"
#include "third_party/blink/renderer/core/layout/ng/ng_physical_fragment.h"
#include "third_party/blink/renderer/platform/fonts/ng_text_fragment_paint_info.h"
@@ -26,23 +27,6 @@ enum class AdjustMidCluster;
class CORE_EXPORT NGPhysicalTextFragment final : public NGPhysicalFragment {
public:
- enum NGTextType {
- // |text_| holds |NGNodeInlineData::text_content_|.
- kNormalText,
- kForcedLineBreak,
- // Flow controls are not to be painted. In particular, a tabulation
- // character and a soft-wrap opportunity.
- kFlowControl,
- kSymbolMarker,
- // |text_| holds generated contents instead of |text_content_| in
- // |NGNodeInlineData|, e.g. hyphen, and ellipsis.
- // Note: Contents generated by CSS pseudo element, e.g. ::before, ::after,
- // are not classified to this. See IsGeneratedText() for them.
- kGeneratedText,
- // When adding new values, make sure the bit size of |sub_type_| is large
- // enough to store.
- };
-
NGPhysicalTextFragment(NGTextFragmentBuilder*);
using PassKey = util::PassKey<NGPhysicalTextFragment>;
@@ -56,20 +40,24 @@ class CORE_EXPORT NGPhysicalTextFragment final : public NGPhysicalFragment {
NGTextType TextType() const { return static_cast<NGTextType>(sub_type_); }
// Returns true if the text is generated (from, e.g., list marker,
// pseudo-element, ...) instead of from a DOM text node.
- bool IsGeneratedText() const { return is_generated_text_or_math_fraction_; }
+ bool IsGeneratedText() const;
// True if this is a forced line break.
- bool IsLineBreak() const { return TextType() == kForcedLineBreak; }
+ bool IsLineBreak() const {
+ return TextType() == NGTextType::kForcedLineBreak;
+ }
// True if this is not for painting; i.e., a forced line break, a tabulation,
// or a soft-wrap opportunity.
bool IsFlowControl() const {
- return IsLineBreak() || TextType() == kFlowControl;
+ return IsLineBreak() || TextType() == NGTextType::kFlowControl;
}
// True if this is an ellpisis generated by `text-overflow: ellipsis`.
bool IsEllipsis() const {
return StyleVariant() == NGStyleVariant::kEllipsis;
}
- bool IsSymbolMarker() const { return TextType() == kSymbolMarker; }
+ bool IsSymbolMarker() const {
+ return TextType() == NGTextType::kSymbolMarker;
+ }
const String& TextContent() const { return text_; }
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_physical_text_fragment_test.cc b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_physical_text_fragment_test.cc
index ebb2a5abd83..74072b46236 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_physical_text_fragment_test.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_physical_text_fragment_test.cc
@@ -190,17 +190,17 @@ TEST_F(NGPhysicalTextFragmentTest, Ellipsis) {
const NGPhysicalTextFragment& truncated = *text_fragments[1];
const NGPhysicalTextFragment& ellipsis = *text_fragments[2];
- EXPECT_EQ(NGPhysicalTextFragment::kNormalText, hidden.TextType());
+ EXPECT_EQ(NGTextType::kNormal, hidden.TextType());
EXPECT_FALSE(hidden.IsGeneratedText());
EXPECT_TRUE(hidden.IsHiddenForPaint());
EXPECT_EQ(u8"abcdef", GetText(hidden));
- EXPECT_EQ(NGPhysicalTextFragment::kNormalText, truncated.TextType());
+ EXPECT_EQ(NGTextType::kNormal, truncated.TextType());
EXPECT_FALSE(truncated.IsGeneratedText());
EXPECT_FALSE(truncated.IsHiddenForPaint());
EXPECT_EQ(u8"abc", GetText(truncated));
- EXPECT_EQ(NGPhysicalTextFragment::kGeneratedText, ellipsis.TextType());
+ EXPECT_EQ(NGTextType::kLayoutGenerated, ellipsis.TextType());
EXPECT_TRUE(ellipsis.IsGeneratedText());
EXPECT_FALSE(ellipsis.IsHiddenForPaint());
EXPECT_EQ(u8"\u2026", GetText(ellipsis));
@@ -242,15 +242,15 @@ TEST_F(NGPhysicalTextFragmentTest, SoftHyphen) {
const NGPhysicalTextFragment& abc = *text_fragments[0];
const NGPhysicalTextFragment& shy = *text_fragments[1];
const NGPhysicalTextFragment& def = *text_fragments[2];
- EXPECT_EQ(NGPhysicalTextFragment::kNormalText, abc.TextType());
+ EXPECT_EQ(NGTextType::kNormal, abc.TextType());
// Note: ShapeResult::RunInfo.width_ == 0 for U+00AD
EXPECT_EQ(u8"abc\u00AD", GetText(abc));
- EXPECT_EQ(NGPhysicalTextFragment::kGeneratedText, shy.TextType());
- // Note: |ComputedStyle::HypenString()| returns "-" or U+2010 based on
+ EXPECT_EQ(NGTextType::kLayoutGenerated, shy.TextType());
+ // Note: |ComputedStyle::HyphenString()| returns "-" or U+2010 based on
// glyph availability.
if (GetText(shy) != "-")
EXPECT_EQ(u8"\u2010", GetText(shy));
- EXPECT_EQ(NGPhysicalTextFragment::kNormalText, def.TextType());
+ EXPECT_EQ(NGTextType::kNormal, def.TextType());
}
TEST_F(NGPhysicalTextFragmentTest, QuotationMarksAreAnonymousText) {
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_text_fragment_builder.cc b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_text_fragment_builder.cc
index 0b85af665ca..bd872d67343 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_text_fragment_builder.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_text_fragment_builder.cc
@@ -22,25 +22,25 @@ NGTextFragmentBuilder::NGTextFragmentBuilder(
shape_result_(fragment.TextShapeResult()),
text_type_(fragment.TextType()) {}
-void NGTextFragmentBuilder::SetItem(
- NGPhysicalTextFragment::NGTextType text_type,
- const NGInlineItemsData& items_data,
- NGInlineItemResult* item_result,
- LayoutUnit line_height) {
- DCHECK_NE(text_type, NGPhysicalTextFragment::kGeneratedText)
- << "Please use SetText() instead.";
+void NGTextFragmentBuilder::SetItem(const String& text_content,
+ NGInlineItemResult* item_result,
+ LayoutUnit line_height) {
DCHECK(item_result);
- DCHECK(item_result->item->Style());
+ const NGInlineItem* item = item_result->item;
+ DCHECK(item);
+ DCHECK_NE(item->TextType(), NGTextType::kLayoutGenerated)
+ << "Please use SetText() instead.";
+ DCHECK(item->Style());
- text_type_ = text_type;
- text_ = items_data.text_content;
+ text_type_ = item->TextType();
+ text_ = text_content;
start_offset_ = item_result->start_offset;
end_offset_ = item_result->end_offset;
- resolved_direction_ = item_result->item->Direction();
- SetStyle(item_result->item->Style(), item_result->item->StyleVariant());
+ resolved_direction_ = item->Direction();
+ SetStyle(item->Style(), item->StyleVariant());
size_ = {item_result->inline_size, line_height};
shape_result_ = std::move(item_result->shape_result);
- layout_object_ = item_result->item->GetLayoutObject();
+ layout_object_ = item->GetLayoutObject();
}
void NGTextFragmentBuilder::SetText(
@@ -53,7 +53,7 @@ void NGTextFragmentBuilder::SetText(
DCHECK(style);
DCHECK(shape_result);
- text_type_ = NGPhysicalTextFragment::kGeneratedText;
+ text_type_ = NGTextType::kLayoutGenerated;
text_ = text;
start_offset_ = shape_result->StartIndex();
end_offset_ = shape_result->EndIndex();
@@ -66,21 +66,6 @@ void NGTextFragmentBuilder::SetText(
layout_object_ = layout_object;
}
-bool NGTextFragmentBuilder::IsGeneratedText() const {
- if (UNLIKELY(style_variant_ == NGStyleVariant::kEllipsis ||
- text_type_ == NGPhysicalTextFragment::kGeneratedText))
- return true;
-
- DCHECK(layout_object_);
- if (const auto* layout_text_fragment =
- ToLayoutTextFragmentOrNull(layout_object_)) {
- return !layout_text_fragment->AssociatedTextNode();
- }
-
- const Node* node = layout_object_->GetNode();
- return !node || node->IsPseudoElement();
-}
-
scoped_refptr<const NGPhysicalTextFragment>
NGTextFragmentBuilder::ToTextFragment() {
scoped_refptr<const NGPhysicalTextFragment> fragment =
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_text_fragment_builder.h b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_text_fragment_builder.h
index 3cb38c1af32..1d028144f27 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_text_fragment_builder.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_text_fragment_builder.h
@@ -29,8 +29,7 @@ class CORE_EXPORT NGTextFragmentBuilder final : public NGFragmentBuilder {
TextDirection ResolvedDirection() const { return resolved_direction_; }
// NOTE: Takes ownership of the shape result within the item result.
- void SetItem(NGPhysicalTextFragment::NGTextType,
- const NGInlineItemsData&,
+ void SetItem(const String& text_content,
NGInlineItemResult*,
LayoutUnit line_height);
@@ -45,17 +44,12 @@ class CORE_EXPORT NGTextFragmentBuilder final : public NGFragmentBuilder {
scoped_refptr<const NGPhysicalTextFragment> ToTextFragment();
private:
- // Returns true if the text is generated (from, e.g., list marker,
- // pseudo-element, ...) instead of from a DOM text node.
- bool IsGeneratedText() const;
-
String text_;
unsigned start_offset_;
unsigned end_offset_;
scoped_refptr<const ShapeResultView> shape_result_;
- NGPhysicalTextFragment::NGTextType text_type_ =
- NGPhysicalTextFragment::kNormalText;
+ NGTextType text_type_ = NGTextType::kNormal;
// Set from |NGInlineItem| by |SetItem()|.
TextDirection resolved_direction_ = TextDirection::kLtr;
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_text_type.h b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_text_type.h
new file mode 100644
index 00000000000..be2a2d58c1e
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_text_type.h
@@ -0,0 +1,32 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_TEXT_TYPE_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_TEXT_TYPE_H_
+
+namespace blink {
+
+// Type of text nodes and fragments.
+enum class NGTextType {
+ // Normal text from |text_content_| in |NGNodeInlineData|. It is from
+ // the box-tree; i.e., originated from DOM text nodes, or content generated by
+ // pseudo elements.
+ kNormal,
+ // Forced line break, either from <br> element or preserved new line
+ // characters.
+ kForcedLineBreak,
+ // Flow controls are not to be painted. In particular, a tabulation
+ // character and a soft-wrap opportunity.
+ kFlowControl,
+ kSymbolMarker,
+ // This text is generated by layout, e.g. hyphens and ellipsis, not from
+ // |LayoutText| nor from |NGNodeInlineData|.
+ // Note: Contents generated by CSS pseudo element, e.g. ::before, ::after,
+ // are not classified to this. See |IsStyleGenerated()| for them.
+ kLayoutGenerated,
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_TEXT_TYPE_H_
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/layout_box_utils.cc b/chromium/third_party/blink/renderer/core/layout/ng/layout_box_utils.cc
index 402f5bbe615..d68f0ba0b58 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/layout_box_utils.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/layout_box_utils.cc
@@ -13,6 +13,7 @@
#include "third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.h"
#include "third_party/blink/renderer/core/layout/ng/ng_constraint_space_builder.h"
#include "third_party/blink/renderer/core/layout/ng/ng_length_utils.h"
+#include "third_party/blink/renderer/core/paint/paint_layer.h"
namespace blink {
@@ -115,12 +116,20 @@ NGLogicalStaticPosition LayoutBoxUtils::ComputeStaticPositionFromLegacy(
MinimumValueForLength(logical_top, containing_block_logical_height);
}
+ NGLogicalStaticPosition::BlockEdge block_edge =
+ box.Layer()->StaticBlockEdge();
+ NGLogicalStaticPosition::InlineEdge inline_edge =
+ box.Layer()->StaticInlineEdge();
+
+ if (!IsLtr(parent_direction)) {
+ if (inline_edge == NGLogicalStaticPosition::InlineEdge::kInlineStart)
+ inline_edge = NGLogicalStaticPosition::InlineEdge::kInlineEnd;
+ else if (inline_edge == NGLogicalStaticPosition::InlineEdge::kInlineEnd)
+ inline_edge = NGLogicalStaticPosition::InlineEdge::kInlineStart;
+ }
+
NGLogicalStaticPosition logical_static_position{
- {static_line, static_block},
- IsLtr(parent_direction)
- ? NGLogicalStaticPosition::InlineEdge::kInlineStart
- : NGLogicalStaticPosition::InlineEdge::kInlineEnd,
- NGLogicalStaticPosition::BlockEdge::kBlockStart};
+ {static_line, static_block}, inline_edge, block_edge};
// Determine the physical available-size, remember that the available-size is
// currently in the *descendant's* writing-mode.
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_block_flow_mixin.cc b/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_block_flow_mixin.cc
index ef990b7ce3f..a7904987197 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_block_flow_mixin.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_block_flow_mixin.cc
@@ -299,8 +299,12 @@ void LayoutNGBlockFlowMixin<Base>::DirtyLinesFromChangedChild(
// We need to dirty line box fragments only if the child is once laid out in
// LayoutNG inline formatting context. New objects are handled in
// NGInlineNode::MarkLineBoxesDirty().
- if (child->IsInLayoutNGInlineFormattingContext())
- NGPaintFragment::DirtyLinesFromChangedChild(child);
+ if (child->IsInLayoutNGInlineFormattingContext()) {
+ if (RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()) {
+ if (const NGFragmentItems* items = Base::FragmentItems())
+ items->DirtyLinesFromChangedChild(child);
+ }
+ }
}
template <typename Base>
@@ -341,6 +345,10 @@ void LayoutNGBlockFlowMixin<Base>::UpdateMargins() {
template class CORE_TEMPLATE_EXPORT LayoutNGBlockFlowMixin<LayoutBlockFlow>;
template class CORE_TEMPLATE_EXPORT LayoutNGBlockFlowMixin<LayoutProgress>;
+template class CORE_TEMPLATE_EXPORT LayoutNGBlockFlowMixin<LayoutRubyAsBlock>;
+template class CORE_TEMPLATE_EXPORT LayoutNGBlockFlowMixin<LayoutRubyBase>;
+template class CORE_TEMPLATE_EXPORT LayoutNGBlockFlowMixin<LayoutRubyRun>;
+template class CORE_TEMPLATE_EXPORT LayoutNGBlockFlowMixin<LayoutRubyText>;
template class CORE_TEMPLATE_EXPORT LayoutNGBlockFlowMixin<LayoutTableCaption>;
template class CORE_TEMPLATE_EXPORT LayoutNGBlockFlowMixin<LayoutTableCell>;
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_block_flow_mixin.h b/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_block_flow_mixin.h
index 2e808c039bb..9e58015d936 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_block_flow_mixin.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_block_flow_mixin.h
@@ -11,6 +11,8 @@
#include "third_party/blink/renderer/core/layout/layout_block_flow.h"
#include "third_party/blink/renderer/core/layout/layout_box_model_object.h"
#include "third_party/blink/renderer/core/layout/layout_progress.h"
+#include "third_party/blink/renderer/core/layout/layout_ruby.h"
+#include "third_party/blink/renderer/core/layout/layout_ruby_run.h"
#include "third_party/blink/renderer/core/layout/layout_table_caption.h"
#include "third_party/blink/renderer/core/layout/layout_table_cell.h"
#include "third_party/blink/renderer/core/layout/ng/layout_ng_mixin.h"
@@ -97,6 +99,14 @@ extern template class CORE_EXTERN_TEMPLATE_EXPORT
extern template class CORE_EXTERN_TEMPLATE_EXPORT
LayoutNGBlockFlowMixin<LayoutProgress>;
extern template class CORE_EXTERN_TEMPLATE_EXPORT
+ LayoutNGBlockFlowMixin<LayoutRubyAsBlock>;
+extern template class CORE_EXTERN_TEMPLATE_EXPORT
+ LayoutNGBlockFlowMixin<LayoutRubyBase>;
+extern template class CORE_EXTERN_TEMPLATE_EXPORT
+ LayoutNGBlockFlowMixin<LayoutRubyRun>;
+extern template class CORE_EXTERN_TEMPLATE_EXPORT
+ LayoutNGBlockFlowMixin<LayoutRubyText>;
+extern template class CORE_EXTERN_TEMPLATE_EXPORT
LayoutNGBlockFlowMixin<LayoutTableCaption>;
extern template class CORE_EXTERN_TEMPLATE_EXPORT
LayoutNGBlockFlowMixin<LayoutTableCell>;
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_fieldset.cc b/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_fieldset.cc
index 907d45bb278..2e2a703eb57 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_fieldset.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_fieldset.cc
@@ -30,12 +30,39 @@ void LayoutNGFieldset::AddChild(LayoutObject* new_child,
// supported). Removing it from its actual DOM siblings and putting it
// elsewhere, on the other hand, does not work well.
+ // TODO(crbug.com/875235): Consider other display types not mentioned in the
+ // spec (ex. EDisplay::kLayoutCustom).
+ EDisplay display = EDisplay::kFlowRoot;
+ switch (StyleRef().Display()) {
+ case EDisplay::kFlex:
+ case EDisplay::kInlineFlex:
+ display = EDisplay::kFlex;
+ break;
+ case EDisplay::kGrid:
+ case EDisplay::kInlineGrid:
+ display = EDisplay::kGrid;
+ break;
+ default:
+ break;
+ }
+
scoped_refptr<ComputedStyle> new_style =
- ComputedStyle::CreateAnonymousStyleWithDisplay(StyleRef(),
- EDisplay::kFlowRoot);
+ ComputedStyle::CreateAnonymousStyleWithDisplay(StyleRef(), display);
+
+ // Inherit all properties listed here:
+ // https://html.spec.whatwg.org/C/#the-fieldset-and-legend-elements
+
// TODO(crbug.com/875235): When the paint code is ready for anonymous
// scrollable containers, inherit overflow-x and overflow-y here.
+ new_style->SetAlignContent(StyleRef().AlignContent());
+ new_style->SetAlignItems(StyleRef().AlignItems());
+
+ new_style->SetBorderBottomLeftRadius(StyleRef().BorderBottomLeftRadius());
+ new_style->SetBorderBottomRightRadius(StyleRef().BorderBottomRightRadius());
+ new_style->SetBorderTopLeftRadius(StyleRef().BorderTopLeftRadius());
+ new_style->SetBorderTopRightRadius(StyleRef().BorderTopRightRadius());
+
new_style->SetPaddingTop(StyleRef().PaddingTop());
new_style->SetPaddingRight(StyleRef().PaddingRight());
new_style->SetPaddingBottom(StyleRef().PaddingBottom());
@@ -50,12 +77,32 @@ void LayoutNGFieldset::AddChild(LayoutObject* new_child,
}
new_style->SetColumnGap(StyleRef().ColumnGap());
new_style->SetColumnFill(StyleRef().GetColumnFill());
+ new_style->SetColumnRuleColor(StyleColor(LayoutObject::ResolveColor(
+ StyleRef(), GetCSSPropertyColumnRuleColor())));
+ new_style->SetColumnRuleStyle(StyleRef().ColumnRuleStyle());
+ new_style->SetColumnRuleWidth(StyleRef().ColumnRuleWidth());
new_style->SetFlexDirection(StyleRef().FlexDirection());
- new_style->SetJustifyContent(StyleRef().JustifyContent());
+ new_style->SetFlexWrap(StyleRef().FlexWrap());
- // TODO(mstensho): Inherit all properties listed here:
- // https://html.spec.whatwg.org/C/#the-fieldset-and-legend-elements
+ new_style->SetGridAutoColumns(StyleRef().GridAutoColumns());
+ new_style->SetGridAutoFlow(StyleRef().GetGridAutoFlow());
+ new_style->SetGridAutoRows(StyleRef().GridAutoRows());
+ new_style->SetGridColumnEnd(StyleRef().GridColumnEnd());
+ new_style->SetGridColumnStart(StyleRef().GridColumnStart());
+ new_style->SetGridRowEnd(StyleRef().GridRowEnd());
+ new_style->SetGridRowStart(StyleRef().GridRowStart());
+ new_style->SetGridTemplateColumns(StyleRef().GridTemplateColumns());
+ new_style->SetGridTemplateRows(StyleRef().GridTemplateRows());
+ new_style->SetNamedGridArea(StyleRef().NamedGridArea());
+ new_style->SetNamedGridAreaColumnCount(
+ StyleRef().NamedGridAreaColumnCount());
+ new_style->SetNamedGridAreaRowCount(StyleRef().NamedGridAreaRowCount());
+ new_style->SetRowGap(StyleRef().RowGap());
+
+ new_style->SetJustifyContent(StyleRef().JustifyContent());
+ new_style->SetJustifyItems(StyleRef().JustifyItems());
+ new_style->SetUnicodeBidi(StyleRef().GetUnicodeBidi());
fieldset_content = LayoutBlock::CreateAnonymousWithParentAndDisplay(
this, new_style->Display());
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_grid.cc b/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_grid.cc
new file mode 100644
index 00000000000..672f1a4b32c
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_grid.cc
@@ -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.
+
+#include "third_party/blink/renderer/core/layout/ng/layout_ng_grid.h"
+
+#include "third_party/blink/renderer/core/layout/ng/ng_layout_result.h"
+
+namespace blink {
+
+LayoutNGGrid::LayoutNGGrid(Element* element)
+ : LayoutNGMixin<LayoutBlock>(element) {}
+
+void LayoutNGGrid::UpdateBlockLayout(bool relayout_children) {
+ if (IsOutOfFlowPositioned()) {
+ UpdateOutOfFlowBlockLayout();
+ return;
+ }
+
+ UpdateInFlowBlockLayout();
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_grid.h b/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_grid.h
new file mode 100644
index 00000000000..060835974ba
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_grid.h
@@ -0,0 +1,31 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_LAYOUT_NG_GRID_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_LAYOUT_NG_GRID_H_
+
+#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/core/layout/layout_block.h"
+#include "third_party/blink/renderer/core/layout/ng/layout_ng_mixin.h"
+
+namespace blink {
+
+class CORE_EXPORT LayoutNGGrid : public LayoutNGMixin<LayoutBlock> {
+ public:
+ explicit LayoutNGGrid(Element*);
+
+ void UpdateBlockLayout(bool relayout_children) override;
+
+ const char* GetName() const override { return "LayoutNGGrid"; }
+
+ protected:
+ bool IsOfType(LayoutObjectType type) const override {
+ return type == kLayoutObjectNGGrid ||
+ LayoutNGMixin<LayoutBlock>::IsOfType(type);
+ }
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_LAYOUT_NG_GRID_H_
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_mixin.cc b/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_mixin.cc
index 89ad70133c1..1c82b8a6480 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_mixin.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_mixin.cc
@@ -26,6 +26,8 @@ LayoutNGMixin<Base>::LayoutNGMixin(Element* element) : Base(element) {
std::is_base_of<LayoutBlock, Base>::value,
"Base class of LayoutNGMixin must be LayoutBlock or derived class.");
DCHECK(!element || !element->ShouldForceLegacyLayout());
+ if (element)
+ Base::GetDocument().IncLayoutBlockCounterNG();
}
template <typename Base>
@@ -88,9 +90,11 @@ MinMaxSizes LayoutNGMixin<Base>::ComputeIntrinsicLogicalWidths() const {
LayoutBoxUtils::AvailableLogicalHeight(*this, Base::ContainingBlock());
NGConstraintSpace space = ConstraintSpaceForMinMaxSizes();
- MinMaxSizes sizes = node.ComputeMinMaxSizes(
- node.Style().GetWritingMode(), MinMaxSizesInput(available_logical_height),
- &space);
+ MinMaxSizes sizes =
+ node.ComputeMinMaxSizes(node.Style().GetWritingMode(),
+ MinMaxSizesInput(available_logical_height),
+ &space)
+ .sizes;
if (Base::IsTableCell()) {
// If a table cell, or the column that it belongs to, has a specified fixed
@@ -276,6 +280,10 @@ LayoutNGMixin<Base>::UpdateInFlowBlockLayout() {
template class CORE_TEMPLATE_EXPORT LayoutNGMixin<LayoutBlock>;
template class CORE_TEMPLATE_EXPORT LayoutNGMixin<LayoutBlockFlow>;
template class CORE_TEMPLATE_EXPORT LayoutNGMixin<LayoutProgress>;
+template class CORE_TEMPLATE_EXPORT LayoutNGMixin<LayoutRubyAsBlock>;
+template class CORE_TEMPLATE_EXPORT LayoutNGMixin<LayoutRubyBase>;
+template class CORE_TEMPLATE_EXPORT LayoutNGMixin<LayoutRubyRun>;
+template class CORE_TEMPLATE_EXPORT LayoutNGMixin<LayoutRubyText>;
template class CORE_TEMPLATE_EXPORT LayoutNGMixin<LayoutTableCaption>;
template class CORE_TEMPLATE_EXPORT LayoutNGMixin<LayoutTableCell>;
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_mixin.h b/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_mixin.h
index a6194724268..94bce7652fd 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_mixin.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_mixin.h
@@ -10,6 +10,10 @@
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/layout/layout_block_flow.h"
#include "third_party/blink/renderer/core/layout/layout_progress.h"
+#include "third_party/blink/renderer/core/layout/layout_ruby.h"
+#include "third_party/blink/renderer/core/layout/layout_ruby_base.h"
+#include "third_party/blink/renderer/core/layout/layout_ruby_run.h"
+#include "third_party/blink/renderer/core/layout/layout_ruby_text.h"
#include "third_party/blink/renderer/core/layout/layout_table_caption.h"
#include "third_party/blink/renderer/core/layout/layout_table_cell.h"
@@ -49,6 +53,11 @@ extern template class CORE_EXTERN_TEMPLATE_EXPORT
LayoutNGMixin<LayoutBlockFlow>;
extern template class CORE_EXTERN_TEMPLATE_EXPORT LayoutNGMixin<LayoutProgress>;
extern template class CORE_EXTERN_TEMPLATE_EXPORT
+ LayoutNGMixin<LayoutRubyAsBlock>;
+extern template class CORE_EXTERN_TEMPLATE_EXPORT LayoutNGMixin<LayoutRubyBase>;
+extern template class CORE_EXTERN_TEMPLATE_EXPORT LayoutNGMixin<LayoutRubyRun>;
+extern template class CORE_EXTERN_TEMPLATE_EXPORT LayoutNGMixin<LayoutRubyText>;
+extern template class CORE_EXTERN_TEMPLATE_EXPORT
LayoutNGMixin<LayoutTableCaption>;
extern template class CORE_EXTERN_TEMPLATE_EXPORT
LayoutNGMixin<LayoutTableCell>;
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_as_block.cc b/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_as_block.cc
new file mode 100644
index 00000000000..3da5af1bf83
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_as_block.cc
@@ -0,0 +1,18 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/layout/ng/layout_ng_ruby_as_block.h"
+
+namespace blink {
+
+LayoutNGRubyAsBlock::LayoutNGRubyAsBlock(Element* element)
+ : LayoutNGBlockFlowMixin<LayoutRubyAsBlock>(element) {}
+
+LayoutNGRubyAsBlock::~LayoutNGRubyAsBlock() = default;
+
+void LayoutNGRubyAsBlock::UpdateBlockLayout(bool relayout_children) {
+ UpdateNGBlockLayout();
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_as_block.h b/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_as_block.h
new file mode 100644
index 00000000000..7dff53b6eb7
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_as_block.h
@@ -0,0 +1,28 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_LAYOUT_NG_RUBY_AS_BLOCK_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_LAYOUT_NG_RUBY_AS_BLOCK_H_
+
+#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/core/layout/layout_ruby.h"
+#include "third_party/blink/renderer/core/layout/ng/layout_ng_block_flow_mixin.h"
+
+namespace blink {
+
+// A NG version of LayoutRubyAsBlock.
+// This adds anonymous block building to LayoutNGBlockFlow.
+class CORE_EXPORT LayoutNGRubyAsBlock
+ : public LayoutNGBlockFlowMixin<LayoutRubyAsBlock> {
+ public:
+ explicit LayoutNGRubyAsBlock(Element*);
+ ~LayoutNGRubyAsBlock() override;
+
+ const char* GetName() const override { return "LayoutNGRubyAsBlock"; }
+ void UpdateBlockLayout(bool relayout_children) override;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_LAYOUT_NG_RUBY_AS_BLOCK_H_
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_base.cc b/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_base.cc
new file mode 100644
index 00000000000..472efc47b28
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_base.cc
@@ -0,0 +1,18 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/layout/ng/layout_ng_ruby_base.h"
+
+namespace blink {
+
+LayoutNGRubyBase::LayoutNGRubyBase()
+ : LayoutNGBlockFlowMixin<LayoutRubyBase>(nullptr) {}
+
+LayoutNGRubyBase::~LayoutNGRubyBase() = default;
+
+void LayoutNGRubyBase::UpdateBlockLayout(bool relayout_children) {
+ UpdateNGBlockLayout();
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_base.h b/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_base.h
new file mode 100644
index 00000000000..8e0e73370cc
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_base.h
@@ -0,0 +1,27 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_LAYOUT_NG_RUBY_BASE_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_LAYOUT_NG_RUBY_BASE_H_
+
+#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/core/layout/layout_ruby_base.h"
+#include "third_party/blink/renderer/core/layout/ng/layout_ng_block_flow_mixin.h"
+
+namespace blink {
+
+// A LayoutNG version of LayoutRubyBase.
+class CORE_EXPORT LayoutNGRubyBase final
+ : public LayoutNGBlockFlowMixin<LayoutRubyBase> {
+ public:
+ explicit LayoutNGRubyBase();
+ ~LayoutNGRubyBase() override;
+
+ const char* GetName() const override { return "LayoutNGRubyBase"; }
+ void UpdateBlockLayout(bool relayout_children) override;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_LAYOUT_NG_RUBY_BASE_H_
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_run.cc b/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_run.cc
new file mode 100644
index 00000000000..928e85be304
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_run.cc
@@ -0,0 +1,19 @@
+// 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/core/layout/ng/layout_ng_ruby_run.h"
+
+namespace blink {
+
+LayoutNGRubyRun::LayoutNGRubyRun()
+ : LayoutNGBlockFlowMixin<LayoutRubyRun>(nullptr) {}
+
+LayoutNGRubyRun::~LayoutNGRubyRun() = default;
+
+void LayoutNGRubyRun::UpdateBlockLayout(bool relayout_children) {
+ // TODO(crbug.com/1069817): Implement ruby-specific layout.
+ UpdateNGBlockLayout();
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_run.h b/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_run.h
new file mode 100644
index 00000000000..d5ff077683a
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_run.h
@@ -0,0 +1,27 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_LAYOUT_NG_RUBY_RUN_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_LAYOUT_NG_RUBY_RUN_H_
+
+#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/core/layout/layout_ruby_run.h"
+#include "third_party/blink/renderer/core/layout/ng/layout_ng_block_flow_mixin.h"
+
+namespace blink {
+
+// A LayoutNG version of LayoutRubyRun.
+class CORE_EXPORT LayoutNGRubyRun final
+ : public LayoutNGBlockFlowMixin<LayoutRubyRun> {
+ public:
+ explicit LayoutNGRubyRun();
+ ~LayoutNGRubyRun() override;
+
+ const char* GetName() const override { return "LayoutNGRubyRun"; }
+ void UpdateBlockLayout(bool relayout_children) override;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_LAYOUT_NG_RUBY_RUN_H_
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_text.cc b/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_text.cc
new file mode 100644
index 00000000000..15dfb02f972
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_text.cc
@@ -0,0 +1,18 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/layout/ng/layout_ng_ruby_text.h"
+
+namespace blink {
+
+LayoutNGRubyText::LayoutNGRubyText(Element* element)
+ : LayoutNGBlockFlowMixin<LayoutRubyText>(element) {}
+
+LayoutNGRubyText::~LayoutNGRubyText() = default;
+
+void LayoutNGRubyText::UpdateBlockLayout(bool relayout_children) {
+ UpdateNGBlockLayout();
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_text.h b/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_text.h
new file mode 100644
index 00000000000..51511b629b0
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_text.h
@@ -0,0 +1,27 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_LAYOUT_NG_RUBY_TEXT_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_LAYOUT_NG_RUBY_TEXT_H_
+
+#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/core/layout/layout_ruby_text.h"
+#include "third_party/blink/renderer/core/layout/ng/layout_ng_block_flow_mixin.h"
+
+namespace blink {
+
+// A LayoutNG version of LayoutRubyText.
+class CORE_EXPORT LayoutNGRubyText final
+ : public LayoutNGBlockFlowMixin<LayoutRubyText> {
+ public:
+ explicit LayoutNGRubyText(Element* element);
+ ~LayoutNGRubyText() override;
+
+ const char* GetName() const override { return "LayoutNGRubyText"; }
+ void UpdateBlockLayout(bool relayout_children) override;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_LAYOUT_NG_RUBY_TEXT_H_
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_table_cell.h b/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_table_cell.h
deleted file mode 100644
index 4781aa05bb3..00000000000
--- a/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_table_cell.h
+++ /dev/null
@@ -1,26 +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_CORE_LAYOUT_NG_LAYOUT_NG_TABLE_CELL_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_LAYOUT_NG_TABLE_CELL_H_
-
-#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/core/layout/layout_table_cell.h"
-#include "third_party/blink/renderer/core/layout/ng/layout_ng_block_flow_mixin.h"
-
-namespace blink {
-
-class CORE_EXPORT LayoutNGTableCell final
- : public LayoutNGBlockFlowMixin<LayoutTableCell> {
- public:
- explicit LayoutNGTableCell(Element*);
-
- void UpdateBlockLayout(bool relayout_children) override;
-
- const char* GetName() const override { return "LayoutNGTableCell"; }
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_LAYOUT_NG_TABLE_CELL_H_
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/legacy_layout_tree_walking.h b/chromium/third_party/blink/renderer/core/layout/ng/legacy_layout_tree_walking.h
index e01bc5d90ec..afa57830aaf 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/legacy_layout_tree_walking.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/legacy_layout_tree_walking.h
@@ -24,11 +24,13 @@ inline LayoutObject* GetLayoutObjectForFirstChildNode(LayoutBlock* parent) {
if (!child)
return nullptr;
if (UNLIKELY(child->IsLayoutFlowThread()))
- return To<LayoutBlockFlow>(child)->FirstChild();
- // The rendered legend is a child of the anonymous wrapper inside the fieldset
- // container. If we find it, skip it. As far as NG is concerned, the rendered
- // legend is a child of the fieldset container.
- if (UNLIKELY(child->IsRenderedLegend()))
+ child = To<LayoutBlockFlow>(child)->FirstChild();
+ // The rendered legend is a child of the anonymous wrapper, inside the
+ // fieldset container. Or in the case of a multi-column, the rendered legend
+ // is a child of the multi-column flow thread, inside the anonymous wrapper
+ // and fieldset. If we find it, skip it. As far as NG is concerned, the
+ // rendered legend is a child of the fieldset container.
+ if (UNLIKELY(child && child->IsRenderedLegend()))
return child->NextSibling();
return child;
}
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/mathml/layout_ng_mathml_block.cc b/chromium/third_party/blink/renderer/core/layout/ng/mathml/layout_ng_mathml_block.cc
index 161826f1cff..7ccadb2bafe 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/mathml/layout_ng_mathml_block.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/mathml/layout_ng_mathml_block.cc
@@ -6,10 +6,11 @@
#include "third_party/blink/renderer/core/layout/layout_analyzer.h"
#include "third_party/blink/renderer/core/layout/ng/ng_layout_result.h"
+#include "third_party/blink/renderer/core/mathml/mathml_element.h"
namespace blink {
-LayoutNGMathMLBlock::LayoutNGMathMLBlock(MathMLElement* element)
+LayoutNGMathMLBlock::LayoutNGMathMLBlock(Element* element)
: LayoutNGMixin<LayoutBlock>(element) {
DCHECK(element);
}
@@ -34,7 +35,7 @@ bool LayoutNGMathMLBlock::IsOfType(LayoutObjectType type) const {
bool LayoutNGMathMLBlock::IsChildAllowed(LayoutObject* child,
const ComputedStyle&) const {
- return child->GetNode() && child->GetNode()->IsMathMLElement();
+ return child->GetNode() && IsA<MathMLElement>(child->GetNode());
}
bool LayoutNGMathMLBlock::CanHaveChildren() const {
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/mathml/layout_ng_mathml_block.h b/chromium/third_party/blink/renderer/core/layout/ng/mathml/layout_ng_mathml_block.h
index bc9dc975643..414e098cc6d 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/mathml/layout_ng_mathml_block.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/mathml/layout_ng_mathml_block.h
@@ -6,13 +6,12 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_MATHML_LAYOUT_NG_MATHML_BLOCK_H_
#include "third_party/blink/renderer/core/layout/ng/layout_ng_mixin.h"
-#include "third_party/blink/renderer/core/mathml/mathml_element.h"
namespace blink {
class LayoutNGMathMLBlock : public LayoutNGMixin<LayoutBlock> {
public:
- explicit LayoutNGMathMLBlock(MathMLElement*);
+ explicit LayoutNGMathMLBlock(Element*);
const char* GetName() const override { return "LayoutNGMathMLBlock"; }
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_fraction_layout_algorithm.cc b/chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_fraction_layout_algorithm.cc
index 9deb2e3c49f..831821243aa 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_fraction_layout_algorithm.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_fraction_layout_algorithm.cc
@@ -192,10 +192,6 @@ scoped_refptr<const NGLayoutResult> NGMathFractionLayoutAlgorithm::Layout() {
ConstraintSpace().GetWritingMode(), ConstraintSpace().Direction(),
To<NGPhysicalBoxFragment>(denominator_layout_result->PhysicalFragment()));
- LayoutUnit content_inline_size = std::max(
- numerator_fragment.InlineSize() + numerator_margins.InlineSum(),
- denominator_fragment.InlineSize() + denominator_margins.InlineSum());
-
LayoutUnit numerator_ascent =
numerator_margins.block_start +
numerator_fragment.Baseline().value_or(numerator_fragment.BlockSize());
@@ -252,13 +248,13 @@ scoped_refptr<const NGLayoutResult> NGMathFractionLayoutAlgorithm::Layout() {
LogicalOffset denominator_offset;
numerator_offset.inline_offset =
border_scrollbar_padding_.inline_start + numerator_margins.inline_start +
- (content_inline_size -
+ (child_available_size.inline_size -
(numerator_fragment.InlineSize() + numerator_margins.InlineSum())) /
2;
denominator_offset.inline_offset =
border_scrollbar_padding_.inline_start +
denominator_margins.inline_start +
- (content_inline_size -
+ (child_available_size.inline_size -
(denominator_fragment.InlineSize() + denominator_margins.InlineSum())) /
2;
@@ -278,7 +274,8 @@ scoped_refptr<const NGLayoutResult> NGMathFractionLayoutAlgorithm::Layout() {
denominator.StoreMargins(ConstraintSpace(), denominator_margins);
LayoutUnit block_size = ComputeBlockSizeForFragment(
- ConstraintSpace(), Style(), border_scrollbar_padding_, total_block_size);
+ ConstraintSpace(), Style(), border_scrollbar_padding_, total_block_size,
+ border_box_size.inline_size);
container_builder_.SetIntrinsicBlockSize(total_block_size);
container_builder_.SetBlockSize(block_size);
@@ -290,34 +287,31 @@ scoped_refptr<const NGLayoutResult> NGMathFractionLayoutAlgorithm::Layout() {
return container_builder_.ToBoxFragment();
}
-base::Optional<MinMaxSizes> NGMathFractionLayoutAlgorithm::ComputeMinMaxSizes(
- const MinMaxSizesInput& input) const {
- base::Optional<MinMaxSizes> sizes =
- CalculateMinMaxSizesIgnoringChildren(Node(), border_scrollbar_padding_);
- if (sizes)
- return sizes;
-
- sizes.emplace();
- LayoutUnit child_percentage_resolution_block_size =
- CalculateChildPercentageBlockSizeForMinMax(
- ConstraintSpace(), Node(), border_scrollbar_padding_,
- input.percentage_resolution_block_size);
+MinMaxSizesResult NGMathFractionLayoutAlgorithm::ComputeMinMaxSizes(
+ const MinMaxSizesInput& child_input) const {
+ if (auto result = CalculateMinMaxSizesIgnoringChildren(
+ Node(), border_scrollbar_padding_))
+ return *result;
- MinMaxSizesInput child_input(child_percentage_resolution_block_size);
+ MinMaxSizes sizes;
+ bool depends_on_percentage_block_size = false;
for (NGLayoutInputNode child = Node().FirstChild(); child;
child = child.NextSibling()) {
if (child.IsOutOfFlowPositioned())
continue;
- auto child_sizes =
+ auto child_result =
ComputeMinAndMaxContentContribution(Style(), child, child_input);
NGBoxStrut margins = ComputeMinMaxMargins(Style(), child);
- child_sizes += margins.InlineSum();
- sizes->Encompass(child_sizes);
+ child_result.sizes += margins.InlineSum();
+
+ sizes.Encompass(child_result.sizes);
+ depends_on_percentage_block_size |=
+ child_result.depends_on_percentage_block_size;
}
- *sizes += border_scrollbar_padding_.InlineSum();
- return sizes;
+ sizes += border_scrollbar_padding_.InlineSum();
+ return {sizes, depends_on_percentage_block_size};
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_fraction_layout_algorithm.h b/chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_fraction_layout_algorithm.h
index d645439465f..83640d5826a 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_fraction_layout_algorithm.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_fraction_layout_algorithm.h
@@ -19,8 +19,7 @@ class CORE_EXPORT NGMathFractionLayoutAlgorithm
private:
scoped_refptr<const NGLayoutResult> Layout() final;
- base::Optional<MinMaxSizes> ComputeMinMaxSizes(
- const MinMaxSizesInput&) const final;
+ MinMaxSizesResult ComputeMinMaxSizes(const MinMaxSizesInput&) const final;
void GatherChildren(NGBlockNode* numerator, NGBlockNode* denominator);
const NGBoxStrut border_scrollbar_padding_;
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_layout_utils.cc b/chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_layout_utils.cc
index 44f6ed8d617..1c826af849e 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_layout_utils.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_layout_utils.cc
@@ -10,6 +10,7 @@
#include "third_party/blink/renderer/core/layout/ng/ng_length_utils.h"
#include "third_party/blink/renderer/core/layout/ng/ng_space_utils.h"
#include "third_party/blink/renderer/core/mathml/mathml_fraction_element.h"
+#include "third_party/blink/renderer/core/mathml/mathml_scripts_element.h"
namespace blink {
@@ -69,6 +70,21 @@ bool IsValidMathMLFraction(const NGBlockNode& node) {
return InFlowChildCountIs(node, 2);
}
+bool IsValidMathMLScript(const NGBlockNode& node) {
+ switch (node.ScriptType()) {
+ case MathScriptType::kUnder:
+ case MathScriptType::kOver:
+ case MathScriptType::kSub:
+ case MathScriptType::kSuper:
+ return InFlowChildCountIs(node, 2);
+ case MathScriptType::kSubSup:
+ case MathScriptType::kUnderOver:
+ return InFlowChildCountIs(node, 3);
+ default:
+ return false;
+ }
+}
+
namespace {
inline LayoutUnit DefaultFractionLineThickness(const ComputedStyle& style) {
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_layout_utils.h b/chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_layout_utils.h
index 366e1a81171..0d57c2665be 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_layout_utils.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_layout_utils.h
@@ -26,6 +26,7 @@ NGLayoutInputNode FirstChildInFlow(const NGBlockNode&);
NGLayoutInputNode NextSiblingInFlow(const NGBlockNode&);
bool IsValidMathMLFraction(const NGBlockNode&);
+bool IsValidMathMLScript(const NGBlockNode&);
inline float RuleThicknessFallback(const ComputedStyle& style) {
// This function returns a value for the default rule thickness (TeX's
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_row_layout_algorithm.cc b/chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_row_layout_algorithm.cc
index 6fe8785a1cc..a4f4ef38039 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_row_layout_algorithm.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_row_layout_algorithm.cc
@@ -128,7 +128,8 @@ scoped_refptr<const NGLayoutResult> NGMathRowLayoutAlgorithm::Layout() {
auto block_size = ComputeBlockSizeForFragment(
ConstraintSpace(), Style(), border_padding_,
- max_row_size.block_size + border_scrollbar_padding_.BlockSum());
+ max_row_size.block_size + border_scrollbar_padding_.BlockSum(),
+ border_box_size.inline_size);
container_builder_.SetBlockSize(block_size);
NGOutOfFlowLayoutPart(
@@ -140,41 +141,39 @@ scoped_refptr<const NGLayoutResult> NGMathRowLayoutAlgorithm::Layout() {
return container_builder_.ToBoxFragment();
}
-base::Optional<MinMaxSizes> NGMathRowLayoutAlgorithm::ComputeMinMaxSizes(
- const MinMaxSizesInput& input) const {
- base::Optional<MinMaxSizes> sizes =
- CalculateMinMaxSizesIgnoringChildren(Node(), border_scrollbar_padding_);
- if (sizes)
- return sizes;
+MinMaxSizesResult NGMathRowLayoutAlgorithm::ComputeMinMaxSizes(
+ const MinMaxSizesInput& child_input) const {
+ if (auto result = CalculateMinMaxSizesIgnoringChildren(
+ Node(), border_scrollbar_padding_))
+ return *result;
- sizes.emplace();
- LayoutUnit child_percentage_resolution_block_size =
- CalculateChildPercentageBlockSizeForMinMax(
- ConstraintSpace(), Node(), border_padding_,
- input.percentage_resolution_block_size);
-
- MinMaxSizesInput child_input(child_percentage_resolution_block_size);
+ MinMaxSizes sizes;
+ bool depends_on_percentage_block_size = false;
for (NGLayoutInputNode child = Node().FirstChild(); child;
child = child.NextSibling()) {
if (child.IsOutOfFlowPositioned())
continue;
- MinMaxSizes child_min_max_sizes =
+ MinMaxSizesResult child_result =
ComputeMinAndMaxContentContribution(Style(), child, child_input);
NGBoxStrut child_margins = ComputeMinMaxMargins(Style(), child);
- child_min_max_sizes += child_margins.InlineSum();
- sizes->max_size += child_min_max_sizes.max_size;
- sizes->min_size += child_min_max_sizes.min_size;
+ child_result.sizes += child_margins.InlineSum();
+
+ sizes += child_result.sizes;
+ depends_on_percentage_block_size |=
+ child_result.depends_on_percentage_block_size;
// TODO(rbuis): Operators can add lspace and rspace.
}
- sizes->max_size = std::max(sizes->max_size, sizes->min_size);
// Due to negative margins, it is possible that we calculated a negative
// intrinsic width. Make sure that we never return a negative width.
- sizes->Encompass(LayoutUnit());
- *sizes += border_scrollbar_padding_.InlineSum();
- return sizes;
+ sizes.Encompass(LayoutUnit());
+
+ DCHECK_LE(sizes.min_size, sizes.max_size);
+ sizes += border_scrollbar_padding_.InlineSum();
+
+ return {sizes, depends_on_percentage_block_size};
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_row_layout_algorithm.h b/chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_row_layout_algorithm.h
index 72b8dd10b40..1463e6256f6 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_row_layout_algorithm.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_row_layout_algorithm.h
@@ -29,8 +29,7 @@ class CORE_EXPORT NGMathRowLayoutAlgorithm
private:
scoped_refptr<const NGLayoutResult> Layout() final;
- base::Optional<MinMaxSizes> ComputeMinMaxSizes(
- const MinMaxSizesInput&) const final;
+ MinMaxSizesResult ComputeMinMaxSizes(const MinMaxSizesInput&) const final;
LogicalSize child_available_size_;
const NGBoxStrut border_padding_;
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_scripts_layout_algorithm.cc b/chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_scripts_layout_algorithm.cc
new file mode 100644
index 00000000000..afdfca8c5b8
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_scripts_layout_algorithm.cc
@@ -0,0 +1,392 @@
+// 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/core/layout/ng/mathml/ng_math_scripts_layout_algorithm.h"
+
+#include "third_party/blink/renderer/core/layout/ng/mathml/ng_math_layout_utils.h"
+#include "third_party/blink/renderer/core/layout/ng/ng_block_break_token.h"
+#include "third_party/blink/renderer/core/layout/ng/ng_box_fragment.h"
+#include "third_party/blink/renderer/core/layout/ng/ng_length_utils.h"
+#include "third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.h"
+
+namespace blink {
+namespace {
+
+using MathConstants = OpenTypeMathSupport::MathConstants;
+
+LayoutUnit GetSpaceAfterScript(const ComputedStyle& style) {
+ return LayoutUnit(MathConstant(style, MathConstants::kSpaceAfterScript)
+ .value_or(style.FontSize() / 5));
+}
+
+// Describes the amount of shift to apply to the sub/sup boxes.
+// Data is populated from the OpenType MATH table.
+// If the OpenType MATH table is not present fallback values are used.
+// https://mathml-refresh.github.io/mathml-core/#base-with-subscript
+// https://mathml-refresh.github.io/mathml-core/#base-with-superscript
+// https://mathml-refresh.github.io/mathml-core/#base-with-subscript-and-superscript
+struct ScriptsVerticalParameters {
+ STACK_ALLOCATED();
+
+ public:
+ LayoutUnit subscript_shift_down;
+ LayoutUnit superscript_shift_up;
+ LayoutUnit superscript_shift_up_cramped;
+ LayoutUnit subscript_baseline_drop_min;
+ LayoutUnit superscript_baseline_drop_max;
+ LayoutUnit sub_superscript_gap_min;
+ LayoutUnit superscript_bottom_min;
+ LayoutUnit subscript_top_max;
+ LayoutUnit superscript_bottom_max_with_subscript;
+};
+
+ScriptsVerticalParameters GetScriptsVerticalParameters(
+ const ComputedStyle& style) {
+ ScriptsVerticalParameters parameters;
+ auto x_height = style.GetFont().PrimaryFont()->GetFontMetrics().XHeight();
+ parameters.subscript_shift_down =
+ LayoutUnit(MathConstant(style, MathConstants::kSubscriptShiftDown)
+ .value_or(x_height / 3));
+ parameters.superscript_shift_up =
+ LayoutUnit(MathConstant(style, MathConstants::kSuperscriptShiftUp)
+ .value_or(x_height));
+ parameters.superscript_shift_up_cramped =
+ LayoutUnit(MathConstant(style, MathConstants::kSuperscriptShiftUpCramped)
+ .value_or(x_height));
+ parameters.subscript_baseline_drop_min =
+ LayoutUnit(MathConstant(style, MathConstants::kSubscriptBaselineDropMin)
+ .value_or(x_height / 2));
+ parameters.superscript_baseline_drop_max =
+ LayoutUnit(MathConstant(style, MathConstants::kSuperscriptBaselineDropMax)
+ .value_or(x_height / 2));
+ parameters.sub_superscript_gap_min =
+ LayoutUnit(MathConstant(style, MathConstants::kSubSuperscriptGapMin)
+ .value_or(style.FontSize() / 5));
+ parameters.superscript_bottom_min =
+ LayoutUnit(MathConstant(style, MathConstants::kSuperscriptBottomMin)
+ .value_or(x_height / 4));
+ parameters.subscript_top_max =
+ LayoutUnit(MathConstant(style, MathConstants::kSubscriptTopMax)
+ .value_or(4 * x_height / 5));
+ parameters.superscript_bottom_max_with_subscript = LayoutUnit(
+ MathConstant(style, MathConstants::kSuperscriptBottomMaxWithSubscript)
+ .value_or(4 * x_height / 5));
+ return parameters;
+}
+
+} // namespace
+
+NGMathScriptsLayoutAlgorithm::NGMathScriptsLayoutAlgorithm(
+ const NGLayoutAlgorithmParams& params)
+ : NGLayoutAlgorithm(params),
+ border_scrollbar_padding_(params.fragment_geometry.border +
+ params.fragment_geometry.scrollbar +
+ params.fragment_geometry.padding) {
+ DCHECK(params.space.IsNewFormattingContext());
+ container_builder_.SetIsNewFormattingContext(
+ params.space.IsNewFormattingContext());
+ container_builder_.SetInitialFragmentGeometry(params.fragment_geometry);
+ child_available_size_ = ShrinkAvailableSize(
+ container_builder_.InitialBorderBoxSize(), border_scrollbar_padding_);
+}
+
+void NGMathScriptsLayoutAlgorithm::GatherChildren(
+ NGBlockNode* base,
+ NGBlockNode* sub,
+ NGBlockNode* sup,
+ NGBoxFragmentBuilder* container_builder) const {
+ auto script_type = Node().ScriptType();
+ for (NGLayoutInputNode child = Node().FirstChild(); child;
+ child = child.NextSibling()) {
+ NGBlockNode block_child = To<NGBlockNode>(child);
+ if (child.IsOutOfFlowPositioned()) {
+ if (container_builder) {
+ container_builder->AddOutOfFlowChildCandidate(
+ block_child, {border_scrollbar_padding_.inline_start,
+ border_scrollbar_padding_.block_start});
+ }
+ continue;
+ }
+ if (!*base) {
+ // All scripted elements must have at least one child.
+ // The first child is the base.
+ *base = block_child;
+ continue;
+ }
+ switch (script_type) {
+ case MathScriptType::kSub:
+ // These elements must have exactly two children.
+ // The second child is a postscript and there are no prescripts.
+ // <msub> base subscript </msub>
+ // <msup> base superscript </msup>
+ DCHECK(!*sub);
+ *sub = block_child;
+ continue;
+ case MathScriptType::kSuper:
+ DCHECK(!*sup);
+ *sup = block_child;
+ continue;
+ case MathScriptType::kSubSup:
+ // These elements must have exactly three children.
+ // The second and third children are postscripts and there are no
+ // prescripts. <msubsup> base subscript superscript </msubsup>
+ if (!*sub) {
+ *sub = block_child;
+ } else {
+ DCHECK(!*sup);
+ *sup = block_child;
+ }
+ continue;
+ default:
+ NOTREACHED();
+ }
+ }
+}
+
+// Determines ascent/descent and shift metrics depending on script type.
+NGMathScriptsLayoutAlgorithm::VerticalMetrics
+NGMathScriptsLayoutAlgorithm::GetVerticalMetrics(
+ const ChildAndMetrics& base_metrics,
+ const ChildAndMetrics& sub_metrics,
+ const ChildAndMetrics& sup_metrics) const {
+ ScriptsVerticalParameters parameters = GetScriptsVerticalParameters(Style());
+ VerticalMetrics metrics;
+
+ MathScriptType type = Node().ScriptType();
+ if (type == MathScriptType::kSub || type == MathScriptType::kSubSup) {
+ metrics.sub_shift =
+ std::max(parameters.subscript_shift_down,
+ base_metrics.descent + parameters.subscript_baseline_drop_min);
+ }
+ LayoutUnit shift_up = parameters.superscript_shift_up;
+ if (type == MathScriptType::kSuper || type == MathScriptType::kSubSup) {
+ // TODO(rbuis): test cramped for super/subSup.
+ metrics.sup_shift =
+ std::max(shift_up, base_metrics.ascent -
+ parameters.superscript_baseline_drop_max);
+ }
+
+ switch (type) {
+ case MathScriptType::kSub: {
+ metrics.descent = sub_metrics.descent;
+ metrics.sub_shift = std::max(
+ metrics.sub_shift, sub_metrics.ascent - parameters.subscript_top_max);
+ } break;
+ case MathScriptType::kSuper: {
+ metrics.ascent = sup_metrics.ascent;
+ metrics.sup_shift =
+ std::max(metrics.sup_shift,
+ parameters.superscript_bottom_min + sup_metrics.descent);
+ } break;
+ case MathScriptType::kSubSup: {
+ metrics.ascent = std::max(metrics.ascent, sup_metrics.ascent);
+ metrics.descent = std::max(metrics.descent, sub_metrics.descent);
+ LayoutUnit sub_script_shift = std::max(
+ parameters.subscript_shift_down,
+ base_metrics.descent + parameters.subscript_baseline_drop_min);
+ sub_script_shift = std::max(
+ sub_script_shift, sub_metrics.ascent - parameters.subscript_top_max);
+ LayoutUnit sup_script_shift =
+ std::max(shift_up, base_metrics.ascent -
+ parameters.superscript_baseline_drop_max);
+ sup_script_shift =
+ std::max(sup_script_shift,
+ parameters.superscript_bottom_min + sup_metrics.descent);
+
+ LayoutUnit sub_super_script_gap =
+ (sub_script_shift - sub_metrics.ascent) +
+ (sup_script_shift - sup_metrics.descent);
+ if (sub_super_script_gap < parameters.sub_superscript_gap_min) {
+ // First, we try and push the superscript up.
+ LayoutUnit delta = parameters.superscript_bottom_max_with_subscript -
+ (sup_script_shift - sup_metrics.descent);
+ if (delta > 0) {
+ delta = std::min(
+ delta, parameters.sub_superscript_gap_min - sub_super_script_gap);
+ sup_script_shift += delta;
+ sub_super_script_gap += delta;
+ }
+ // If that is not enough, we push the subscript down.
+ if (sub_super_script_gap < parameters.sub_superscript_gap_min) {
+ sub_script_shift +=
+ parameters.sub_superscript_gap_min - sub_super_script_gap;
+ }
+ }
+
+ metrics.sub_shift = std::max(metrics.sub_shift, sub_script_shift);
+ metrics.sup_shift = std::max(metrics.sup_shift, sup_script_shift);
+ } break;
+ case MathScriptType::kOver:
+ case MathScriptType::kUnder:
+ case MathScriptType::kUnderOver:
+ // TODO(rbuis): implement movablelimits.
+ NOTREACHED();
+ break;
+ }
+
+ return metrics;
+}
+
+NGMathScriptsLayoutAlgorithm::ChildAndMetrics
+NGMathScriptsLayoutAlgorithm::LayoutAndGetMetrics(NGBlockNode child) const {
+ ChildAndMetrics child_and_metrics;
+ auto constraint_space = CreateConstraintSpaceForMathChild(
+ Node(), child_available_size_, ConstraintSpace(), child);
+ child_and_metrics.result =
+ child.Layout(constraint_space, nullptr /*break_token*/);
+ NGBoxFragment fragment(
+ ConstraintSpace().GetWritingMode(), ConstraintSpace().Direction(),
+ To<NGPhysicalBoxFragment>(child_and_metrics.result->PhysicalFragment()));
+ child_and_metrics.inline_size = fragment.InlineSize();
+ child_and_metrics.margins =
+ ComputeMarginsFor(constraint_space, child.Style(), ConstraintSpace());
+ child_and_metrics.ascent = fragment.Baseline().value_or(fragment.BlockSize());
+ child_and_metrics.descent = fragment.BlockSize() - child_and_metrics.ascent +
+ child_and_metrics.margins.block_end;
+ child_and_metrics.ascent += child_and_metrics.margins.block_start;
+ return child_and_metrics;
+}
+
+scoped_refptr<const NGLayoutResult> NGMathScriptsLayoutAlgorithm::Layout() {
+ DCHECK(!BreakToken());
+
+ NGBlockNode base = nullptr;
+ NGBlockNode sub = nullptr;
+ NGBlockNode sup = nullptr;
+ GatherChildren(&base, &sub, &sup, &container_builder_);
+
+ ChildAndMetrics base_metrics = LayoutAndGetMetrics(base);
+ ChildAndMetrics sub_metrics, sup_metrics;
+ if (sub)
+ sub_metrics = LayoutAndGetMetrics(sub);
+ if (sup)
+ sup_metrics = LayoutAndGetMetrics(sup);
+ VerticalMetrics metrics =
+ GetVerticalMetrics(base_metrics, sub_metrics, sup_metrics);
+
+ LayoutUnit ascent =
+ std::max(base_metrics.ascent, metrics.ascent + metrics.sup_shift) +
+ border_scrollbar_padding_.block_start;
+ LayoutUnit descent =
+ std::max(base_metrics.descent, metrics.descent + metrics.sub_shift);
+ // TODO(rbuis): take into account italic correction.
+ LayoutUnit inline_offset = border_scrollbar_padding_.inline_start +
+ base_metrics.margins.inline_start;
+
+ LogicalOffset base_offset(
+ inline_offset,
+ ascent - base_metrics.ascent + base_metrics.margins.block_start);
+ container_builder_.AddChild(base_metrics.result->PhysicalFragment(),
+ base_offset);
+ base.StoreMargins(ConstraintSpace(), base_metrics.margins);
+ inline_offset += base_metrics.inline_size + base_metrics.margins.inline_end;
+
+ if (sub) {
+ LogicalOffset sub_offset(inline_offset + sub_metrics.margins.inline_start,
+ ascent + metrics.sub_shift - sub_metrics.ascent +
+ sub_metrics.margins.block_start);
+ container_builder_.AddChild(sub_metrics.result->PhysicalFragment(),
+ sub_offset);
+ sub.StoreMargins(ConstraintSpace(), sub_metrics.margins);
+ }
+ if (sup) {
+ LogicalOffset sup_offset(inline_offset + sup_metrics.margins.inline_start,
+ ascent - metrics.sup_shift - sup_metrics.ascent +
+ sup_metrics.margins.block_start);
+ container_builder_.AddChild(sup_metrics.result->PhysicalFragment(),
+ sup_offset);
+ sup.StoreMargins(ConstraintSpace(), sup_metrics.margins);
+ }
+
+ container_builder_.SetBaseline(ascent);
+
+ LayoutUnit intrinsic_block_size =
+ ascent + descent + border_scrollbar_padding_.block_end;
+
+ LayoutUnit block_size = ComputeBlockSizeForFragment(
+ ConstraintSpace(), Style(), border_scrollbar_padding_,
+ intrinsic_block_size,
+ container_builder_.InitialBorderBoxSize().inline_size);
+
+ container_builder_.SetIntrinsicBlockSize(intrinsic_block_size);
+ container_builder_.SetBlockSize(block_size);
+
+ NGOutOfFlowLayoutPart(Node(), ConstraintSpace(), container_builder_.Borders(),
+ &container_builder_)
+ .Run();
+
+ return container_builder_.ToBoxFragment();
+}
+
+MinMaxSizesResult NGMathScriptsLayoutAlgorithm::ComputeMinMaxSizes(
+ const MinMaxSizesInput& child_input) const {
+ if (auto result = CalculateMinMaxSizesIgnoringChildren(
+ Node(), border_scrollbar_padding_))
+ return *result;
+
+ NGBlockNode base = nullptr;
+ NGBlockNode sub = nullptr;
+ NGBlockNode sup = nullptr;
+ GatherChildren(&base, &sub, &sup);
+
+ MinMaxSizes sizes;
+ bool depends_on_percentage_block_size = false;
+
+ MinMaxSizesResult base_result =
+ ComputeMinAndMaxContentContribution(Style(), base, child_input);
+ base_result.sizes += ComputeMinMaxMargins(Style(), base).InlineSum() +
+ GetSpaceAfterScript(Style());
+
+ sizes = base_result.sizes;
+ depends_on_percentage_block_size |=
+ base_result.depends_on_percentage_block_size;
+
+ switch (Node().ScriptType()) {
+ case MathScriptType::kSub:
+ case MathScriptType::kSuper: {
+ // TODO(fwang): Take italic correction into account.
+ auto first_post_script = sub ? sub : sup;
+ auto first_post_script_result = ComputeMinAndMaxContentContribution(
+ Style(), first_post_script, child_input);
+ first_post_script_result.sizes +=
+ ComputeMinMaxMargins(Style(), first_post_script).InlineSum();
+
+ sizes += first_post_script_result.sizes;
+ depends_on_percentage_block_size |=
+ first_post_script_result.depends_on_percentage_block_size;
+ break;
+ }
+ case MathScriptType::kSubSup: {
+ // TODO(fwang): Take italic correction into account.
+ MinMaxSizes sub_sup_pair_size;
+ auto sub_result =
+ ComputeMinAndMaxContentContribution(Style(), sub, child_input);
+ sub_result.sizes += ComputeMinMaxMargins(Style(), sub).InlineSum();
+ sub_sup_pair_size.Encompass(sub_result.sizes);
+
+ auto sup_result =
+ ComputeMinAndMaxContentContribution(Style(), sup, child_input);
+ sup_result.sizes += ComputeMinMaxMargins(Style(), sup).InlineSum();
+ sub_sup_pair_size.Encompass(sup_result.sizes);
+
+ sizes += sub_sup_pair_size;
+ depends_on_percentage_block_size |=
+ sub_result.depends_on_percentage_block_size;
+ depends_on_percentage_block_size |=
+ sup_result.depends_on_percentage_block_size;
+ break;
+ }
+ case MathScriptType::kUnder:
+ case MathScriptType::kOver:
+ case MathScriptType::kUnderOver:
+ // TODO(rbuis): implement movablelimits.
+ NOTREACHED();
+ break;
+ }
+ sizes += border_scrollbar_padding_.InlineSum();
+
+ return {sizes, depends_on_percentage_block_size};
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_scripts_layout_algorithm.h b/chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_scripts_layout_algorithm.h
new file mode 100644
index 00000000000..8d8f34ea40c
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_scripts_layout_algorithm.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_CORE_LAYOUT_NG_MATHML_NG_MATH_SCRIPTS_LAYOUT_ALGORITHM_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_MATHML_NG_MATH_SCRIPTS_LAYOUT_ALGORITHM_H_
+
+#include "third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.h"
+#include "third_party/blink/renderer/core/layout/ng/ng_layout_algorithm.h"
+#include "third_party/blink/renderer/core/mathml/mathml_scripts_element.h"
+
+namespace blink {
+
+class NGBlockNode;
+
+// This algorithm handles msub, msup and msubsup elements.
+class CORE_EXPORT NGMathScriptsLayoutAlgorithm
+ : public NGLayoutAlgorithm<NGBlockNode,
+ NGBoxFragmentBuilder,
+ NGBlockBreakToken> {
+ public:
+ explicit NGMathScriptsLayoutAlgorithm(const NGLayoutAlgorithmParams& params);
+
+ private:
+ void GatherChildren(NGBlockNode* base,
+ NGBlockNode* sup,
+ NGBlockNode* sub,
+ NGBoxFragmentBuilder* = nullptr) const;
+
+ MinMaxSizesResult ComputeMinMaxSizes(const MinMaxSizesInput&) const final;
+
+ struct ChildAndMetrics {
+ STACK_ALLOCATED();
+
+ public:
+ scoped_refptr<const NGLayoutResult> result;
+ LayoutUnit ascent;
+ LayoutUnit descent;
+ LayoutUnit inline_size;
+ NGBoxStrut margins;
+ };
+
+ ChildAndMetrics LayoutAndGetMetrics(NGBlockNode child) const;
+
+ struct VerticalMetrics {
+ STACK_ALLOCATED();
+
+ public:
+ LayoutUnit sub_shift;
+ LayoutUnit sup_shift;
+ LayoutUnit ascent;
+ LayoutUnit descent;
+ NGBoxStrut margins;
+ };
+ VerticalMetrics GetVerticalMetrics(const ChildAndMetrics& base_metrics,
+ const ChildAndMetrics& sub_metrics,
+ const ChildAndMetrics& sup_metrics) const;
+
+ scoped_refptr<const NGLayoutResult> Layout() final;
+
+ LogicalSize child_available_size_;
+ const NGBoxStrut border_scrollbar_padding_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_MATHML_NG_MATH_SCRIPTS_LAYOUT_ALGORITHM_H_
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_space_layout_algorithm.cc b/chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_space_layout_algorithm.cc
index 4abfa765870..6dad93301a8 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_space_layout_algorithm.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_space_layout_algorithm.cc
@@ -23,7 +23,8 @@ scoped_refptr<const NGLayoutResult> NGMathSpaceLayoutAlgorithm::Layout() {
DCHECK(!BreakToken());
LayoutUnit block_size = ComputeBlockSizeForFragment(
- ConstraintSpace(), Style(), border_padding_, border_padding_.BlockSum());
+ ConstraintSpace(), Style(), border_padding_, border_padding_.BlockSum(),
+ container_builder_.InitialBorderBoxSize().inline_size);
container_builder_.SetIntrinsicBlockSize(border_padding_.BlockSum());
container_builder_.SetBlockSize(block_size);
@@ -34,9 +35,16 @@ scoped_refptr<const NGLayoutResult> NGMathSpaceLayoutAlgorithm::Layout() {
return container_builder_.ToBoxFragment();
}
-base::Optional<MinMaxSizes> NGMathSpaceLayoutAlgorithm::ComputeMinMaxSizes(
- const MinMaxSizesInput& input) const {
- return CalculateMinMaxSizesIgnoringChildren(Node(), border_padding_);
+MinMaxSizesResult NGMathSpaceLayoutAlgorithm::ComputeMinMaxSizes(
+ const MinMaxSizesInput&) const {
+ if (auto result =
+ CalculateMinMaxSizesIgnoringChildren(Node(), border_padding_))
+ return *result;
+
+ MinMaxSizes sizes;
+ sizes += border_padding_.InlineSum();
+
+ return {sizes, /* depends_on_percentage_block_size */ false};
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_space_layout_algorithm.h b/chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_space_layout_algorithm.h
index 7b493ef0b17..838d058f895 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_space_layout_algorithm.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_space_layout_algorithm.h
@@ -20,8 +20,7 @@ class CORE_EXPORT NGMathSpaceLayoutAlgorithm
private:
scoped_refptr<const NGLayoutResult> Layout() final;
- base::Optional<MinMaxSizes> ComputeMinMaxSizes(
- const MinMaxSizesInput&) const final;
+ MinMaxSizesResult ComputeMinMaxSizes(const MinMaxSizesInput&) const final;
const NGBoxStrut border_padding_;
};
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_under_over_layout_algorithm.cc b/chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_under_over_layout_algorithm.cc
new file mode 100644
index 00000000000..1b419ddb83e
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_under_over_layout_algorithm.cc
@@ -0,0 +1,286 @@
+// 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/core/layout/ng/mathml/ng_math_under_over_layout_algorithm.h"
+
+#include "third_party/blink/renderer/core/layout/ng/mathml/ng_math_layout_utils.h"
+#include "third_party/blink/renderer/core/layout/ng/ng_block_break_token.h"
+#include "third_party/blink/renderer/core/layout/ng/ng_box_fragment.h"
+#include "third_party/blink/renderer/core/layout/ng/ng_length_utils.h"
+#include "third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.h"
+#include "third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h"
+#include "third_party/blink/renderer/core/mathml/mathml_under_over_element.h"
+
+namespace blink {
+namespace {
+
+// Describes the amount to shift to apply to the under/over boxes.
+// Data is populated from the OpenType MATH table.
+// If the OpenType MATH table is not present fallback values are used.
+// https://mathml-refresh.github.io/mathml-core/#base-with-underscript
+// https://mathml-refresh.github.io/mathml-core/#base-with-overscript
+struct UnderOverVerticalParameters {
+ bool use_under_over_bar_fallback;
+ LayoutUnit under_gap_min;
+ LayoutUnit over_gap_min;
+ LayoutUnit under_shift_min;
+ LayoutUnit over_shift_min;
+ LayoutUnit under_extra_descender;
+ LayoutUnit over_extra_ascender;
+ LayoutUnit accent_base_height;
+};
+
+UnderOverVerticalParameters GetUnderOverVerticalParameters(
+ const ComputedStyle& style) {
+ UnderOverVerticalParameters parameters;
+
+ if (!OpenTypeMathSupport::HasMathData(
+ style.GetFont().PrimaryFont()->PlatformData().GetHarfBuzzFace())) {
+ // The MATH table specification does not really provide any suggestions,
+ // except for some underbar/overbar values and AccentBaseHeight.
+ LayoutUnit default_line_thickness =
+ LayoutUnit(RuleThicknessFallback(style));
+ parameters.under_gap_min = 3 * default_line_thickness;
+ parameters.over_gap_min = 3 * default_line_thickness;
+ parameters.under_extra_descender = default_line_thickness;
+ parameters.over_extra_ascender = default_line_thickness;
+ parameters.accent_base_height =
+ LayoutUnit(style.GetFont().PrimaryFont()->GetFontMetrics().XHeight());
+ parameters.use_under_over_bar_fallback = true;
+ return parameters;
+ }
+
+ // The base is a large operator so we read UpperLimit/LowerLimit constants
+ // from the MATH table.
+ parameters.under_gap_min = LayoutUnit(
+ MathConstant(style, OpenTypeMathSupport::MathConstants::kLowerLimitGapMin)
+ .value_or(0));
+ parameters.over_gap_min = LayoutUnit(
+ MathConstant(style, OpenTypeMathSupport::MathConstants::kUpperLimitGapMin)
+ .value_or(0));
+ parameters.under_shift_min = LayoutUnit(
+ MathConstant(
+ style, OpenTypeMathSupport::MathConstants::kLowerLimitBaselineDropMin)
+ .value_or(0));
+ parameters.over_shift_min = LayoutUnit(
+ MathConstant(
+ style, OpenTypeMathSupport::MathConstants::kUpperLimitBaselineRiseMin)
+ .value_or(0));
+ parameters.use_under_over_bar_fallback = false;
+ return parameters;
+}
+
+} // namespace
+
+NGMathUnderOverLayoutAlgorithm::NGMathUnderOverLayoutAlgorithm(
+ const NGLayoutAlgorithmParams& params)
+ : NGLayoutAlgorithm(params),
+ border_scrollbar_padding_(params.fragment_geometry.border +
+ params.fragment_geometry.padding +
+ params.fragment_geometry.scrollbar) {
+ DCHECK(params.space.IsNewFormattingContext());
+ container_builder_.SetIsNewFormattingContext(
+ params.space.IsNewFormattingContext());
+ container_builder_.SetInitialFragmentGeometry(params.fragment_geometry);
+}
+
+void NGMathUnderOverLayoutAlgorithm::GatherChildren(NGBlockNode* base,
+ NGBlockNode* over,
+ NGBlockNode* under) {
+ auto script_type = Node().ScriptType();
+ for (NGLayoutInputNode child = Node().FirstChild(); child;
+ child = child.NextSibling()) {
+ NGBlockNode block_child = To<NGBlockNode>(child);
+ if (child.IsOutOfFlowPositioned()) {
+ container_builder_.AddOutOfFlowChildCandidate(
+ block_child, {border_scrollbar_padding_.inline_start,
+ border_scrollbar_padding_.block_start});
+ continue;
+ }
+ if (!*base) {
+ *base = block_child;
+ continue;
+ }
+ switch (script_type) {
+ case MathScriptType::kUnder:
+ DCHECK(!*under);
+ *under = block_child;
+ break;
+ case MathScriptType::kOver:
+ DCHECK(!*over);
+ *over = block_child;
+ break;
+ case MathScriptType::kUnderOver:
+ if (!*under) {
+ *under = block_child;
+ continue;
+ }
+ DCHECK(!*over);
+ *over = block_child;
+ break;
+ default:
+ NOTREACHED();
+ }
+ }
+}
+
+scoped_refptr<const NGLayoutResult> NGMathUnderOverLayoutAlgorithm::Layout() {
+ DCHECK(!BreakToken());
+ DCHECK(IsValidMathMLScript(Node()));
+
+ NGBlockNode base = nullptr;
+ NGBlockNode over = nullptr;
+ NGBlockNode under = nullptr;
+ GatherChildren(&base, &over, &under);
+
+ const LogicalSize border_box_size = container_builder_.InitialBorderBoxSize();
+ auto child_available_size =
+ ShrinkAvailableSize(border_box_size, border_scrollbar_padding_);
+
+ LayoutUnit block_offset = border_scrollbar_padding_.block_start;
+ UnderOverVerticalParameters parameters =
+ GetUnderOverVerticalParameters(Style());
+ // TODO(rbuis): handle stretchy operators.
+ // TODO(rbuis): handle accent.
+
+ // All children are positioned centered relative to the container (and
+ // therefore centered relative to themselves).
+ if (over) {
+ auto over_space = CreateConstraintSpaceForMathChild(
+ Node(), child_available_size, ConstraintSpace(), over);
+ scoped_refptr<const NGLayoutResult> over_layout_result =
+ over.Layout(over_space);
+ NGBoxStrut over_margins =
+ ComputeMarginsFor(over_space, over.Style(), ConstraintSpace());
+ NGBoxFragment over_fragment(
+ ConstraintSpace().GetWritingMode(), ConstraintSpace().Direction(),
+ To<NGPhysicalBoxFragment>(over_layout_result->PhysicalFragment()));
+ block_offset += parameters.over_extra_ascender + over_margins.block_start;
+ LogicalOffset over_offset = {
+ border_scrollbar_padding_.inline_start + over_margins.inline_start +
+ (child_available_size.inline_size -
+ (over_fragment.InlineSize() + over_margins.InlineSum())) /
+ 2,
+ block_offset};
+ container_builder_.AddChild(over_layout_result->PhysicalFragment(),
+ over_offset);
+ over.StoreMargins(ConstraintSpace(), over_margins);
+ if (parameters.use_under_over_bar_fallback) {
+ block_offset += over_fragment.BlockSize();
+ block_offset += parameters.over_gap_min;
+ } else {
+ LayoutUnit over_ascent =
+ over_fragment.Baseline().value_or(over_fragment.BlockSize());
+ block_offset +=
+ std::max(over_fragment.BlockSize() + parameters.over_gap_min,
+ over_ascent + parameters.over_shift_min);
+ }
+ block_offset += over_margins.block_end;
+ }
+
+ auto base_space = CreateConstraintSpaceForMathChild(
+ Node(), child_available_size, ConstraintSpace(), base);
+ auto base_layout_result = base.Layout(base_space);
+ auto base_margins =
+ ComputeMarginsFor(base_space, base.Style(), ConstraintSpace());
+
+ NGBoxFragment base_fragment(
+ ConstraintSpace().GetWritingMode(), ConstraintSpace().Direction(),
+ To<NGPhysicalBoxFragment>(base_layout_result->PhysicalFragment()));
+
+ block_offset += base_margins.block_start;
+ LogicalOffset base_offset = {
+ border_scrollbar_padding_.inline_start + base_margins.inline_start +
+ (child_available_size.inline_size -
+ (base_fragment.InlineSize() + base_margins.InlineSum())) /
+ 2,
+ block_offset};
+ container_builder_.AddChild(base_layout_result->PhysicalFragment(),
+ base_offset);
+ base.StoreMargins(ConstraintSpace(), base_margins);
+ block_offset += base_fragment.BlockSize() + base_margins.block_end;
+
+ if (under) {
+ auto under_space = CreateConstraintSpaceForMathChild(
+ Node(), child_available_size, ConstraintSpace(), under);
+ scoped_refptr<const NGLayoutResult> under_layout_result =
+ under.Layout(under_space);
+ NGBoxStrut under_margins =
+ ComputeMarginsFor(under_space, under.Style(), ConstraintSpace());
+ NGBoxFragment under_fragment(
+ ConstraintSpace().GetWritingMode(), ConstraintSpace().Direction(),
+ To<NGPhysicalBoxFragment>(under_layout_result->PhysicalFragment()));
+ block_offset += under_margins.block_start;
+ if (parameters.use_under_over_bar_fallback) {
+ block_offset += parameters.under_gap_min;
+ } else {
+ LayoutUnit under_ascent =
+ under_fragment.Baseline().value_or(under_fragment.BlockSize());
+ block_offset += std::max(parameters.under_gap_min,
+ parameters.under_shift_min - under_ascent);
+ }
+ LogicalOffset under_offset = {
+ border_scrollbar_padding_.inline_start + under_margins.inline_start +
+ (child_available_size.inline_size -
+ (under_fragment.InlineSize() + under_margins.InlineSum())) /
+ 2,
+ block_offset};
+ block_offset += under_fragment.BlockSize();
+ block_offset += parameters.under_extra_descender;
+ container_builder_.AddChild(under_layout_result->PhysicalFragment(),
+ under_offset);
+ under.StoreMargins(ConstraintSpace(), under_margins);
+ block_offset += under_margins.block_end;
+ }
+
+ LayoutUnit base_ascent =
+ base_fragment.Baseline().value_or(base_fragment.BlockSize());
+ container_builder_.SetBaseline(base_offset.block_offset + base_ascent);
+
+ block_offset += border_scrollbar_padding_.block_end;
+
+ LayoutUnit block_size = ComputeBlockSizeForFragment(
+ ConstraintSpace(), Style(), border_scrollbar_padding_, block_offset,
+ border_box_size.inline_size);
+
+ container_builder_.SetIntrinsicBlockSize(block_offset);
+ container_builder_.SetBlockSize(block_size);
+
+ NGOutOfFlowLayoutPart(Node(), ConstraintSpace(), container_builder_.Borders(),
+ &container_builder_)
+ .Run();
+
+ return container_builder_.ToBoxFragment();
+}
+
+MinMaxSizesResult NGMathUnderOverLayoutAlgorithm::ComputeMinMaxSizes(
+ const MinMaxSizesInput& child_input) const {
+ DCHECK(IsValidMathMLScript(Node()));
+
+ if (auto result = CalculateMinMaxSizesIgnoringChildren(
+ Node(), border_scrollbar_padding_))
+ return *result;
+
+ MinMaxSizes sizes;
+ bool depends_on_percentage_block_size = false;
+
+ for (NGLayoutInputNode child = Node().FirstChild(); child;
+ child = child.NextSibling()) {
+ if (child.IsOutOfFlowPositioned())
+ continue;
+ auto child_result =
+ ComputeMinAndMaxContentContribution(Style(), child, child_input);
+ NGBoxStrut margins = ComputeMinMaxMargins(Style(), child);
+ child_result.sizes += margins.InlineSum();
+
+ sizes.Encompass(child_result.sizes);
+ depends_on_percentage_block_size |=
+ child_result.depends_on_percentage_block_size;
+ }
+
+ sizes += border_scrollbar_padding_.InlineSum();
+ return {sizes, depends_on_percentage_block_size};
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_under_over_layout_algorithm.h b/chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_under_over_layout_algorithm.h
new file mode 100644
index 00000000000..a324e1b6032
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/layout/ng/mathml/ng_math_under_over_layout_algorithm.h
@@ -0,0 +1,35 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_MATHML_NG_MATH_UNDER_OVER_LAYOUT_ALGORITHM_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_MATHML_NG_MATH_UNDER_OVER_LAYOUT_ALGORITHM_H_
+
+#include "third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.h"
+#include "third_party/blink/renderer/core/layout/ng/ng_layout_algorithm.h"
+
+namespace blink {
+
+class CORE_EXPORT NGMathUnderOverLayoutAlgorithm
+ : public NGLayoutAlgorithm<NGBlockNode,
+ NGBoxFragmentBuilder,
+ NGBlockBreakToken> {
+ public:
+ explicit NGMathUnderOverLayoutAlgorithm(
+ const NGLayoutAlgorithmParams& params);
+
+ scoped_refptr<const NGLayoutResult> Layout() override;
+
+ MinMaxSizesResult ComputeMinMaxSizes(const MinMaxSizesInput&) const override;
+
+ private:
+ void GatherChildren(NGBlockNode* base,
+ NGBlockNode* second,
+ NGBlockNode* third);
+
+ const NGBoxStrut border_scrollbar_padding_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_MATHML_NG_MATH_UNDER_OVER_LAYOUT_ALGORITHM_H_
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.cc b/chromium/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.cc
index 9d0e5660942..ab6b62882b8 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.cc
@@ -11,6 +11,7 @@
#include "base/optional.h"
#include "third_party/blink/renderer/core/frame/web_feature.h"
#include "third_party/blink/renderer/core/layout/layout_object.h"
+#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_physical_line_box_fragment.h"
#include "third_party/blink/renderer/core/layout/ng/list/ng_unpositioned_list_marker.h"
@@ -37,6 +38,98 @@
namespace blink {
namespace {
+// Returns the logical bottom offset of the last line text, relative to
+// |container| origin. This is used to decide ruby annotation box position.
+//
+// TODO(layout-dev): Using ScrollableOverflow() is same as legacy
+// LayoutRubyRun. However its result is not good with some fonts/platforms.
+LayoutUnit LastLineTextLogicalBottom(const NGPhysicalBoxFragment& container,
+ LayoutUnit default_value) {
+ const ComputedStyle& container_style = container.Style();
+ if (RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()) {
+ if (!container.Items())
+ return default_value;
+ NGInlineCursor cursor(*container.Items());
+ cursor.MoveToLastLine();
+ const auto* line_item = cursor.CurrentItem();
+ if (!line_item)
+ return default_value;
+ DCHECK_EQ(line_item->Type(), NGFragmentItem::kLine);
+ DCHECK(line_item->LineBoxFragment());
+ PhysicalRect line_rect =
+ line_item->LineBoxFragment()->ScrollableOverflowForLine(
+ container, container_style, *line_item, cursor);
+ return line_rect
+ .ConvertToLogical(container_style.GetWritingMode(),
+ container_style.Direction(), container.Size(),
+ cursor.Current().Size())
+ .BlockEndOffset();
+ }
+
+ const NGPhysicalLineBoxFragment* last_line = nullptr;
+ PhysicalOffset last_line_offset;
+ for (const auto& child_link : container.PostLayoutChildren()) {
+ if (const auto* maybe_line =
+ DynamicTo<NGPhysicalLineBoxFragment>(*child_link)) {
+ last_line = maybe_line;
+ last_line_offset = child_link.offset;
+ }
+ }
+ if (!last_line)
+ return default_value;
+ PhysicalRect line_rect =
+ last_line->ScrollableOverflow(container, container_style);
+ line_rect.Move(last_line_offset);
+ return line_rect
+ .ConvertToLogical(container_style.GetWritingMode(),
+ container_style.Direction(), container.Size(),
+ last_line->Size())
+ .BlockEndOffset();
+}
+
+// Returns the logical top offset of the first line text, relative to
+// |container| origin. This is used to decide ruby annotation box position.
+//
+// TODO(layout-dev): Using ScrollableOverflow() is same as legacy
+// LayoutRubyRun. However its result is not good with some fonts/platforms.
+LayoutUnit FirstLineTextLogicalTop(const NGPhysicalBoxFragment& container,
+ LayoutUnit default_value) {
+ const ComputedStyle& container_style = container.Style();
+ if (RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()) {
+ if (!container.Items())
+ return default_value;
+ NGInlineCursor cursor(*container.Items());
+ cursor.MoveToFirstLine();
+ const auto* line_item = cursor.CurrentItem();
+ if (!line_item)
+ return default_value;
+ DCHECK_EQ(line_item->Type(), NGFragmentItem::kLine);
+ DCHECK(line_item->LineBoxFragment());
+ PhysicalRect line_rect =
+ line_item->LineBoxFragment()->ScrollableOverflowForLine(
+ container, container_style, *line_item, cursor);
+ return line_rect
+ .ConvertToLogical(container_style.GetWritingMode(),
+ container_style.Direction(), container.Size(),
+ cursor.Current().Size())
+ .offset.block_offset;
+ }
+
+ for (const auto& child_link : container.PostLayoutChildren()) {
+ if (const auto* line = DynamicTo<NGPhysicalLineBoxFragment>(*child_link)) {
+ PhysicalRect line_rect =
+ line->ScrollableOverflow(container, container_style);
+ line_rect.Move(child_link.offset);
+ return line_rect
+ .ConvertToLogical(container_style.GetWritingMode(),
+ container_style.Direction(), container.Size(),
+ line->Size())
+ .offset.block_offset;
+ }
+ }
+ return default_value;
+}
+
inline scoped_refptr<const NGLayoutResult> LayoutBlockChild(
const NGConstraintSpace& space,
const NGBreakToken* break_token,
@@ -179,10 +272,10 @@ NGBlockLayoutAlgorithm::NGBlockLayoutAlgorithm(
params.fragment_geometry.padding),
border_scrollbar_padding_(border_padding_ +
params.fragment_geometry.scrollbar),
+ previous_result_(params.previous_result),
is_resuming_(IsResumingLayout(params.break_token)),
exclusion_space_(params.space.ExclusionSpace()),
lines_until_clamp_(params.space.LinesUntilClamp()),
- force_truncate_at_line_clamp_(params.space.ForceTruncateAtLineClamp()),
early_break_(params.early_break) {
AdjustForFragmentation(BreakToken(), &border_scrollbar_padding_);
container_builder_.SetIsNewFormattingContext(
@@ -198,18 +291,14 @@ void NGBlockLayoutAlgorithm::SetBoxType(NGPhysicalFragment::NGBoxType type) {
container_builder_.SetBoxType(type);
}
-base::Optional<MinMaxSizes> NGBlockLayoutAlgorithm::ComputeMinMaxSizes(
+MinMaxSizesResult NGBlockLayoutAlgorithm::ComputeMinMaxSizes(
const MinMaxSizesInput& input) const {
- base::Optional<MinMaxSizes> sizes =
- CalculateMinMaxSizesIgnoringChildren(node_, border_scrollbar_padding_);
- if (sizes)
- return sizes;
+ if (auto result = CalculateMinMaxSizesIgnoringChildren(
+ node_, border_scrollbar_padding_))
+ return *result;
- sizes.emplace();
- LayoutUnit child_percentage_resolution_block_size =
- CalculateChildPercentageBlockSizeForMinMax(
- ConstraintSpace(), Node(), border_padding_,
- input.percentage_resolution_block_size);
+ MinMaxSizes sizes;
+ bool depends_on_percentage_block_size = false;
const TextDirection direction = Style().Direction();
LayoutUnit float_left_inline_size = input.float_left_inline_size;
@@ -217,6 +306,8 @@ base::Optional<MinMaxSizes> NGBlockLayoutAlgorithm::ComputeMinMaxSizes(
for (NGLayoutInputNode child = Node().FirstChild(); child;
child = child.NextSibling()) {
+ // We don't check IsRubyText() here intentionally. RubyText width should
+ // affect this width.
if (child.IsOutOfFlowPositioned() ||
(child.IsColumnSpanAll() && ConstraintSpace().IsInColumnBfc()))
continue;
@@ -236,7 +327,7 @@ base::Optional<MinMaxSizes> NGBlockLayoutAlgorithm::ComputeMinMaxSizes(
float_left_inline_size + float_right_inline_size;
if (child_clear != EClear::kNone)
- sizes->max_size = std::max(sizes->max_size, float_inline_size);
+ sizes.max_size = std::max(sizes.max_size, float_inline_size);
if (child_clear == EClear::kBoth || child_clear == EClear::kLeft)
float_left_inline_size = LayoutUnit();
@@ -245,13 +336,13 @@ base::Optional<MinMaxSizes> NGBlockLayoutAlgorithm::ComputeMinMaxSizes(
float_right_inline_size = LayoutUnit();
}
- MinMaxSizesInput child_input(child_percentage_resolution_block_size);
+ MinMaxSizesInput child_input(input.percentage_resolution_block_size);
if (child.IsInline() || child.IsAnonymousBlock()) {
child_input.float_left_inline_size = float_left_inline_size;
child_input.float_right_inline_size = float_right_inline_size;
}
- MinMaxSizes child_sizes;
+ MinMaxSizesResult child_result;
if (child.IsInline()) {
// From |NGBlockLayoutAlgorithm| perspective, we can handle |NGInlineNode|
// almost the same as |NGBlockNode|, because an |NGInlineNode| includes
@@ -259,13 +350,14 @@ base::Optional<MinMaxSizes> NGBlockLayoutAlgorithm::ComputeMinMaxSizes(
// an anonymous box that contains all line boxes.
// |NextSibling| returns the next block sibling, or nullptr, skipping all
// following inline siblings and descendants.
- child_sizes =
+ child_result =
child.ComputeMinMaxSizes(Style().GetWritingMode(), child_input);
} else {
- child_sizes =
+ child_result =
ComputeMinAndMaxContentContribution(Style(), child, child_input);
}
- DCHECK_LE(child_sizes.min_size, child_sizes.max_size) << child.ToString();
+ DCHECK_LE(child_result.sizes.min_size, child_result.sizes.max_size)
+ << child.ToString();
// Determine the max inline contribution of the child.
NGBoxStrut margins = ComputeMinMaxMargins(Style(), child);
@@ -274,7 +366,8 @@ base::Optional<MinMaxSizes> NGBlockLayoutAlgorithm::ComputeMinMaxSizes(
if (child.IsFloating()) {
// A float adds to its inline size to the current "line". The new max
// inline contribution is just the sum of all the floats on that "line".
- LayoutUnit float_inline_size = child_sizes.max_size + margins.InlineSum();
+ LayoutUnit float_inline_size =
+ child_result.sizes.max_size + margins.InlineSum();
// float_inline_size is negative when the float is completely outside of
// the content area, by e.g., negative margins. Such floats do not affect
@@ -309,19 +402,26 @@ base::Optional<MinMaxSizes> NGBlockLayoutAlgorithm::ComputeMinMaxSizes(
? std::max(float_right_inline_size, margin_line_right)
: float_right_inline_size + margin_line_right;
+ // The order of operations is important here.
+ // If child_result.sizes.max_size is saturated, adding the insets
+ // sequentially can result in an DCHECK.
max_inline_contribution =
- child_sizes.max_size + line_left_inset + line_right_inset;
+ child_result.sizes.max_size + (line_left_inset + line_right_inset);
} else {
// This is just a standard inflow child.
- max_inline_contribution = child_sizes.max_size + margins.InlineSum();
+ max_inline_contribution =
+ child_result.sizes.max_size + margins.InlineSum();
}
- sizes->max_size = std::max(sizes->max_size, max_inline_contribution);
+ sizes.max_size = std::max(sizes.max_size, max_inline_contribution);
// The min inline contribution just assumes that floats are all on their own
// "line".
LayoutUnit min_inline_contribution =
- child_sizes.min_size + margins.InlineSum();
- sizes->min_size = std::max(sizes->min_size, min_inline_contribution);
+ child_result.sizes.min_size + margins.InlineSum();
+ sizes.min_size = std::max(sizes.min_size, min_inline_contribution);
+
+ depends_on_percentage_block_size |=
+ child_result.depends_on_percentage_block_size;
// Anything that isn't a float will create a new "line" resetting the float
// size trackers.
@@ -331,11 +431,11 @@ base::Optional<MinMaxSizes> NGBlockLayoutAlgorithm::ComputeMinMaxSizes(
}
}
- DCHECK_GE(sizes->min_size, LayoutUnit());
- DCHECK_LE(sizes->min_size, sizes->max_size) << Node().ToString();
+ DCHECK_GE(sizes.min_size, LayoutUnit());
+ DCHECK_LE(sizes.min_size, sizes.max_size) << Node().ToString();
- *sizes += border_scrollbar_padding_.InlineSum();
- return sizes;
+ sizes += border_scrollbar_padding_.InlineSum();
+ return {sizes, depends_on_percentage_block_size};
}
LogicalOffset NGBlockLayoutAlgorithm::CalculateLogicalOffset(
@@ -366,8 +466,9 @@ scoped_refptr<const NGLayoutResult> NGBlockLayoutAlgorithm::Layout() {
// Inline children require an inline child layout context to be
// passed between siblings. We want to stack-allocate that one, but
// only on demand, as it's quite big.
- if (Node().IsInlineFormattingContextRoot())
- result = LayoutWithInlineChildLayoutContext();
+ NGLayoutInputNode first_child(nullptr);
+ if (Node().IsInlineFormattingContextRoot(&first_child))
+ result = LayoutWithInlineChildLayoutContext(first_child);
else
result = Layout(nullptr);
if (UNLIKELY(result->Status() == NGLayoutResult::kNeedsEarlierBreak)) {
@@ -379,24 +480,26 @@ scoped_refptr<const NGLayoutResult> NGBlockLayoutAlgorithm::Layout() {
} else if (UNLIKELY(result->Status() ==
NGLayoutResult::
kNeedsRelayoutWithNoForcedTruncateAtLineClamp)) {
- DCHECK(force_truncate_at_line_clamp_);
- return RelayoutNoForcedTruncateForLineClamp();
+ DCHECK(!ignore_line_clamp_);
+ return RelayoutIgnoringLineClamp();
}
return result;
}
NOINLINE scoped_refptr<const NGLayoutResult>
-NGBlockLayoutAlgorithm::LayoutWithInlineChildLayoutContext() {
+NGBlockLayoutAlgorithm::LayoutWithInlineChildLayoutContext(
+ const NGLayoutInputNode& first_child) {
NGInlineChildLayoutContext context;
if (!RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled())
return Layout(&context);
- return LayoutWithItemsBuilder(&context);
+ return LayoutWithItemsBuilder(To<NGInlineNode>(first_child), &context);
}
NOINLINE scoped_refptr<const NGLayoutResult>
NGBlockLayoutAlgorithm::LayoutWithItemsBuilder(
+ const NGInlineNode& first_child,
NGInlineChildLayoutContext* context) {
- NGFragmentItemsBuilder items_builder(&container_builder_);
+ NGFragmentItemsBuilder items_builder(first_child);
container_builder_.SetItemsBuilder(&items_builder);
context->SetItemsBuilder(&items_builder);
scoped_refptr<const NGLayoutResult> result = Layout(context);
@@ -425,16 +528,16 @@ NGBlockLayoutAlgorithm::RelayoutAndBreakEarlier(
}
NOINLINE scoped_refptr<const NGLayoutResult>
-NGBlockLayoutAlgorithm::RelayoutNoForcedTruncateForLineClamp() {
+NGBlockLayoutAlgorithm::RelayoutIgnoringLineClamp() {
NGLayoutAlgorithmParams params(Node(),
container_builder_.InitialFragmentGeometry(),
ConstraintSpace(), BreakToken(), nullptr);
- NGBlockLayoutAlgorithm algorithm_with_forced_truncate(params);
- algorithm_with_forced_truncate.force_truncate_at_line_clamp_ = false;
+ NGBlockLayoutAlgorithm algorithm_ignoring_line_clamp(params);
+ algorithm_ignoring_line_clamp.ignore_line_clamp_ = true;
NGBoxFragmentBuilder& new_builder =
- algorithm_with_forced_truncate.container_builder_;
+ algorithm_ignoring_line_clamp.container_builder_;
new_builder.SetBoxType(container_builder_.BoxType());
- return algorithm_with_forced_truncate.Layout();
+ return algorithm_ignoring_line_clamp.Layout();
}
inline scoped_refptr<const NGLayoutResult> NGBlockLayoutAlgorithm::Layout(
@@ -460,16 +563,6 @@ inline scoped_refptr<const NGLayoutResult> NGBlockLayoutAlgorithm::Layout(
Node().IsInlineFormattingContextRoot());
container_builder_.SetIsInlineFormattingContext(inline_child_layout_context);
- if (ConstraintSpace().HasBlockFragmentation()) {
- container_builder_.SetHasBlockFragmentation();
- // The whereabouts of our container's so far best breakpoint is none of our
- // business, but we store its appeal, so that we don't look for breakpoints
- // with lower appeal than that.
- container_builder_.SetBreakAppeal(ConstraintSpace().EarlyBreakAppeal());
-
- if (ConstraintSpace().IsInitialColumnBalancingPass())
- container_builder_.SetIsInitialColumnBalancingPass();
- }
container_builder_.SetBfcLineOffset(
ConstraintSpace().BfcOffset().line_offset);
@@ -487,8 +580,9 @@ inline scoped_refptr<const NGLayoutResult> NGBlockLayoutAlgorithm::Layout(
container_builder_.SetAdjoiningObjectTypes(adjoining_object_types);
}
- if (Style().IsDeprecatedWebkitBoxWithVerticalLineClamp() &&
- RuntimeEnabledFeatures::BlockFlowHandlesWebkitLineClampEnabled())
+ if (RuntimeEnabledFeatures::BlockFlowHandlesWebkitLineClampEnabled() &&
+ Style().IsDeprecatedWebkitBoxWithVerticalLineClamp() &&
+ !ignore_line_clamp_)
lines_until_clamp_ = Style().LineClamp();
LayoutUnit content_edge = border_scrollbar_padding_.block_start;
@@ -577,6 +671,7 @@ inline scoped_refptr<const NGLayoutResult> NGBlockLayoutAlgorithm::Layout(
if (Node().LayoutBlockedByDisplayLock(DisplayLockLifecycleTarget::kChildren))
child_iterator = NGBlockChildIterator(NGBlockNode(nullptr), nullptr);
+ NGLayoutInputNode ruby_text_child(nullptr);
for (auto entry = child_iterator.NextChild();
NGLayoutInputNode child = entry.node;
entry = child_iterator.NextChild(previous_inline_break_token.get())) {
@@ -611,6 +706,8 @@ inline scoped_refptr<const NGLayoutResult> NGBlockLayoutAlgorithm::Layout(
/* is_forced_break */ true);
}
break;
+ } else if (IsRubyText(child)) {
+ ruby_text_child = child;
} else {
// If this is the child we had previously determined to break before, do
// so now and finish layout.
@@ -671,9 +768,12 @@ inline scoped_refptr<const NGLayoutResult> NGBlockLayoutAlgorithm::Layout(
}
}
+ if (ruby_text_child)
+ LayoutRubyText(&ruby_text_child);
+
if (UNLIKELY(ConstraintSpace().IsNewFormattingContext() &&
- force_truncate_at_line_clamp_ &&
- intrinsic_block_size_when_clamped_ && lines_until_clamp_ == 0)) {
+ !ignore_line_clamp_ && lines_until_clamp_ == 0 &&
+ intrinsic_block_size_when_clamped_)) {
// Truncation of the last line was forced, but there are no lines after the
// truncated line. Rerun layout without forcing truncation. This is only
// done if line-clamp was specified on the element as the element containing
@@ -790,7 +890,8 @@ scoped_refptr<const NGLayoutResult> NGBlockLayoutAlgorithm::FinishLayout(
// Recompute the block-axis size now that we know our content size.
border_box_size.block_size = ComputeBlockSizeForFragment(
- ConstraintSpace(), Style(), border_padding_, intrinsic_block_size_);
+ ConstraintSpace(), Style(), border_padding_, intrinsic_block_size_,
+ border_box_size.inline_size);
container_builder_.SetBlockSize(border_box_size.block_size);
// If our BFC block-offset is still unknown, we check:
@@ -868,7 +969,7 @@ scoped_refptr<const NGLayoutResult> NGBlockLayoutAlgorithm::FinishLayout(
#endif
// Adjust the position of the final baseline if needed.
- FinalizeBaseline();
+ container_builder_.SetLastBaselineToBlockEndMarginEdgeIfNeeded();
// An exclusion space is confined to nodes within the same formatting context.
if (!ConstraintSpace().IsNewFormattingContext()) {
@@ -889,85 +990,48 @@ scoped_refptr<const NGLayoutResult> NGBlockLayoutAlgorithm::FinishLayout(
return container_builder_.ToBoxFragment();
}
-const NGInlineBreakToken* NGBlockLayoutAlgorithm::TryReuseFragmentsFromCache(
+bool NGBlockLayoutAlgorithm::TryReuseFragmentsFromCache(
NGInlineNode inline_node,
NGPreviousInflowPosition* previous_inflow_position,
- bool* aborted_out) {
- DCHECK(RuntimeEnabledFeatures::LayoutNGLineCacheEnabled());
- LayoutBox* layout_box = inline_node.GetLayoutBox();
- if (layout_box->SelfNeedsLayout())
- return nullptr;
-
- // If floats are intruding into this node, re-layout may be needed.
- if (!exclusion_space_.IsEmpty())
- return nullptr;
-
- // Laying out from a break token is not supported yet, because this logic
- // synthesize a break token.
- if (BreakToken())
- return nullptr;
-
- const NGPaintFragment* lineboxes =
- inline_node.ReusableLineBoxContainer(ConstraintSpace());
- if (!lineboxes)
- return nullptr;
-
- // Following is a copy of logic from HandleInFlow(). They need to keep in
- // sync.
- if (inline_node.IsEmptyInline())
- return nullptr;
- if (!ResolveBfcBlockOffset(previous_inflow_position)) {
- *aborted_out = true;
- return nullptr;
- }
+ scoped_refptr<const NGInlineBreakToken>* inline_break_token_out) {
+ DCHECK(RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled());
+ DCHECK(previous_result_);
+ DCHECK(!inline_node.IsEmptyInline());
DCHECK(container_builder_.BfcBlockOffset());
+ DCHECK(previous_inflow_position->margin_strut.IsEmpty());
+ DCHECK(!previous_inflow_position->self_collapsing_child_had_clearance);
- WritingMode writing_mode = container_builder_.GetWritingMode();
- TextDirection direction = container_builder_.Direction();
- DCHECK_EQ(writing_mode, lineboxes->Style().GetWritingMode());
- DCHECK_EQ(direction, lineboxes->Style().Direction());
- const PhysicalSize outer_size = lineboxes->Size();
-
- LayoutUnit used_block_size = previous_inflow_position->logical_block_offset;
- const NGBreakToken* last_break_token = nullptr;
- for (const NGPaintFragment* child : lineboxes->Children()) {
- if (child->IsDirty())
- break;
-
- // Abort if the line propagated its descendants to outside of the line. They
- // are propagated through NGLayoutResult, which we don't cache.
- const NGPhysicalLineBoxFragment* line =
- DynamicTo<NGPhysicalLineBoxFragment>(&child->PhysicalFragment());
- if (!line || line->HasPropagatedDescendants())
- break;
-
- // TODO(kojii): Running the normal layout code at least once for this child
- // helps reducing the code to setup internal states after the reuse. Remove
- // the last fragment if it is the end of the fragmentation to do so, but we
- // should figure out how to setup the states without doing this.
- const NGBreakToken* break_token = line->BreakToken();
- DCHECK(break_token);
- if (break_token->IsFinished())
- break;
+ const auto& previous_fragment =
+ To<NGPhysicalBoxFragment>(previous_result_->PhysicalFragment());
+ const NGFragmentItems* previous_items = previous_fragment.Items();
+ DCHECK(previous_items);
+ previous_items->DirtyLinesFromNeedsLayout(inline_node.GetLayoutBlockFlow());
- last_break_token = break_token;
- LogicalOffset logical_offset = child->Offset().ConvertToLogical(
- writing_mode, direction, outer_size, line->Size());
- container_builder_.AddChild(
- *line, {logical_offset.inline_offset, used_block_size});
- used_block_size += line->Size().ConvertToLogical(writing_mode).block_size;
+ const auto& children = container_builder_.Children();
+ const wtf_size_t children_before = children.size();
+ const NGConstraintSpace& space = ConstraintSpace();
+ const auto result = container_builder_.ItemsBuilder()->AddPreviousItems(
+ *previous_items, space.GetWritingMode(), space.Direction(),
+ previous_fragment.Size(), &container_builder_, /* stop_at_dirty */ true);
+
+ if (UNLIKELY(!result.succeeded)) {
+ DCHECK_EQ(children.size(), children_before);
+ DCHECK(!result.used_block_size);
+ DCHECK(!result.inline_break_token);
+ return false;
}
- if (!last_break_token)
- return nullptr;
- // Update the internal states to after the re-used fragments.
- previous_inflow_position->logical_block_offset = used_block_size;
+ // |AddPreviousItems| may have added more than one lines. Propagate baselines
+ // from them.
+ for (const auto& child : base::make_span(children).subspan(children_before)) {
+ DCHECK(child.fragment->IsLineBox());
+ PropagateBaselineFromChild(To<NGPhysicalContainerFragment>(*child.fragment),
+ child.offset.block_offset);
+ }
- // In order to layout the rest of lines, return the break token from the last
- // reused line box.
- DCHECK(last_break_token);
- DCHECK(!last_break_token->IsFinished());
- return To<NGInlineBreakToken>(last_break_token);
+ previous_inflow_position->logical_block_offset += result.used_block_size;
+ *inline_break_token_out = result.inline_break_token;
+ return true;
}
void NGBlockLayoutAlgorithm::HandleOutOfFlowPositioned(
@@ -1497,21 +1561,26 @@ NGLayoutResult::EStatus NGBlockLayoutAlgorithm::HandleInflow(
DCHECK(!child.IsOutOfFlowPositioned());
DCHECK(!child.CreatesNewFormattingContext());
+ bool is_non_empty_inline = false;
auto* child_inline_node = DynamicTo<NGInlineNode>(child);
- if (child_inline_node && !child_break_token &&
- RuntimeEnabledFeatures::LayoutNGLineCacheEnabled()) {
- DCHECK(!*previous_inline_break_token);
- bool aborted = false;
- *previous_inline_break_token = TryReuseFragmentsFromCache(
- *child_inline_node, previous_inflow_position, &aborted);
- if (*previous_inline_break_token)
- return NGLayoutResult::kSuccess;
- if (aborted)
- return NGLayoutResult::kBfcBlockOffsetResolved;
+ if (child_inline_node) {
+ is_non_empty_inline = !child_inline_node->IsEmptyInline();
+
+ // Add reusable line boxes from |previous_result_| if any.
+ if (is_non_empty_inline && !child_break_token && previous_result_ &&
+ RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()) {
+ if (!ResolveBfcBlockOffset(previous_inflow_position))
+ return NGLayoutResult::kBfcBlockOffsetResolved;
+ DCHECK(container_builder_.BfcBlockOffset());
+
+ DCHECK(!*previous_inline_break_token);
+ if (TryReuseFragmentsFromCache(*child_inline_node,
+ previous_inflow_position,
+ previous_inline_break_token))
+ return NGLayoutResult::kSuccess;
+ }
}
- bool is_non_empty_inline =
- child_inline_node && !child_inline_node->IsEmptyInline();
bool has_clearance_past_adjoining_floats =
!container_builder_.BfcBlockOffset() && child.IsBlock() &&
HasClearancePastAdjoiningFloats(container_builder_.AdjoiningObjectTypes(),
@@ -1580,7 +1649,8 @@ NGLayoutResult::EStatus NGBlockLayoutAlgorithm::FinishInflow(
// Only non self-collapsing children (e.g. "normal children") can be pushed
// by floats in this way.
- bool normal_child_had_clearance = layout_result->IsPushedByFloats();
+ bool normal_child_had_clearance =
+ layout_result->IsPushedByFloats() && child.IsBlock();
DCHECK(!normal_child_had_clearance || !is_self_collapsing);
// A child may have aborted its layout if it resolved its BFC block-offset.
@@ -2123,7 +2193,8 @@ bool NGBlockLayoutAlgorithm::FinalizeForFragmentation() {
} else {
block_size = ComputeBlockSizeForFragment(
ConstraintSpace(), Style(), border_padding_,
- consumed_block_size + intrinsic_block_size_);
+ consumed_block_size + intrinsic_block_size_,
+ container_builder_.InitialBorderBoxSize().inline_size);
block_size -= consumed_block_size;
DCHECK_GE(block_size, LayoutUnit())
@@ -2473,7 +2544,6 @@ NGConstraintSpace NGBlockLayoutAlgorithm::CreateConstraintSpaceForChild(
container_builder_.AdjoiningObjectTypes());
}
builder.SetLinesUntilClamp(lines_until_clamp_);
- builder.SetForceTruncateAtLineClamp(force_truncate_at_line_clamp_);
} else if (child_data.is_resuming_after_break) {
// If the child is being resumed after a break, margins inside the child may
// be adjoining with the fragmentainer boundary, regardless of whether the
@@ -2488,8 +2558,9 @@ NGConstraintSpace NGBlockLayoutAlgorithm::CreateConstraintSpaceForChild(
// fragmentation line.
if (is_new_fc)
fragmentainer_offset_delta = *child_bfc_block_offset;
- SetupFragmentation(ConstraintSpace(), child, fragmentainer_offset_delta,
- &builder, is_new_fc);
+ SetupSpaceBuilderForFragmentation(ConstraintSpace(), child,
+ fragmentainer_offset_delta, &builder,
+ is_new_fc);
builder.SetEarlyBreakAppeal(container_builder_.BreakAppeal());
}
@@ -2547,21 +2618,6 @@ void NGBlockLayoutAlgorithm::PropagateBaselineFromChild(
}
}
-void NGBlockLayoutAlgorithm::FinalizeBaseline() {
- if (ConstraintSpace().BaselineAlgorithmType() !=
- NGBaselineAlgorithmType::kInlineBlock)
- return;
-
- if (!Node().UseLogicalBottomMarginEdgeForInlineBlockBaseline())
- return;
-
- // When overflow is present (within an atomic-inline baseline context) we
- // should always use the block-end margin edge as the baseline.
- NGBoxStrut margins = ComputeMarginsForSelf(ConstraintSpace(), Style());
- container_builder_.SetLastBaseline(container_builder_.BlockSize() +
- margins.block_end);
-}
-
bool NGBlockLayoutAlgorithm::ResolveBfcBlockOffset(
NGPreviousInflowPosition* previous_inflow_position,
LayoutUnit bfc_block_offset,
@@ -2747,4 +2803,77 @@ bool NGBlockLayoutAlgorithm::PositionListMarkerWithoutLineBoxes(
return true;
}
+bool NGBlockLayoutAlgorithm::IsRubyText(const NGLayoutInputNode& child) const {
+ return Node().IsRubyRun() && child.IsRubyText();
+}
+
+void NGBlockLayoutAlgorithm::LayoutRubyText(
+ NGLayoutInputNode* ruby_text_child) {
+ DCHECK(RuntimeEnabledFeatures::LayoutNGRubyEnabled());
+ DCHECK(Node().IsRubyRun());
+
+ scoped_refptr<const NGBlockBreakToken> break_token;
+ if (const auto* token = BreakToken()) {
+ for (const auto* child_token : token->ChildBreakTokens()) {
+ if (child_token->InputNode() == *ruby_text_child) {
+ break_token = To<NGBlockBreakToken>(child_token);
+ break;
+ }
+ }
+ }
+
+ NGConstraintSpaceBuilder builder(
+ ConstraintSpace(), ruby_text_child->Style().GetWritingMode(), true);
+ builder.SetAvailableSize(child_available_size_);
+
+ scoped_refptr<const NGLayoutResult> result =
+ To<NGBlockNode>(*ruby_text_child)
+ .Layout(builder.ToConstraintSpace(), break_token.get());
+
+ LayoutUnit ruby_text_top;
+ const NGPhysicalBoxFragment& ruby_text_fragment =
+ To<NGPhysicalBoxFragment>(result->PhysicalFragment());
+ if (Style().IsFlippedLinesWritingMode() ==
+ (Style().GetRubyPosition() == RubyPosition::kAfter)) {
+ LayoutUnit last_line_ruby_text_bottom = LastLineTextLogicalBottom(
+ ruby_text_fragment, result->IntrinsicBlockSize());
+
+ // Find a fragment for RubyBase, and get the top of text in it.
+ LayoutUnit first_line_top;
+ for (const auto& child : container_builder_.Children()) {
+ if (const auto* layout_object = child.fragment->GetLayoutObject()) {
+ if (layout_object->IsRubyBase()) {
+ first_line_top = FirstLineTextLogicalTop(
+ To<NGPhysicalBoxFragment>(*child.fragment), LayoutUnit());
+ first_line_top += child.offset.block_offset;
+ break;
+ }
+ }
+ }
+ ruby_text_top = first_line_top - last_line_ruby_text_bottom;
+ } else {
+ LayoutUnit first_line_ruby_text_top =
+ FirstLineTextLogicalTop(ruby_text_fragment, LayoutUnit());
+
+ // Find a fragment for RubyBase, and get the bottom of text in it.
+ LayoutUnit last_line_bottom;
+ for (const auto& child : container_builder_.Children()) {
+ if (const auto* layout_object = child.fragment->GetLayoutObject()) {
+ if (layout_object->IsRubyBase()) {
+ last_line_bottom = LastLineTextLogicalBottom(
+ To<NGPhysicalBoxFragment>(*child.fragment),
+ child.fragment->Size()
+ .ConvertToLogical(Style().GetWritingMode())
+ .block_size);
+ last_line_bottom += child.offset.block_offset;
+ break;
+ }
+ }
+ }
+ ruby_text_top = last_line_bottom - first_line_ruby_text_top;
+ }
+ container_builder_.AddResult(*result,
+ LogicalOffset(LayoutUnit(), ruby_text_top));
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.h b/chromium/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.h
index 644bb031ead..b7599118a1a 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.h
@@ -59,14 +59,14 @@ class CORE_EXPORT NGBlockLayoutAlgorithm
void SetBoxType(NGPhysicalFragment::NGBoxType type);
- base::Optional<MinMaxSizes> ComputeMinMaxSizes(
- const MinMaxSizesInput&) const override;
+ MinMaxSizesResult ComputeMinMaxSizes(const MinMaxSizesInput&) const override;
scoped_refptr<const NGLayoutResult> Layout() override;
private:
NOINLINE scoped_refptr<const NGLayoutResult>
- LayoutWithInlineChildLayoutContext();
+ LayoutWithInlineChildLayoutContext(const NGLayoutInputNode& first_child);
NOINLINE scoped_refptr<const NGLayoutResult> LayoutWithItemsBuilder(
+ const NGInlineNode& first_child,
NGInlineChildLayoutContext* context);
// Lay out again, this time with a predefined good breakpoint that we
@@ -76,8 +76,7 @@ class CORE_EXPORT NGBlockLayoutAlgorithm
NOINLINE scoped_refptr<const NGLayoutResult> RelayoutAndBreakEarlier(
const NGEarlyBreak&);
- NOINLINE scoped_refptr<const NGLayoutResult>
- RelayoutNoForcedTruncateForLineClamp();
+ NOINLINE scoped_refptr<const NGLayoutResult> RelayoutIgnoringLineClamp();
inline scoped_refptr<const NGLayoutResult> Layout(
NGInlineChildLayoutContext* inline_child_layout_context);
@@ -149,10 +148,10 @@ class CORE_EXPORT NGBlockLayoutAlgorithm
// function adds part of cached fragments to |container_builder_|, update
// |break_token_| to continue layout from the last reused fragment, and
// returns |true|. Otherwise returns |false|.
- const NGInlineBreakToken* TryReuseFragmentsFromCache(
+ bool TryReuseFragmentsFromCache(
NGInlineNode child,
NGPreviousInflowPosition*,
- bool* abort_out);
+ scoped_refptr<const NGInlineBreakToken>* inline_break_token_out);
void HandleOutOfFlowPositioned(const NGPreviousInflowPosition&, NGBlockNode);
void HandleFloat(const NGPreviousInflowPosition&,
@@ -249,9 +248,6 @@ class CORE_EXPORT NGBlockLayoutAlgorithm
void PropagateBaselineFromChild(const NGPhysicalContainerFragment& child,
LayoutUnit block_offset);
- // Performs any final baseline adjustments needed.
- void FinalizeBaseline();
-
// If still unresolved, resolve the fragment's BFC block offset.
//
// This includes applying clearance, so the |bfc_block_offset| passed won't
@@ -338,6 +334,14 @@ class CORE_EXPORT NGBlockLayoutAlgorithm
base::Optional<LayoutUnit> CalculateQuirkyBodyMarginBlockSum(
const NGMarginStrut& end_margin_strut);
+ // Returns true if |this| is a ruby segment (LayoutNGRubyRun) and the
+ // specified |child| is a ruby annotation box (LayoutNGRubyText).
+ bool IsRubyText(const NGLayoutInputNode& child) const;
+
+ // Layout |ruby_text_child| content, and decide the location of
+ // |ruby_text_child|. This is called only if IsRubyText() returns true.
+ void LayoutRubyText(NGLayoutInputNode* ruby_text_child);
+
// Border + padding sum, resolved from the node's computed style.
const NGBoxStrut border_padding_;
@@ -350,6 +354,8 @@ class CORE_EXPORT NGBlockLayoutAlgorithm
LogicalSize child_percentage_size_;
LogicalSize replaced_child_percentage_size_;
+ scoped_refptr<const NGLayoutResult> previous_result_;
+
// Intrinsic block size based on child layout and containment.
LayoutUnit intrinsic_block_size_;
@@ -394,9 +400,8 @@ class CORE_EXPORT NGBlockLayoutAlgorithm
// the current line should be clamped. This may go negative.
base::Optional<int> lines_until_clamp_;
- // If true, truncation is forced at the clamped line regardless of whether
- // there is more text.
- bool force_truncate_at_line_clamp_ = true;
+ // If true, ignore the line-clamp property as truncation wont be required.
+ bool ignore_line_clamp_ = false;
// If set, one of the lines was clamped and this is the intrinsic size at the
// time of the clamp.
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm_test.cc b/chromium/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm_test.cc
index f07b9dcfcf3..6b75c41df3b 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm_test.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm_test.cc
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.h"
#include "testing/gmock/include/gmock/gmock.h"
+#include "third_party/blink/renderer/core/dom/dom_token_list.h"
#include "third_party/blink/renderer/core/dom/node_computed_style.h"
#include "third_party/blink/renderer/core/dom/tag_collection.h"
#include "third_party/blink/renderer/core/layout/ng/layout_ng_block_flow.h"
@@ -45,9 +46,7 @@ class NGBlockLayoutAlgorithmTest : public NGBaseLayoutAlgorithmTest {
NGBlockLayoutAlgorithm algorithm({node, fragment_geometry, space});
MinMaxSizesInput input(
/* percentage_resolution_block_size */ (LayoutUnit()));
- auto min_max = algorithm.ComputeMinMaxSizes(input);
- EXPECT_TRUE(min_max.has_value());
- return *min_max;
+ return algorithm.ComputeMinMaxSizes(input).sizes;
}
scoped_refptr<const NGLayoutResult> RunCachedLayoutResult(
@@ -211,17 +210,13 @@ TEST_F(NGBlockLayoutAlgorithmTest, PercentageBlockSizeQuirkDescendantsCaching) {
<div style="height: 20px;"></div>
<div style="display: flex; height: 50%;"></div>
</div>
- <div id="box6">
- <div style="height: 20px;"></div>
- <div style="display: table;"></div>
- </div>
- <div id="box7" style="position: relative;">
+ <div id="box6" style="position: relative;">
<div style="position: absolute; width: 10px; height: 100%;"></div>
</div>
- <div id="box8">
+ <div id="box7">
<img />
</div>
- <div id="box9">
+ <div id="box8">
<img style="height: 100%;" />
</div>
</div>
@@ -274,22 +269,17 @@ TEST_F(NGBlockLayoutAlgorithmTest, PercentageBlockSizeQuirkDescendantsCaching) {
// behaviour, but is %-sized.
EXPECT_EQ(run_test("box5"), nullptr);
- // Test 6: A table (legacy descendant), which does use the quirks mode
- // behaviour.
- // NOTE: This test may fail when tables are converted to LayoutNG.
- EXPECT_EQ(run_test("box6"), nullptr);
-
- // Test 7: An OOF positioned descentant which has a %-height, should not
+ // Test 6: An OOF positioned descentant which has a %-height, should not
// count as a percentage descendant.
- EXPECT_NE(run_test("box7"), nullptr);
+ EXPECT_NE(run_test("box6"), nullptr);
- // Test 8: A replaced element (legacy descendant), shouldn't use the quirks
+ // Test 7: A replaced element (legacy descendant), shouldn't use the quirks
// mode behaviour.
- EXPECT_NE(run_test("box8"), nullptr);
+ EXPECT_NE(run_test("box7"), nullptr);
- // Test 9: A replaced element (legacy descendant), shouldn't use the quirks
+ // Test 8: A replaced element (legacy descendant), shouldn't use the quirks
// mode behaviour, but is %-sized.
- EXPECT_EQ(run_test("box9"), nullptr);
+ EXPECT_EQ(run_test("box8"), nullptr);
}
TEST_F(NGBlockLayoutAlgorithmTest, LineOffsetCaching) {
@@ -2450,6 +2440,52 @@ TEST_F(NGBlockLayoutAlgorithmTest, RootFragmentOffsetInsideLegacy) {
// EXPECT_EQ(PhysicalOffset(20, 10), fragment->Offset());
}
+// This test checks if the inline block baseline is computed correctly when it
+// is from the logical bottom margin edge, even after the simplified layout.
+TEST_F(NGBlockLayoutAlgorithmTest,
+ BaselineAtBlockEndMarginEdgeAfterSimplifiedLayout) {
+ SetBodyInnerHTML(R"HTML(
+ <!DOCTYPE html>
+ <style>
+ #outer {
+ height: 200px;
+ }
+ #outer.after {
+ height: 400px;
+ }
+ #target {
+ display: inline-block;
+ overflow: hidden;
+ width: 300px;
+ height: 100%;
+ }
+ </style>
+ <div id="outer">
+ <div id="target">
+ </div>
+ </div>
+ )HTML");
+ UpdateAllLifecyclePhasesForTest();
+
+ // #target uses the logical bottom margin edge for the inline block baseline.
+ auto* target_block_flow =
+ To<LayoutBlockFlow>(GetLayoutObjectByElementId("target"));
+ NGBlockNode target(target_block_flow);
+ ASSERT_TRUE(target.UseBlockEndMarginEdgeForInlineBlockBaseline());
+ scoped_refptr<const NGPhysicalBoxFragment> before =
+ To<NGPhysicalBoxFragment>(target_block_flow->CurrentFragment());
+ EXPECT_EQ(*before->LastBaseline(), LayoutUnit(200));
+
+ // Change the height of the container. This should kick the simplified layout.
+ Element* outer_element = GetElementById("outer");
+ outer_element->classList().Add("after");
+ UpdateAllLifecyclePhasesForTest();
+
+ scoped_refptr<const NGPhysicalBoxFragment> after =
+ To<NGPhysicalBoxFragment>(target_block_flow->CurrentFragment());
+ EXPECT_EQ(*after->LastBaseline(), LayoutUnit(400));
+}
+
// TODO(dgrogan): Move this to ng_flex_layout_algorithm_test.cc if there ever is
// one.
TEST_F(NGBlockLayoutAlgorithmTest, DetailsFlexDoesntCrash) {
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm_utils.h b/chromium/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm_utils.h
index a95dbb39bd2..04932846cd0 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm_utils.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm_utils.h
@@ -19,6 +19,8 @@ class NGExclusionSpace;
//
// This function calculates the inline-offset to avoid floats, and respect
// text-align.
+//
+// TODO(ikilpatrick): Move this back into ng_block_layout_algorithm.cc
LayoutUnit CalculateOutOfFlowStaticInlineLevelOffset(
const ComputedStyle& container_style,
const NGBfcOffset& origin_bfc_offset,
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_block_node.cc b/chromium/third_party/blink/renderer/core/layout/ng/ng_block_node.cc
index 48871b0c4f8..80d066499e2 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_block_node.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_block_node.cc
@@ -24,6 +24,7 @@
#include "third_party/blink/renderer/core/layout/min_max_sizes.h"
#include "third_party/blink/renderer/core/layout/ng/custom/layout_ng_custom.h"
#include "third_party/blink/renderer/core/layout/ng/custom/ng_custom_layout_algorithm.h"
+#include "third_party/blink/renderer/core/layout/ng/flex/ng_flex_layout_algorithm.h"
#include "third_party/blink/renderer/core/layout/ng/geometry/ng_fragment_geometry.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.h"
@@ -32,7 +33,9 @@
#include "third_party/blink/renderer/core/layout/ng/mathml/ng_math_fraction_layout_algorithm.h"
#include "third_party/blink/renderer/core/layout/ng/mathml/ng_math_layout_utils.h"
#include "third_party/blink/renderer/core/layout/ng/mathml/ng_math_row_layout_algorithm.h"
+#include "third_party/blink/renderer/core/layout/ng/mathml/ng_math_scripts_layout_algorithm.h"
#include "third_party/blink/renderer/core/layout/ng/mathml/ng_math_space_layout_algorithm.h"
+#include "third_party/blink/renderer/core/layout/ng/mathml/ng_math_under_over_layout_algorithm.h"
#include "third_party/blink/renderer/core/layout/ng/ng_block_break_token.h"
#include "third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.h"
#include "third_party/blink/renderer/core/layout/ng/ng_box_fragment.h"
@@ -41,7 +44,6 @@
#include "third_party/blink/renderer/core/layout/ng/ng_constraint_space.h"
#include "third_party/blink/renderer/core/layout/ng/ng_constraint_space_builder.h"
#include "third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm.h"
-#include "third_party/blink/renderer/core/layout/ng/ng_flex_layout_algorithm.h"
#include "third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.h"
#include "third_party/blink/renderer/core/layout/ng/ng_layout_input_node.h"
#include "third_party/blink/renderer/core/layout/ng/ng_layout_result.h"
@@ -54,7 +56,9 @@
#include "third_party/blink/renderer/core/layout/text_autosizer.h"
#include "third_party/blink/renderer/core/mathml/mathml_element.h"
#include "third_party/blink/renderer/core/mathml/mathml_fraction_element.h"
+#include "third_party/blink/renderer/core/mathml/mathml_scripts_element.h"
#include "third_party/blink/renderer/core/mathml/mathml_space_element.h"
+#include "third_party/blink/renderer/core/mathml/mathml_under_over_element.h"
#include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/text/writing_mode.h"
@@ -64,6 +68,11 @@ namespace blink {
namespace {
+inline bool HasInlineChildren(LayoutBlockFlow* block_flow) {
+ auto* child = GetLayoutObjectForFirstChildNode(block_flow);
+ return child && AreNGBlockFlowChildrenInline(block_flow);
+}
+
inline LayoutMultiColumnFlowThread* GetFlowThread(
const LayoutBlockFlow* block_flow) {
if (!block_flow)
@@ -75,6 +84,12 @@ inline LayoutMultiColumnFlowThread* GetFlowThread(const LayoutBox& box) {
return GetFlowThread(DynamicTo<LayoutBlockFlow>(box));
}
+inline wtf_size_t FragmentIndex(const NGBlockBreakToken* incoming_break_token) {
+ if (incoming_break_token && !incoming_break_token->IsBreakBefore())
+ return incoming_break_token->SequenceNumber() + 1;
+ return 0;
+}
+
// The entire purpose of this function is to avoid allocating space on the stack
// for all layout algorithms for each node we lay out. Therefore it must not be
// inline.
@@ -94,13 +109,22 @@ NOINLINE void DetermineMathMLAlgorithmAndRun(
// Currently math layout algorithms can only apply to MathML elements.
auto* element = box.GetNode();
DCHECK(element);
- if (IsA<MathMLSpaceElement>(element))
+ if (IsA<MathMLSpaceElement>(element)) {
CreateAlgorithmAndRun<NGMathSpaceLayoutAlgorithm>(params, callback);
- else if (IsA<MathMLFractionElement>(element) &&
- IsValidMathMLFraction(params.node))
+ } else if (IsA<MathMLFractionElement>(element) &&
+ IsValidMathMLFraction(params.node)) {
CreateAlgorithmAndRun<NGMathFractionLayoutAlgorithm>(params, callback);
- else
+ } else if (IsA<MathMLScriptsElement>(element) &&
+ IsValidMathMLScript(params.node)) {
+ // TODO(rbuis): take into account movablelimits.
+ if (IsA<MathMLUnderOverElement>(element)) {
+ CreateAlgorithmAndRun<NGMathUnderOverLayoutAlgorithm>(params, callback);
+ } else {
+ CreateAlgorithmAndRun<NGMathScriptsLayoutAlgorithm>(params, callback);
+ }
+ } else {
CreateAlgorithmAndRun<NGMathRowLayoutAlgorithm>(params, callback);
+ }
}
template <typename Callback>
@@ -140,15 +164,15 @@ inline scoped_refptr<const NGLayoutResult> LayoutWithAlgorithm(
return result;
}
-inline base::Optional<MinMaxSizes> ComputeMinMaxSizesWithAlgorithm(
+inline MinMaxSizesResult ComputeMinMaxSizesWithAlgorithm(
const NGLayoutAlgorithmParams& params,
const MinMaxSizesInput& input) {
- base::Optional<MinMaxSizes> min_max_sizes;
+ MinMaxSizesResult result;
DetermineAlgorithmAndRun(
- params, [&min_max_sizes, &input](NGLayoutAlgorithmOperations* algorithm) {
- min_max_sizes = algorithm->ComputeMinMaxSizes(input);
+ params, [&result, &input](NGLayoutAlgorithmOperations* algorithm) {
+ result = algorithm->ComputeMinMaxSizes(input);
});
- return min_max_sizes;
+ return result;
}
void UpdateLegacyMultiColumnFlowThread(
@@ -234,13 +258,12 @@ void UpdateLegacyMultiColumnFlowThread(
flow_thread->ClearNeedsLayout();
}
-NGConstraintSpaceBuilder CreateConstraintSpaceBuilderForMinMax(
- NGBlockNode node) {
+NGConstraintSpace CreateConstraintSpaceForMinMax(const NGBlockNode& node) {
NGConstraintSpaceBuilder builder(node.Style().GetWritingMode(),
node.Style().GetWritingMode(),
node.CreatesNewFormattingContext());
builder.SetTextDirection(node.Style().Direction());
- return builder;
+ return builder.ToConstraintSpace();
}
LayoutUnit CalculateAvailableInlineSizeForLegacy(
@@ -296,14 +319,17 @@ void SetupBoxLayoutExtraInput(const NGConstraintSpace& space,
if (space.IsFixedInlineSize())
input->override_inline_size = space.AvailableSize().inline_size;
- if (space.IsFixedBlockSize())
+ if (space.IsFixedBlockSize()) {
input->override_block_size = space.AvailableSize().block_size;
+ input->is_override_block_size_definite =
+ !space.IsFixedBlockSizeIndefinite();
+ }
}
bool CanUseCachedIntrinsicInlineSizes(const MinMaxSizesInput& input,
- const LayoutBox& box) {
+ const NGBlockNode& node) {
// Obviously can't use the cache if our intrinsic logical widths are dirty.
- if (box.IntrinsicLogicalWidthsDirty())
+ if (node.GetLayoutBox()->IntrinsicLogicalWidthsDirty())
return false;
// We don't store the float inline sizes for comparison, always skip the
@@ -312,16 +338,11 @@ bool CanUseCachedIntrinsicInlineSizes(const MinMaxSizesInput& input,
return false;
// Check if we have any percentage inline padding.
- const auto& style = box.StyleRef();
+ const auto& style = node.Style();
if (style.MayHavePadding() && (style.PaddingStart().IsPercentOrCalc() ||
style.PaddingEnd().IsPercentOrCalc()))
return false;
- // Check if the %-block-size matches.
- if (input.percentage_resolution_block_size !=
- box.IntrinsicLogicalWidthsPercentageResolutionBlockSize())
- return false;
-
return true;
}
@@ -392,13 +413,8 @@ scoped_refptr<const NGLayoutResult> NGBlockNode::Layout(
break_token, early_break);
// Try to perform "simplified" layout.
- // TODO(crbug.com/992953): Add a simplified layout pass for custom layout.
if (cache_status == NGLayoutCacheStatus::kNeedsSimplifiedLayout &&
- block_flow && !GetFlowThread(block_flow) &&
- // TODO(kojii): Enable simplified layout for fragment items.
- !(block_flow->ChildrenInline() &&
- RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()) &&
- !block_flow->IsLayoutNGCustom()) {
+ !GetFlowThread(block_flow)) {
DCHECK(layout_result);
#if DCHECK_IS_ON()
scoped_refptr<const NGLayoutResult> previous_result = layout_result;
@@ -413,9 +429,12 @@ scoped_refptr<const NGLayoutResult> NGBlockNode::Layout(
#if DCHECK_IS_ON()
if (layout_result) {
layout_result->CheckSameForSimplifiedLayout(
- *previous_result, /* check_same_block_size */ false);
+ *previous_result, /* check_same_block_size */ !block_flow);
}
#endif
+ } else if (cache_status == NGLayoutCacheStatus::kCanReuseLines) {
+ params.previous_result = layout_result.get();
+ layout_result = nullptr;
} else {
layout_result = nullptr;
}
@@ -447,6 +466,7 @@ scoped_refptr<const NGLayoutResult> NGBlockNode::Layout(
// We need to clear any previous results when scrollbars change. For
// example - we may have stored a "measure" layout result which will be
// incorrect if we try and reuse it.
+ params.previous_result = nullptr;
box_->ClearLayoutResults();
#if DCHECK_IS_ON()
@@ -487,11 +507,17 @@ scoped_refptr<const NGLayoutResult> NGBlockNode::Layout(
return layout_result;
}
-scoped_refptr<const NGLayoutResult> NGBlockNode::SimplifiedLayout() {
+scoped_refptr<const NGLayoutResult> NGBlockNode::SimplifiedLayout(
+ const NGPhysicalFragment& previous_fragment) {
scoped_refptr<const NGLayoutResult> previous_result =
box_->GetCachedLayoutResult();
DCHECK(previous_result);
+ // We might be be trying to perform simplfied layout on a fragment in the
+ // "measure" cache slot, abort if this is the case.
+ if (&previous_result->PhysicalFragment() != &previous_fragment)
+ return nullptr;
+
if (!box_->NeedsLayout())
return previous_result;
@@ -596,19 +622,15 @@ void NGBlockNode::FinishLayout(
// layout box at higher indices than that of the one we're writing back.
const auto& physical_fragment =
To<NGPhysicalBoxFragment>(layout_result->PhysicalFragment());
- wtf_size_t fragment_index = 0;
- if (break_token && !break_token->IsBreakBefore())
- fragment_index = break_token->SequenceNumber() + 1;
if (layout_result->IsSingleUse())
- box_->AddLayoutResult(layout_result, fragment_index);
+ box_->AddLayoutResult(layout_result, FragmentIndex(break_token));
else
box_->SetCachedLayoutResult(layout_result);
if (block_flow) {
- auto* child = GetLayoutObjectForFirstChildNode(block_flow);
- bool has_inline_children =
- child && AreNGBlockFlowChildrenInline(block_flow);
+ const NGFragmentItems* items = physical_fragment.Items();
+ bool has_inline_children = items || HasInlineChildren(block_flow);
// Don't consider display-locked objects as having any children.
if (has_inline_children && box_->LayoutBlockedByDisplayLock(
@@ -634,21 +656,24 @@ void NGBlockNode::FinishLayout(
physical_fragment, physical_fragment.Size().width,
Style().IsFlippedBlocksWritingMode());
block_flow->SetPaintFragment(break_token, &physical_fragment);
- } else {
- CopyFragmentDataToLayoutBoxForInlineChildren(physical_fragment);
+ } else if (items) {
+ CopyFragmentItemsToLayoutBox(physical_fragment, *items);
}
} else {
// We still need to clear paint fragments in case it had inline children,
// and thus had NGPaintFragment.
block_flow->ClearNGInlineNodeData();
- block_flow->SetPaintFragment(break_token, nullptr);
+ if (!RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled())
+ block_flow->SetPaintFragment(break_token, nullptr);
}
+ } else {
+ DCHECK(!physical_fragment.HasItems());
}
CopyFragmentDataToLayoutBox(constraint_space, *layout_result, break_token);
}
-MinMaxSizes NGBlockNode::ComputeMinMaxSizes(
+MinMaxSizesResult NGBlockNode::ComputeMinMaxSizes(
WritingMode container_writing_mode,
const MinMaxSizesInput& input,
const NGConstraintSpace* constraint_space) {
@@ -660,89 +685,124 @@ MinMaxSizes NGBlockNode::ComputeMinMaxSizes(
bool is_orthogonal_flow_root =
!IsParallelWritingMode(container_writing_mode, Style().GetWritingMode());
- if (CanUseCachedIntrinsicInlineSizes(input, *box_))
- return box_->IntrinsicLogicalWidths();
-
- box_->SetIntrinsicLogicalWidthsDirty();
-
- MinMaxSizes sizes;
- // If we're orthogonal, we have to run layout to compute the sizes. However,
- // if we're outside of layout, we can't do that. This can happen on Mac.
- if ((!CanUseNewLayout() && !is_orthogonal_flow_root) ||
- (is_orthogonal_flow_root && !box_->GetFrameView()->IsInPerformLayout()))
- return ComputeMinMaxSizesFromLegacy(input);
-
- NGConstraintSpace zero_constraint_space =
- CreateConstraintSpaceBuilderForMinMax(*this).ToConstraintSpace();
-
- if (!constraint_space) {
- // Using the zero-sized constraint space when measuring for an orthogonal
- // flow root isn't going to give the right result.
- DCHECK(!is_orthogonal_flow_root);
-
- constraint_space = &zero_constraint_space;
- }
+ // If we're orthogonal, run layout to compute the sizes.
+ if (is_orthogonal_flow_root) {
+ MinMaxSizes sizes;
+ // Some other areas of the code can query the intrinsic-sizes while outside
+ // of the layout phase.
+ // TODO(ikilpatrick): Remove this check.
+ if (!box_->GetFrameView()->IsInPerformLayout()) {
+ sizes = ComputeMinMaxSizesFromLegacy(input);
+ return {sizes, /* depends_on_percentage_block_size */ false};
+ }
- if (is_orthogonal_flow_root || !CanUseNewLayout()) {
+ DCHECK(constraint_space);
scoped_refptr<const NGLayoutResult> layout_result =
Layout(*constraint_space);
DCHECK_EQ(layout_result->Status(), NGLayoutResult::kSuccess);
- NGBoxFragment fragment(
- container_writing_mode,
- TextDirection::kLtr, // irrelevant here
- To<NGPhysicalBoxFragment>(layout_result->PhysicalFragment()));
- sizes.min_size = sizes.max_size = fragment.Size().inline_size;
- return sizes;
+ sizes =
+ NGFragment(container_writing_mode, layout_result->PhysicalFragment())
+ .InlineSize();
+ return {sizes, /* depends_on_percentage_block_size */ false};
}
+ bool can_use_cached_intrinsic_inline_sizes =
+ CanUseCachedIntrinsicInlineSizes(input, *this);
+
+ // Use our cached sizes if either:
+ // - The %-block-sizes match.
+ // - We don't have a descendant which depends on the %-block-size.
+ if (can_use_cached_intrinsic_inline_sizes &&
+ (input.percentage_resolution_block_size ==
+ box_->IntrinsicLogicalWidthsPercentageResolutionBlockSize() ||
+ !box_->IntrinsicLogicalWidthsChildDependsOnPercentageBlockSize())) {
+ MinMaxSizes sizes = box_->IsTable() ? box_->PreferredLogicalWidths()
+ : box_->IntrinsicLogicalWidths();
+ bool depends_on_percentage_block_size =
+ box_->IntrinsicLogicalWidthsDependsOnPercentageBlockSize();
+ return {sizes, depends_on_percentage_block_size};
+ }
+
+ // Synthesize a zero space if not provided.
+ auto zero_constraint_space = CreateConstraintSpaceForMinMax(*this);
+ if (!constraint_space)
+ constraint_space = &zero_constraint_space;
+
NGFragmentGeometry fragment_geometry =
CalculateInitialMinMaxFragmentGeometry(*constraint_space, *this);
- base::Optional<MinMaxSizes> maybe_sizes = ComputeMinMaxSizesWithAlgorithm(
- NGLayoutAlgorithmParams(*this, fragment_geometry, *constraint_space),
- input);
-
- if (maybe_sizes.has_value()) {
- auto* html_marquee_element = DynamicTo<HTMLMarqueeElement>(box_->GetNode());
- if (UNLIKELY(html_marquee_element && html_marquee_element->IsHorizontal()))
- maybe_sizes->min_size = LayoutUnit();
- else if (UNLIKELY(IsA<HTMLSelectElement>(box_->GetNode()) ||
- (IsA<HTMLInputElement>(box_->GetNode()) &&
- To<HTMLInputElement>(box_->GetNode())->type() ==
- input_type_names::kFile)) &&
- Style().LogicalWidth().IsPercentOrCalc())
- maybe_sizes->min_size = LayoutUnit();
- box_->SetIntrinsicLogicalWidthsFromNG(
- *maybe_sizes, input.percentage_resolution_block_size);
- return *maybe_sizes;
+
+ // Calculate the %-block-size for our children up front. This allows us to
+ // determine if |input|'s %-block-size is used.
+ bool uses_input_percentage_block_size = false;
+ LayoutUnit child_percentage_resolution_block_size =
+ CalculateChildPercentageBlockSizeForMinMax(
+ *constraint_space, *this,
+ fragment_geometry.border + fragment_geometry.padding,
+ input.percentage_resolution_block_size,
+ &uses_input_percentage_block_size);
+
+ bool cache_depends_on_percentage_block_size =
+ uses_input_percentage_block_size &&
+ box_->IntrinsicLogicalWidthsChildDependsOnPercentageBlockSize();
+
+ // We might still be able to use the cached values if our children don't
+ // depend on the *input* %-block-size.
+ if (can_use_cached_intrinsic_inline_sizes &&
+ !cache_depends_on_percentage_block_size) {
+ MinMaxSizes sizes = box_->IsTable() ? box_->PreferredLogicalWidths()
+ : box_->IntrinsicLogicalWidths();
+ return {sizes, cache_depends_on_percentage_block_size};
}
- if (!box_->GetFrameView()->IsInPerformLayout()) {
- // We can't synthesize these using Layout() if we're not in PerformLayout.
- // This situation can happen on mac. Fall back to legacy instead.
- return ComputeMinMaxSizesFromLegacy(input);
+ box_->SetIntrinsicLogicalWidthsDirty();
+
+ if (!CanUseNewLayout()) {
+ MinMaxSizes sizes = ComputeMinMaxSizesFromLegacy(input);
+
+ // Update the cache bits for this legacy root (but not the intrinsic
+ // inline-sizes themselves).
+ box_->SetIntrinsicLogicalWidthsFromNG(
+ input.percentage_resolution_block_size,
+ /* depends_on_percentage_block_size */ uses_input_percentage_block_size,
+ /* child_depends_on_percentage_block_size */ true,
+ /* sizes */ nullptr);
+
+ return {sizes, uses_input_percentage_block_size};
}
- // Have to synthesize this value.
- scoped_refptr<const NGLayoutResult> layout_result =
- Layout(zero_constraint_space);
- sizes.min_size =
- NGFragment(container_writing_mode, layout_result->PhysicalFragment())
- .InlineSize();
-
- // Now, redo with infinite space for max_content
- NGConstraintSpaceBuilder builder =
- CreateConstraintSpaceBuilderForMinMax(*this);
- builder.SetAvailableSize({LayoutUnit::Max(), LayoutUnit()});
- builder.SetPercentageResolutionSize({LayoutUnit(), LayoutUnit()});
- NGConstraintSpace infinite_constraint_space = builder.ToConstraintSpace();
-
- layout_result = Layout(infinite_constraint_space);
- NGBoxFragment max_fragment(
- container_writing_mode,
- TextDirection::kLtr, // irrelevant here
- To<NGPhysicalBoxFragment>(layout_result->PhysicalFragment()));
- sizes.max_size = max_fragment.Size().inline_size;
- return sizes;
+ // Copy the input, and set the new %-block-size.
+ MinMaxSizesInput adjusted_input = input;
+ adjusted_input.percentage_resolution_block_size =
+ child_percentage_resolution_block_size;
+
+ MinMaxSizesResult result = ComputeMinMaxSizesWithAlgorithm(
+ NGLayoutAlgorithmParams(*this, fragment_geometry, *constraint_space),
+ adjusted_input);
+
+ const auto* node = box_->GetNode();
+ const auto* html_marquee_element = DynamicTo<HTMLMarqueeElement>(node);
+ if (UNLIKELY(html_marquee_element && html_marquee_element->IsHorizontal()))
+ result.sizes.min_size = LayoutUnit();
+ else if (UNLIKELY(IsA<HTMLSelectElement>(node) ||
+ (IsA<HTMLInputElement>(node) &&
+ To<HTMLInputElement>(node)->type() ==
+ input_type_names::kFile)) &&
+ Style().LogicalWidth().IsPercentOrCalc())
+ result.sizes.min_size = LayoutUnit();
+
+ bool depends_on_percentage_block_size =
+ uses_input_percentage_block_size &&
+ result.depends_on_percentage_block_size;
+
+ box_->SetIntrinsicLogicalWidthsFromNG(
+ input.percentage_resolution_block_size, depends_on_percentage_block_size,
+ /* child_depends_on_percentage_block_size */
+ result.depends_on_percentage_block_size, &result.sizes);
+
+ // We report to our parent if we depend on the %-block-size if we used the
+ // input %-block-size, or one of children said it depended on this.
+ result.depends_on_percentage_block_size = depends_on_percentage_block_size;
+ return result;
}
MinMaxSizes NGBlockNode::ComputeMinMaxSizesFromLegacy(
@@ -924,9 +984,12 @@ void NGBlockNode::CopyFragmentDataToLayoutBox(
PlaceChildrenInLayoutBox(physical_fragment, previous_break_token);
}
+ if (UNLIKELY(!is_last_fragment))
+ return;
+
LayoutBlock* block = DynamicTo<LayoutBlock>(box_);
bool needs_full_invalidation = false;
- if (LIKELY(block && is_last_fragment)) {
+ if (LIKELY(block)) {
LayoutUnit overflow_block_size = layout_result.OverflowBlockSize();
if (UNLIKELY(previous_break_token))
overflow_block_size += previous_break_token->ConsumedBlockSize();
@@ -1004,6 +1067,8 @@ void NGBlockNode::PlaceChildrenInLayoutBox(
// wrapper, we're ready to compensate for this discrepancy. See
// LayoutNGFieldset for more details.
LayoutBlock* content_wrapper = rendered_legend->ContainingBlock();
+ if (content_wrapper->IsLayoutFlowThread())
+ content_wrapper = content_wrapper->ContainingBlock();
DCHECK(content_wrapper->IsAnonymous());
DCHECK(IsA<HTMLFieldSetElement>(content_wrapper->Parent()->GetNode()));
LayoutPoint location = rendered_legend->Location();
@@ -1118,14 +1183,13 @@ void NGBlockNode::CopyFragmentDataToLayoutBoxForInlineChildren(
}
}
-void NGBlockNode::CopyFragmentDataToLayoutBoxForInlineChildren(
- const NGPhysicalBoxFragment& container) {
+void NGBlockNode::CopyFragmentItemsToLayoutBox(
+ const NGPhysicalBoxFragment& container,
+ const NGFragmentItems& items) {
DCHECK(RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled());
- const NGFragmentItems* items = container.Items();
- if (!items)
- return;
+
bool initial_container_is_flipped = Style().IsFlippedBlocksWritingMode();
- for (NGInlineCursor cursor(*items); cursor; cursor.MoveToNext()) {
+ for (NGInlineCursor cursor(items); cursor; cursor.MoveToNext()) {
if (const NGPhysicalBoxFragment* child = cursor.Current().BoxFragment()) {
// Replaced elements and inline blocks need Location() set relative to
// their block container.
@@ -1158,9 +1222,18 @@ void NGBlockNode::CopyFragmentDataToLayoutBoxForInlineChildren(
}
}
-bool NGBlockNode::IsInlineFormattingContextRoot() const {
- if (const auto* block = DynamicTo<LayoutBlockFlow>(box_))
- return AreNGBlockFlowChildrenInline(block) && FirstChild().IsInline();
+bool NGBlockNode::IsInlineFormattingContextRoot(
+ NGLayoutInputNode* first_child_out) const {
+ if (const auto* block = DynamicTo<LayoutBlockFlow>(box_)) {
+ if (!AreNGBlockFlowChildrenInline(block))
+ return false;
+ NGLayoutInputNode first_child = FirstChild();
+ if (first_child.IsInline()) {
+ if (first_child_out)
+ *first_child_out = first_child;
+ return true;
+ }
+ }
return false;
}
@@ -1175,10 +1248,13 @@ bool NGBlockNode::IsAtomicInlineLevel() const {
}
bool NGBlockNode::HasAspectRatio() const {
+ if (Style().AspectRatio().has_value())
+ return true;
LayoutBox* layout_object = GetLayoutBox();
if (!layout_object->IsImage() && !IsA<LayoutVideo>(layout_object) &&
- !layout_object->IsCanvas())
+ !layout_object->IsCanvas() && !layout_object->IsSVGRoot()) {
return false;
+ }
// Retrieving this and throwing it away is wasteful. We could make this method
// return Optional<LogicalSize> that returns the aspect_ratio if there is one.
@@ -1186,6 +1262,12 @@ bool NGBlockNode::HasAspectRatio() const {
}
LogicalSize NGBlockNode::GetAspectRatio() const {
+ // The CSS parser will ensure that this will only be set if the feature
+ // is enabled.
+ const base::Optional<LogicalSize>& ratio = Style().LogicalAspectRatio();
+ if (ratio.has_value())
+ return *ratio;
+
base::Optional<LayoutUnit> computed_inline_size;
base::Optional<LayoutUnit> computed_block_size;
GetOverrideIntrinsicSize(&computed_inline_size, &computed_block_size);
@@ -1198,17 +1280,16 @@ LogicalSize NGBlockNode::GetAspectRatio() const {
LayoutUnit(legacy_sizing_info.aspect_ratio.Height()));
}
-bool NGBlockNode::UseLogicalBottomMarginEdgeForInlineBlockBaseline() const {
- auto* layout_box = DynamicTo<LayoutBlock>(GetLayoutBox());
- return layout_box &&
- layout_box->UseLogicalBottomMarginEdgeForInlineBlockBaseline();
-}
-
bool NGBlockNode::IsCustomLayoutLoaded() const {
DCHECK(box_->IsLayoutNGCustom());
return To<LayoutNGCustom>(box_)->IsLoaded();
}
+MathScriptType NGBlockNode::ScriptType() const {
+ DCHECK(IsA<MathMLScriptsElement>(GetLayoutBox()->GetNode()));
+ return To<MathMLScriptsElement>(GetLayoutBox()->GetNode())->GetScriptType();
+}
+
scoped_refptr<const NGLayoutResult> NGBlockNode::LayoutAtomicInline(
const NGConstraintSpace& parent_constraint_space,
const ComputedStyle& parent_style,
@@ -1359,8 +1440,14 @@ scoped_refptr<const NGLayoutResult> NGBlockNode::RunLegacyLayout(
scoped_refptr<const NGLayoutResult> NGBlockNode::RunSimplifiedLayout(
const NGLayoutAlgorithmParams& params,
- const NGLayoutResult& result) const {
- return NGSimplifiedLayoutAlgorithm(params, result).Layout();
+ const NGLayoutResult& previous_result) const {
+ NGSimplifiedLayoutAlgorithm algorithm(params, previous_result);
+ if (const auto* previous_box_fragment = DynamicTo<NGPhysicalBoxFragment>(
+ &previous_result.PhysicalFragment())) {
+ if (previous_box_fragment->HasItems())
+ return algorithm.LayoutWithItemsBuilder();
+ }
+ return algorithm.Layout();
}
void NGBlockNode::CopyBaselinesFromLegacyLayout(
@@ -1461,4 +1548,11 @@ void NGBlockNode::StoreMargins(const NGPhysicalBoxStrut& physical_margins) {
box_->SetMargin(physical_margins);
}
+void NGBlockNode::AddColumnResult(
+ scoped_refptr<const NGLayoutResult> result,
+ const NGBlockBreakToken* incoming_break_token) {
+ wtf_size_t index = FragmentIndex(incoming_break_token);
+ GetFlowThread(To<LayoutBlockFlow>(box_))->AddLayoutResult(result, index);
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_block_node.h b/chromium/third_party/blink/renderer/core/layout/ng/ng_block_node.h
index 7ccb575505f..9befdc8f5e0 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_block_node.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_block_node.h
@@ -21,10 +21,11 @@ class NGEarlyBreak;
class NGLayoutResult;
class NGPhysicalBoxFragment;
class NGPhysicalContainerFragment;
-struct MinMaxSizes;
struct NGBoxStrut;
struct NGLayoutAlgorithmParams;
+enum class MathScriptType;
+
// Represents a node to be laid out.
class CORE_EXPORT NGBlockNode final : public NGLayoutInputNode {
friend NGLayoutInputNode;
@@ -43,7 +44,8 @@ class CORE_EXPORT NGBlockNode final : public NGLayoutInputNode {
// If layout is dirty, it will perform layout using the previous constraint
// space used to generate the |NGLayoutResult|.
// Otherwise it will simply return the previous layout result generated.
- scoped_refptr<const NGLayoutResult> SimplifiedLayout();
+ scoped_refptr<const NGLayoutResult> SimplifiedLayout(
+ const NGPhysicalFragment& previous_fragment);
// This method is just for use within the |NGOutOfFlowLayoutPart|.
//
@@ -80,9 +82,9 @@ class CORE_EXPORT NGBlockNode final : public NGLayoutInputNode {
// The constraint space is also used to perform layout when this block's
// writing mode is orthogonal to its parent's, in which case the constraint
// space is not optional.
- MinMaxSizes ComputeMinMaxSizes(WritingMode container_writing_mode,
- const MinMaxSizesInput&,
- const NGConstraintSpace* = nullptr);
+ MinMaxSizesResult ComputeMinMaxSizes(WritingMode container_writing_mode,
+ const MinMaxSizesInput&,
+ const NGConstraintSpace* = nullptr);
MinMaxSizes ComputeMinMaxSizesFromLegacy(const MinMaxSizesInput&) const;
@@ -95,7 +97,8 @@ class CORE_EXPORT NGBlockNode final : public NGLayoutInputNode {
// This will only be the case if there is actual inline content. Empty nodes
// or nodes consisting purely of block-level, floats, and/or out-of-flow
// positioned children will return false.
- bool IsInlineFormattingContextRoot() const;
+ bool IsInlineFormattingContextRoot(
+ NGLayoutInputNode* first_child_out = nullptr) const;
bool IsInlineLevel() const;
bool IsAtomicInlineLevel() const;
@@ -121,14 +124,14 @@ class CORE_EXPORT NGBlockNode final : public NGLayoutInputNode {
return (IsDocumentElement() || IsBody());
}
- // CSS defines certain cases to synthesize inline block baselines from box.
- // See comments in UseLogicalBottomMarginEdgeForInlineBlockBaseline().
- bool UseLogicalBottomMarginEdgeForInlineBlockBaseline() const;
-
// Returns true if the custom layout node is in its loaded state (all script
// for the web-developer defined layout is ready).
bool IsCustomLayoutLoaded() const;
+ // Get script type for scripts (msub, msup, msubsup, munder, mover and
+ // munderover).
+ MathScriptType ScriptType() const;
+
// Layout an atomic inline; e.g., inline block.
scoped_refptr<const NGLayoutResult> LayoutAtomicInline(
const NGConstraintSpace& parent_constraint_space,
@@ -145,6 +148,12 @@ class CORE_EXPORT NGBlockNode final : public NGLayoutInputNode {
void StoreMargins(const NGConstraintSpace&, const NGBoxStrut& margins);
void StoreMargins(const NGPhysicalBoxStrut& margins);
+ // Add a column layout result to a list. Columns are essentially
+ // LayoutObject-less, but we still need to keep the fragments generated
+ // somewhere.
+ void AddColumnResult(scoped_refptr<const NGLayoutResult>,
+ const NGBlockBreakToken* incoming_break_token);
+
static bool CanUseNewLayout(const LayoutBox&);
bool CanUseNewLayout() const;
@@ -174,8 +183,8 @@ class CORE_EXPORT NGBlockNode final : public NGLayoutInputNode {
const NGConstraintSpace&,
const NGLayoutResult&,
const NGBlockBreakToken* previous_break_token);
- void CopyFragmentDataToLayoutBoxForInlineChildren(
- const NGPhysicalBoxFragment& container);
+ void CopyFragmentItemsToLayoutBox(const NGPhysicalBoxFragment& container,
+ const NGFragmentItems& items);
void CopyFragmentDataToLayoutBoxForInlineChildren(
const NGPhysicalContainerFragment& container,
LayoutUnit initial_container_width,
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_block_node_test.cc b/chromium/third_party/blink/renderer/core/layout/ng/ng_block_node_test.cc
index f42f0ef6ff5..3ad5edcf391 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_block_node_test.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_block_node_test.cc
@@ -174,9 +174,12 @@ TEST_F(NGBlockNodeForTest, MinAndMaxContent) {
const int kWidth = 30;
NGBlockNode box(ToLayoutBox(GetLayoutObjectByElementId("box")));
- MinMaxSizes sizes = box.ComputeMinMaxSizes(
- WritingMode::kHorizontalTb,
- MinMaxSizesInput(/* percentage_resolution_block_size */ LayoutUnit()));
+ MinMaxSizes sizes =
+ box.ComputeMinMaxSizes(
+ WritingMode::kHorizontalTb,
+ MinMaxSizesInput(
+ /* percentage_resolution_block_size */ LayoutUnit()))
+ .sizes;
EXPECT_EQ(LayoutUnit(kWidth), sizes.min_size);
EXPECT_EQ(LayoutUnit(kWidth), sizes.max_size);
}
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.cc b/chromium/third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.cc
index 96c7f46d336..8a0c0a6ebf2 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.cc
@@ -15,6 +15,7 @@
#include "third_party/blink/renderer/core/layout/ng/ng_break_token.h"
#include "third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.h"
#include "third_party/blink/renderer/core/layout/ng/ng_layout_result.h"
+#include "third_party/blink/renderer/core/layout/ng/ng_length_utils.h"
#include "third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h"
#include "third_party/blink/renderer/core/layout/ng/ng_positioned_float.h"
#include "third_party/blink/renderer/core/paint/ng/ng_paint_fragment.h"
@@ -77,8 +78,9 @@ void GatherInlineContainerFragmentsFromLinebox(
}
}
+template <class Items>
void GatherInlineContainerFragmentsFromItems(
- const Vector<std::unique_ptr<NGFragmentItem>>& items,
+ const Items& items,
const PhysicalOffset& box_offset,
NGBoxFragmentBuilder::InlineContainingBlockMap* inline_containing_block_map,
HashMap<const LayoutObject*, LineBoxPair>* containing_linebox_map) {
@@ -176,8 +178,7 @@ void NGBoxFragmentBuilder::AddBreakBeforeChild(
}
void NGBoxFragmentBuilder::AddResult(const NGLayoutResult& child_layout_result,
- const LogicalOffset offset,
- const LayoutInline* inline_container) {
+ const LogicalOffset offset) {
const auto& fragment = child_layout_result.PhysicalFragment();
if (items_builder_) {
if (const NGPhysicalLineBoxFragment* line =
@@ -187,7 +188,7 @@ void NGBoxFragmentBuilder::AddResult(const NGLayoutResult& child_layout_result,
// maybe OOF objects. Investigate how to handle them.
}
}
- AddChild(fragment, offset, inline_container);
+ AddChild(fragment, offset);
if (fragment.IsBox())
PropagateBreak(child_layout_result);
}
@@ -451,6 +452,20 @@ void NGBoxFragmentBuilder::ComputeInlineContainerGeometry(
}
}
+void NGBoxFragmentBuilder::SetLastBaselineToBlockEndMarginEdgeIfNeeded() {
+ if (ConstraintSpace()->BaselineAlgorithmType() !=
+ NGBaselineAlgorithmType::kInlineBlock)
+ return;
+
+ if (!node_.UseBlockEndMarginEdgeForInlineBlockBaseline())
+ return;
+
+ // When overflow is present (within an atomic-inline baseline context) we
+ // should always use the block-end margin edge as the baseline.
+ NGBoxStrut margins = ComputeMarginsForSelf(*ConstraintSpace(), Style());
+ SetLastBaseline(BlockSize() + margins.block_end);
+}
+
#if DCHECK_IS_ON()
void NGBoxFragmentBuilder::CheckNoBlockFragmentation() const {
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.h b/chromium/third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.h
index 288530aeceb..67cb8f120c3 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.h
@@ -106,9 +106,7 @@ class CORE_EXPORT NGBoxFragmentBuilder final
// Add a layout result. This involves appending the fragment and its relative
// offset to the builder, but also keeping track of out-of-flow positioned
// descendants, propagating fragmentainer breaks, and more.
- void AddResult(const NGLayoutResult&,
- const LogicalOffset,
- const LayoutInline* = nullptr);
+ void AddResult(const NGLayoutResult&, const LogicalOffset);
void AddBreakToken(scoped_refptr<const NGBreakToken>);
@@ -116,6 +114,9 @@ class CORE_EXPORT NGBoxFragmentBuilder final
const NGLogicalStaticPosition&,
const LayoutInline* inline_container);
+ // Specify whether this will be the first fragment generated for the node.
+ void SetIsFirstForNode(bool is_first) { is_first_for_node_ = is_first; }
+
// Set how much of the block-size we've used so far for this box. This will be
// the sum of the block-size of all previous fragments PLUS the one we're
// building now.
@@ -278,6 +279,11 @@ class CORE_EXPORT NGBoxFragmentBuilder final
NGBaselineAlgorithmType::kInlineBlock);
last_baseline_ = baseline;
}
+ base::Optional<LayoutUnit> LastBaseline() const { return last_baseline_; }
+
+ // The inline block baseline is at the block end margin edge under some
+ // circumstances. This function updates |LastBaseline| in such cases.
+ void SetLastBaselineToBlockEndMarginEdgeIfNeeded();
// The |NGFragmentItemsBuilder| for the inline formatting context of this box.
NGFragmentItemsBuilder* ItemsBuilder() { return items_builder_; }
@@ -340,6 +346,7 @@ class CORE_EXPORT NGBoxFragmentBuilder final
bool is_fieldset_container_ = false;
bool is_initial_block_size_indefinite_ = false;
bool is_inline_formatting_context_;
+ bool is_first_for_node_ = true;
bool did_break_;
bool has_forced_break_ = false;
bool is_new_fc_ = false;
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm.cc b/chromium/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm.cc
index f1034c33a1c..2db4791c47a 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm.cc
@@ -127,12 +127,6 @@ scoped_refptr<const NGLayoutResult> NGColumnLayoutAlgorithm::Layout() {
is_constrained_by_outer_fragmentation_context_ =
ConstraintSpace().HasKnownFragmentainerBlockSize();
- if (ConstraintSpace().HasBlockFragmentation()) {
- container_builder_.SetHasBlockFragmentation();
- if (ConstraintSpace().IsInitialColumnBalancingPass())
- container_builder_.SetIsInitialColumnBalancingPass();
- }
-
container_builder_.SetIsBlockFragmentationContextRoot();
intrinsic_block_size_ = border_scrollbar_padding_.block_start;
@@ -188,39 +182,37 @@ scoped_refptr<const NGLayoutResult> NGColumnLayoutAlgorithm::Layout() {
return container_builder_.ToBoxFragment();
}
-base::Optional<MinMaxSizes> NGColumnLayoutAlgorithm::ComputeMinMaxSizes(
+MinMaxSizesResult NGColumnLayoutAlgorithm::ComputeMinMaxSizes(
const MinMaxSizesInput& input) const {
// First calculate the min/max sizes of columns.
NGConstraintSpace space = CreateConstraintSpaceForMinMax();
NGFragmentGeometry fragment_geometry =
CalculateInitialMinMaxFragmentGeometry(space, Node());
NGBlockLayoutAlgorithm algorithm({Node(), fragment_geometry, space});
- base::Optional<MinMaxSizes> min_max_sizes =
- algorithm.ComputeMinMaxSizes(input);
- DCHECK(min_max_sizes.has_value());
- MinMaxSizes sizes = *min_max_sizes;
+ MinMaxSizesResult result = algorithm.ComputeMinMaxSizes(input);
// If column-width is non-auto, pick the larger of that and intrinsic column
// width.
if (!Style().HasAutoColumnWidth()) {
- sizes.min_size =
- std::max(sizes.min_size, LayoutUnit(Style().ColumnWidth()));
- sizes.max_size = std::max(sizes.max_size, sizes.min_size);
+ result.sizes.min_size =
+ std::max(result.sizes.min_size, LayoutUnit(Style().ColumnWidth()));
+ result.sizes.max_size =
+ std::max(result.sizes.max_size, result.sizes.min_size);
}
// Now convert those column min/max values to multicol container min/max
// values. We typically have multiple columns and also gaps between them.
int column_count = Style().ColumnCount();
DCHECK_GE(column_count, 1);
- sizes.min_size *= column_count;
- sizes.max_size *= column_count;
+ result.sizes.min_size *= column_count;
+ result.sizes.max_size *= column_count;
LayoutUnit column_gap = ResolveUsedColumnGap(LayoutUnit(), Style());
- sizes += column_gap * (column_count - 1);
+ result.sizes += column_gap * (column_count - 1);
// TODO(mstensho): Need to include spanners.
- sizes += border_scrollbar_padding_.InlineSum();
- return sizes;
+ result.sizes += border_scrollbar_padding_.InlineSum();
+ return result;
}
NGBreakStatus NGColumnLayoutAlgorithm::LayoutChildren() {
@@ -513,6 +505,8 @@ scoped_refptr<const NGLayoutResult> NGColumnLayoutAlgorithm::LayoutRow(
if (result->ColumnSpanner())
break;
+ Node().AddColumnResult(result, column_break_token.get());
+
column_break_token = To<NGBlockBreakToken>(column.BreakToken());
// If we're participating in an outer fragmentation context, we'll only
@@ -997,8 +991,8 @@ NGConstraintSpace NGColumnLayoutAlgorithm::CreateConstraintSpaceForSpanner(
space_builder.SetPercentageResolutionSize(content_box_size_);
if (ConstraintSpace().HasBlockFragmentation()) {
- SetupFragmentation(ConstraintSpace(), spanner, block_offset, &space_builder,
- /* is_new_fc */ true);
+ SetupSpaceBuilderForFragmentation(ConstraintSpace(), spanner, block_offset,
+ &space_builder, /* is_new_fc */ true);
}
return space_builder.ToConstraintSpace();
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm.h b/chromium/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm.h
index c516f1bafaa..70735070448 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm.h
@@ -26,8 +26,7 @@ class CORE_EXPORT NGColumnLayoutAlgorithm
scoped_refptr<const NGLayoutResult> Layout() override;
- base::Optional<MinMaxSizes> ComputeMinMaxSizes(
- const MinMaxSizesInput&) const override;
+ MinMaxSizesResult ComputeMinMaxSizes(const MinMaxSizesInput&) const override;
private:
// Lay out as many children as we can. If |kNeedsEarlierBreak| is returned, it
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm_test.cc b/chromium/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm_test.cc
index b2d3a0825ec..89e5c4de416 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm_test.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm_test.cc
@@ -2724,14 +2724,14 @@ TEST_F(NGColumnLayoutAlgorithmTest, MinMax) {
// Both column-count and column-width set.
style->SetColumnCount(3);
style->SetColumnWidth(80);
- sizes = algorithm.ComputeMinMaxSizes(zero_input);
+ sizes = algorithm.ComputeMinMaxSizes(zero_input).sizes;
ASSERT_TRUE(sizes.has_value());
EXPECT_EQ(LayoutUnit(260), sizes->min_size);
EXPECT_EQ(LayoutUnit(320), sizes->max_size);
// Only column-count set.
style->SetHasAutoColumnWidth();
- sizes = algorithm.ComputeMinMaxSizes(zero_input);
+ sizes = algorithm.ComputeMinMaxSizes(zero_input).sizes;
ASSERT_TRUE(sizes.has_value());
EXPECT_EQ(LayoutUnit(170), sizes->min_size);
EXPECT_EQ(LayoutUnit(320), sizes->max_size);
@@ -2739,7 +2739,7 @@ TEST_F(NGColumnLayoutAlgorithmTest, MinMax) {
// Only column-width set.
style->SetColumnWidth(80);
style->SetHasAutoColumnCount();
- sizes = algorithm.ComputeMinMaxSizes(zero_input);
+ sizes = algorithm.ComputeMinMaxSizes(zero_input).sizes;
ASSERT_TRUE(sizes.has_value());
EXPECT_EQ(LayoutUnit(80), sizes->min_size);
EXPECT_EQ(LayoutUnit(100), sizes->max_size);
@@ -4466,7 +4466,8 @@ TEST_F(NGColumnLayoutAlgorithmTest, SpannerWithContent) {
EXPECT_EQ(expectation, dump);
}
-TEST_F(NGColumnLayoutAlgorithmTest, TwoSpannersPercentWidth) {
+// TODO(crbug.com/1066617): Fix crash during pre-paint.
+TEST_F(NGColumnLayoutAlgorithmTest, DISABLED_TwoSpannersPercentWidth) {
SetBodyInnerHTML(R"HTML(
<style>
#parent {
@@ -4952,7 +4953,8 @@ TEST_F(NGColumnLayoutAlgorithmTest, MarginAndBorderTopWithSpanner) {
EXPECT_EQ(expectation, dump);
}
-TEST_F(NGColumnLayoutAlgorithmTest, BreakInsideSpannerWithMargins) {
+// TODO(crbug.com/1066617): Fix crash during pre-paint.
+TEST_F(NGColumnLayoutAlgorithmTest, DISABLED_BreakInsideSpannerWithMargins) {
SetBodyInnerHTML(R"HTML(
<style>
#parent {
@@ -5419,7 +5421,8 @@ TEST_F(NGColumnLayoutAlgorithmTest, SoftBreakBetweenSpanners2) {
EXPECT_EQ(expectation, dump);
}
-TEST_F(NGColumnLayoutAlgorithmTest, AvoidSoftBreakBetweenSpanners) {
+// TODO(crbug.com/1066617): Fix crash during pre-paint.
+TEST_F(NGColumnLayoutAlgorithmTest, DISABLED_AvoidSoftBreakBetweenSpanners) {
// There are three spanners in a nested multicol. The first two could fit in
// the same outer column, but the third one is too tall, and we also don't
// want to break before that one.So we should break between the two first
@@ -5455,7 +5458,8 @@ TEST_F(NGColumnLayoutAlgorithmTest, AvoidSoftBreakBetweenSpanners) {
EXPECT_EQ(expectation, dump);
}
-TEST_F(NGColumnLayoutAlgorithmTest, AvoidSoftBreakBetweenSpanners2) {
+// TODO(crbug.com/1066617): Fix crash during pre-paint.
+TEST_F(NGColumnLayoutAlgorithmTest, DISABLED_AvoidSoftBreakBetweenSpanners2) {
// There are two spanners in a nested multicol. They won't fit in the same
// outer column, but we don't want to break inside the second one, and also
// not between the spanners. The first spanner is breakable, so we should
@@ -5498,7 +5502,8 @@ TEST_F(NGColumnLayoutAlgorithmTest, AvoidSoftBreakBetweenSpanners2) {
EXPECT_EQ(expectation, dump);
}
-TEST_F(NGColumnLayoutAlgorithmTest, AvoidSoftBreakBetweenSpanners3) {
+// TODO(crbug.com/1066617): Fix crash during pre-paint.
+TEST_F(NGColumnLayoutAlgorithmTest, DISABLED_AvoidSoftBreakBetweenSpanners3) {
// Violate orphans and widows requests rather than break-between avoidance
// requests.
SetBodyInnerHTML(R"HTML(
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_constraint_space.h b/chromium/third_party/blink/renderer/core/layout/ng/ng_constraint_space.h
index e409701f6ce..6b49934f15d 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_constraint_space.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_constraint_space.h
@@ -558,10 +558,6 @@ class CORE_EXPORT NGConstraintSpace final {
return HasRareData() ? rare_data_->ClearanceOffset() : LayoutUnit::Min();
}
- bool ForceTruncateAtLineClamp() const {
- return HasRareData() ? rare_data_->ForceTruncateAtLineClamp() : true;
- }
-
base::Optional<int> LinesUntilClamp() const {
return HasRareData() ? rare_data_->LinesUntilClamp() : base::nullopt;
}
@@ -835,16 +831,6 @@ class CORE_EXPORT NGConstraintSpace final {
EnsureBlockData()->lines_until_clamp = value;
}
- int ForceTruncateAtLineClamp() const {
- return data_union_type == kBlockData
- ? block_data_.force_truncate_at_line_clamp
- : true;
- }
-
- void SetForceTruncateAtLineClamp(bool value) {
- EnsureBlockData()->force_truncate_at_line_clamp = value;
- }
-
NGBoxStrut TableCellBorders() const {
return data_union_type == kTableCellData
? table_cell_data_.table_cell_borders
@@ -934,13 +920,11 @@ class CORE_EXPORT NGConstraintSpace final {
private:
struct BlockData {
bool MaySkipLayout(const BlockData& other) const {
- return lines_until_clamp == other.lines_until_clamp &&
- force_truncate_at_line_clamp ==
- other.force_truncate_at_line_clamp;
+ return lines_until_clamp == other.lines_until_clamp;
}
bool IsInitialForMaySkipLayout() const {
- return !lines_until_clamp.has_value() && force_truncate_at_line_clamp;
+ return !lines_until_clamp.has_value();
}
NGMarginStrut margin_strut;
@@ -948,9 +932,6 @@ class CORE_EXPORT NGConstraintSpace final {
base::Optional<LayoutUnit> forced_bfc_block_offset;
LayoutUnit clearance_offset = LayoutUnit::Min();
base::Optional<int> lines_until_clamp;
- // If true and |lines_until_clamp| == 1, then the line should be truncated
- // regardless of whether there is more text that follows on the line.
- bool force_truncate_at_line_clamp = true;
};
struct TableCellData {
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_constraint_space_builder.h b/chromium/third_party/blink/renderer/core/layout/ng/ng_constraint_space_builder.h
index 68cc44fc392..30655178c30 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_constraint_space_builder.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_constraint_space_builder.h
@@ -318,15 +318,6 @@ class CORE_EXPORT NGConstraintSpaceBuilder final {
}
}
- void SetForceTruncateAtLineClamp(bool value) {
-#if DCHECK_IS_ON()
- DCHECK(!is_force_truncate_at_line_clamp_set_);
- is_force_truncate_at_line_clamp_set_ = true;
-#endif
- if (!value)
- space_.EnsureRareData()->SetForceTruncateAtLineClamp(value);
- }
-
void SetLinesUntilClamp(const base::Optional<int>& clamp) {
#if DCHECK_IS_ON()
DCHECK(!is_lines_until_clamp_set_);
@@ -401,7 +392,6 @@ class CORE_EXPORT NGConstraintSpaceBuilder final {
bool is_table_cell_intrinsic_padding_set_ = false;
bool is_custom_layout_data_set_ = false;
bool is_lines_until_clamp_set_ = false;
- bool is_force_truncate_at_line_clamp_set_ = false;
bool to_constraint_space_called_ = false;
#endif
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.cc b/chromium/third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.cc
index 4c26a00648f..2be126bca70 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.cc
@@ -90,8 +90,28 @@ void NGContainerFragmentBuilder::PropagateChildData(
// We only need to report if inflow or floating elements depend on the
// percentage resolution block-size. OOF-positioned children resolve their
// percentages against the "final" size of their parent.
- if (child.DependsOnPercentageBlockSize() && !child.IsOutOfFlowPositioned())
- has_descendant_that_depends_on_percentage_block_size_ = true;
+ if (!has_descendant_that_depends_on_percentage_block_size_) {
+ if (child.DependsOnPercentageBlockSize() && !child.IsOutOfFlowPositioned())
+ has_descendant_that_depends_on_percentage_block_size_ = true;
+
+ // We may have a child which has the following style:
+ // <div style="position: relative; top: 50%;"></div>
+ // We need to mark this as depending on our %-block-size for the its offset
+ // to be correctly calculated. This is *slightly* too broad as it only
+ // depends on the available block-size, rather than the %-block-size.
+ const auto& child_style = child.Style();
+ if (child.IsCSSBox() && child_style.GetPosition() == EPosition::kRelative) {
+ if (IsHorizontalWritingMode(Style().GetWritingMode())) {
+ if (child_style.Top().IsPercentOrCalc() ||
+ child_style.Bottom().IsPercentOrCalc())
+ has_descendant_that_depends_on_percentage_block_size_ = true;
+ } else {
+ if (child_style.Left().IsPercentOrCalc() ||
+ child_style.Right().IsPercentOrCalc())
+ has_descendant_that_depends_on_percentage_block_size_ = true;
+ }
+ }
+ }
// The |may_have_descendant_above_block_start_| flag is used to determine if
// a fragment can be re-used when preceding floats are present. This is
@@ -166,13 +186,14 @@ void NGContainerFragmentBuilder::AddOutOfFlowChildCandidate(
NGBlockNode child,
const LogicalOffset& child_offset,
NGLogicalStaticPosition::InlineEdge inline_edge,
- NGLogicalStaticPosition::BlockEdge block_edge) {
+ NGLogicalStaticPosition::BlockEdge block_edge,
+ bool needs_block_offset_adjustment) {
DCHECK(child);
// If an OOF-positioned candidate has a static-position which uses a
- // non-block-start edge, we need to adjust its static-position when the final
- // block-size is known.
- bool needs_block_offset_adjustment =
+ // non-block-start edge, we may need to adjust its static-position when the
+ // final block-size is known.
+ needs_block_offset_adjustment &=
block_edge != NGLogicalStaticPosition::BlockEdge::kBlockStart;
has_oof_candidate_that_needs_block_offset_adjustment_ |=
needs_block_offset_adjustment;
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.h b/chromium/third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.h
index a76a849df0b..4edb57dcf10 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.h
@@ -110,12 +110,13 @@ class CORE_EXPORT NGContainerFragmentBuilder : public NGFragmentBuilder {
// NGOutOfFlowLayoutPart(container_style, builder).Run();
//
// See layout part for builder interaction.
- void AddOutOfFlowChildCandidate(NGBlockNode,
- const LogicalOffset& child_offset,
- NGLogicalStaticPosition::InlineEdge =
- NGLogicalStaticPosition::kInlineStart,
- NGLogicalStaticPosition::BlockEdge =
- NGLogicalStaticPosition::kBlockStart);
+ void AddOutOfFlowChildCandidate(
+ NGBlockNode,
+ const LogicalOffset& child_offset,
+ NGLogicalStaticPosition::InlineEdge =
+ NGLogicalStaticPosition::kInlineStart,
+ NGLogicalStaticPosition::BlockEdge = NGLogicalStaticPosition::kBlockStart,
+ bool needs_block_offset_adjustment = true);
// This should only be used for inline-level OOF-positioned nodes.
// |inline_container_direction| is the current text direction for determining
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm.cc b/chromium/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm.cc
index 02c3b80ed79..2e117e138f2 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm.cc
@@ -34,7 +34,6 @@ NGFieldsetLayoutAlgorithm::NGFieldsetLayoutAlgorithm(
borders_ = container_builder_.Borders();
padding_ = container_builder_.Padding();
border_box_size_ = container_builder_.InitialBorderBoxSize();
- block_start_padding_edge_ = borders_.block_start;
// Leading border and padding should only apply to the first fragment. We
// don't adjust the value of border_padding_ itself so that it can be used
@@ -44,9 +43,6 @@ NGFieldsetLayoutAlgorithm::NGFieldsetLayoutAlgorithm(
}
scoped_refptr<const NGLayoutResult> NGFieldsetLayoutAlgorithm::Layout() {
- // TODO(almaher): Make sure the border start is handled correctly during
- // fragmentation.
-
// Layout of a fieldset container consists of two parts: Create a child
// fragment for the rendered legend (if any), and create a child fragment for
// the fieldset contents anonymous box (if any). Fieldset scrollbars and
@@ -58,16 +54,11 @@ scoped_refptr<const NGLayoutResult> NGFieldsetLayoutAlgorithm::Layout() {
// anonymous child box, and since padding is inside the scrollport, padding
// also needs to be handled by the anonymous child.
- if (ConstraintSpace().HasBlockFragmentation()) {
- container_builder_.SetHasBlockFragmentation();
- // The whereabouts of our container's so far best breakpoint is none of our
- // business, but we store its appeal, so that we don't look for breakpoints
- // with lower appeal than that.
- container_builder_.SetBreakAppeal(ConstraintSpace().EarlyBreakAppeal());
-
- if (ConstraintSpace().IsInitialColumnBalancingPass())
- container_builder_.SetIsInitialColumnBalancingPass();
- }
+ // Calculate the amount of the border block-start that was consumed in
+ // previous fragments.
+ consumed_border_block_start_ =
+ std::min(consumed_block_size_, borders_.block_start);
+ intrinsic_block_size_ = borders_.block_start - consumed_border_block_start_;
NGBreakStatus break_status = LayoutChildren();
if (break_status == NGBreakStatus::kNeedsEarlierBreak) {
@@ -75,14 +66,15 @@ scoped_refptr<const NGLayoutResult> NGFieldsetLayoutAlgorithm::Layout() {
return container_builder_.Abort(NGLayoutResult::kNeedsEarlierBreak);
}
- intrinsic_block_size_ =
- ClampIntrinsicBlockSize(ConstraintSpace(), Node(),
- adjusted_border_padding_, intrinsic_block_size_);
+ intrinsic_block_size_ = ClampIntrinsicBlockSize(
+ ConstraintSpace(), Node(), adjusted_border_padding_,
+ intrinsic_block_size_ + borders_.block_end);
// Recompute the block-axis size now that we know our content size.
border_box_size_.block_size =
ComputeBlockSizeForFragment(ConstraintSpace(), Style(), border_padding_,
- intrinsic_block_size_ + consumed_block_size_);
+ intrinsic_block_size_ + consumed_block_size_,
+ border_box_size_.inline_size);
// The above computation utility knows nothing about fieldset weirdness. The
// legend may eat from the available content box block size. Make room for
@@ -113,7 +105,7 @@ scoped_refptr<const NGLayoutResult> NGFieldsetLayoutAlgorithm::Layout() {
container_builder_.SetBlockSize(block_size);
}
- NGOutOfFlowLayoutPart(Node(), ConstraintSpace(), borders_with_legend_,
+ NGOutOfFlowLayoutPart(Node(), ConstraintSpace(), borders_,
&container_builder_)
.Run();
@@ -154,62 +146,66 @@ NGBreakStatus NGFieldsetLayoutAlgorithm::LayoutChildren() {
NGBreakStatus break_status = LayoutLegend(legend, legend_break_token);
if (break_status != NGBreakStatus::kContinue)
return break_status;
- }
- borders_with_legend_ = borders_;
- borders_with_legend_.block_start = block_start_padding_edge_;
-
- // The legend may eat from the available content box block size. If the
- // border_box_size_ is expanded to encompass the legend, then update the
- // border_box_size_ here, as well, to ensure the fieldset content gets the
- // correct size.
- if (!Node().ShouldApplySizeContainment() && legend_needs_layout) {
- minimum_border_box_block_size_ =
- borders_with_legend_.BlockSum() + padding_.BlockSum();
- if (border_box_size_.block_size != kIndefiniteSize) {
- border_box_size_.block_size =
- std::max(border_box_size_.block_size, minimum_border_box_block_size_);
+ // The legend may eat from the available content box block size. Calculate
+ // the minimum block size needed to encompass the legend.
+ if (!Node().ShouldApplySizeContainment()) {
+ minimum_border_box_block_size_ =
+ intrinsic_block_size_ + padding_.BlockSum() + borders_.block_end;
}
}
+ NGBoxStrut borders_with_legend = borders_;
+ borders_with_legend.block_start = intrinsic_block_size_;
LogicalSize adjusted_padding_box_size =
- ShrinkAvailableSize(border_box_size_, borders_with_legend_);
-
- // If the legend has been laid out in previous fragments,
- // adjusted_padding_box_size will need to be adjusted further to account for
- // block size taken up by the legend.
- if (legend && adjusted_padding_box_size.block_size != kIndefiniteSize) {
- LayoutUnit content_consumed_block_size =
- content_break_token ? content_break_token->ConsumedBlockSize()
- : LayoutUnit();
- LayoutUnit legend_block_size =
- consumed_block_size_ - content_consumed_block_size;
- adjusted_padding_box_size.block_size =
- std::max(padding_.BlockSum(),
- adjusted_padding_box_size.block_size - legend_block_size);
- }
-
- if ((IsResumingLayout(content_break_token.get())) ||
- (!block_start_padding_edge_adjusted_ && IsResumingLayout(BreakToken()))) {
- borders_with_legend_.block_start = LayoutUnit();
+ ShrinkAvailableSize(border_box_size_, borders_with_legend);
+
+ if (adjusted_padding_box_size.block_size != kIndefiniteSize) {
+ // If intrinsic_block_size_ does not include the border block-start that was
+ // consumed in previous fragments, exclude consumed_border_block_start_ from
+ // adjusted_padding_box_size, as well.
+ if (consumed_border_block_start_ > LayoutUnit())
+ adjusted_padding_box_size.block_size -= consumed_border_block_start_;
+
+ // If the legend has been laid out in previous fragments,
+ // adjusted_padding_box_size will need to be adjusted further to account for
+ // block size taken up by the legend.
+ if (legend) {
+ LayoutUnit content_consumed_block_size =
+ content_break_token ? content_break_token->ConsumedBlockSize()
+ : LayoutUnit();
+
+ // Calculate the amount of the border block-end that was consumed in
+ // previous fragments.
+ DCHECK_NE(border_box_size_.block_size, kIndefiniteSize);
+ LayoutUnit consumed_border_block_end =
+ std::max(consumed_block_size_ -
+ (border_box_size_.block_size - borders_.block_end),
+ LayoutUnit());
+
+ LayoutUnit legend_block_size =
+ consumed_block_size_ - content_consumed_block_size -
+ consumed_border_block_start_ - consumed_border_block_end;
+ DCHECK_GE(legend_block_size, LayoutUnit());
+
+ adjusted_padding_box_size.block_size =
+ std::max(padding_.BlockSum(),
+ adjusted_padding_box_size.block_size - legend_block_size);
+ }
}
- intrinsic_block_size_ = borders_with_legend_.BlockSum();
// Proceed with normal fieldset children (excluding the rendered legend). They
// all live inside an anonymous child box of the fieldset container.
auto fieldset_content = Node().GetFieldsetContent();
if (fieldset_content && (content_break_token || !has_seen_all_children)) {
- LayoutUnit fragmentainer_block_offset;
- if (ConstraintSpace().HasBlockFragmentation()) {
- fragmentainer_block_offset =
- ConstraintSpace().FragmentainerOffsetAtBfc() + intrinsic_block_size_;
- if (legend_broke_ &&
- IsFragmentainerOutOfSpace(fragmentainer_block_offset))
- return NGBreakStatus::kContinue;
- }
- NGBreakStatus break_status = LayoutFieldsetContent(
- fieldset_content, content_break_token, adjusted_padding_box_size,
- fragmentainer_block_offset, !!legend);
+ if (ConstraintSpace().HasBlockFragmentation() && legend_broke_ &&
+ IsFragmentainerOutOfSpace(ConstraintSpace().FragmentainerOffsetAtBfc() +
+ intrinsic_block_size_))
+ return NGBreakStatus::kContinue;
+
+ NGBreakStatus break_status =
+ LayoutFieldsetContent(fieldset_content, content_break_token,
+ adjusted_padding_box_size, !!legend);
if (break_status == NGBreakStatus::kNeedsEarlierBreak)
return break_status;
}
@@ -284,8 +280,9 @@ NGBreakStatus NGFieldsetLayoutAlgorithm::LayoutLegend(
NGFragment(writing_mode_, physical_fragment).BlockSize() +
legend_margins.BlockSum();
LayoutUnit space_left = borders_.block_start - legend_margin_box_block_size;
+
if (space_left > LayoutUnit()) {
- // Don't adjust the block_offset if the legend broke.
+ // Don't adjust the block-start offset of the legend if the legend broke.
if (legend_break_token || legend_broke_)
break;
@@ -302,12 +299,20 @@ NGBreakStatus NGFieldsetLayoutAlgorithm::LayoutLegend(
continue;
}
} else {
+ // If the border is smaller, intrinsic_block_size_ should now be based on
+ // the size of the legend instead of the border.
+ intrinsic_block_size_ = legend_margin_box_block_size;
+
+ // Don't adjust the block-start offset of the fragment border if it broke.
+ if (BreakToken() || (ConstraintSpace().HasKnownFragmentainerBlockSize() &&
+ legend_margin_box_block_size >
+ ConstraintSpace().FragmentainerBlockSize()))
+ break;
// If the legend is larger than the width of the fieldset block-start
// border, the actual padding edge of the fieldset will be moved
// accordingly. This will be the block-start offset for the fieldset
// contents anonymous box.
- block_start_padding_edge_ = legend_margin_box_block_size;
- block_start_padding_edge_adjusted_ = true;
+ borders_.block_start = legend_margin_box_block_size;
}
break;
} while (true);
@@ -330,11 +335,9 @@ NGBreakStatus NGFieldsetLayoutAlgorithm::LayoutFieldsetContent(
NGBlockNode& fieldset_content,
scoped_refptr<const NGBlockBreakToken> content_break_token,
LogicalSize adjusted_padding_box_size,
- LayoutUnit fragmentainer_block_offset,
bool has_legend) {
auto child_space = CreateConstraintSpaceForFieldsetContent(
- fieldset_content, adjusted_padding_box_size,
- borders_with_legend_.block_start);
+ fieldset_content, adjusted_padding_box_size, intrinsic_block_size_);
auto result = fieldset_content.Layout(child_space, content_break_token.get());
// TODO(layout-dev): Handle abortions caused by block fragmentation.
@@ -345,7 +348,7 @@ NGBreakStatus NGFieldsetLayoutAlgorithm::LayoutFieldsetContent(
// TODO(almaher): The legend should be treated as out-of-flow.
break_status = BreakBeforeChildIfNeeded(
ConstraintSpace(), fieldset_content, *result.get(),
- fragmentainer_block_offset,
+ ConstraintSpace().FragmentainerOffsetAtBfc() + intrinsic_block_size_,
/*has_container_separation*/ has_legend, &container_builder_);
EBreakBetween break_after = JoinFragmentainerBreakValues(
result->FinalBreakAfter(), fieldset_content.Style().BreakAfter());
@@ -353,7 +356,8 @@ NGBreakStatus NGFieldsetLayoutAlgorithm::LayoutFieldsetContent(
}
if (break_status == NGBreakStatus::kContinue) {
- container_builder_.AddResult(*result, borders_with_legend_.StartOffset());
+ LogicalOffset offset(borders_.inline_start, intrinsic_block_size_);
+ container_builder_.AddResult(*result, offset);
intrinsic_block_size_ +=
NGFragment(writing_mode_, result->PhysicalFragment()).BlockSize();
container_builder_.SetHasSeenAllChildren();
@@ -369,9 +373,9 @@ bool NGFieldsetLayoutAlgorithm::IsFragmentainerOutOfSpace(
return block_offset >= FragmentainerSpaceAtBfcStart(ConstraintSpace());
}
-base::Optional<MinMaxSizes> NGFieldsetLayoutAlgorithm::ComputeMinMaxSizes(
+MinMaxSizesResult NGFieldsetLayoutAlgorithm::ComputeMinMaxSizes(
const MinMaxSizesInput& input) const {
- MinMaxSizes sizes;
+ MinMaxSizesResult result;
// TODO(crbug.com/1011842): Need to consider content-size here.
bool apply_size_containment = Node().ShouldApplySizeContainment();
@@ -379,29 +383,31 @@ base::Optional<MinMaxSizes> NGFieldsetLayoutAlgorithm::ComputeMinMaxSizes(
// Size containment does not consider the legend for sizing.
if (!apply_size_containment) {
if (NGBlockNode legend = Node().GetRenderedLegend()) {
- sizes = ComputeMinAndMaxContentContribution(Style(), legend, input);
- sizes += ComputeMinMaxMargins(Style(), legend).InlineSum();
+ result = ComputeMinAndMaxContentContribution(Style(), legend, input);
+ result.sizes += ComputeMinMaxMargins(Style(), legend).InlineSum();
}
}
// The fieldset content includes the fieldset padding (and any scrollbars),
// while the legend is a regular child and doesn't. We may have a fieldset
// without any content or legend, so add the padding here, on the outside.
- sizes += ComputePadding(ConstraintSpace(), Style()).InlineSum();
+ result.sizes += ComputePadding(ConstraintSpace(), Style()).InlineSum();
// Size containment does not consider the content for sizing.
if (!apply_size_containment) {
if (NGBlockNode content = Node().GetFieldsetContent()) {
- MinMaxSizes content_min_max_sizes =
+ MinMaxSizesResult content_result =
ComputeMinAndMaxContentContribution(Style(), content, input);
- content_min_max_sizes +=
+ content_result.sizes +=
ComputeMinMaxMargins(Style(), content).InlineSum();
- sizes.Encompass(content_min_max_sizes);
+ result.sizes.Encompass(content_result.sizes);
+ result.depends_on_percentage_block_size |=
+ content_result.depends_on_percentage_block_size;
}
}
- sizes += ComputeBorders(ConstraintSpace(), Style()).InlineSum();
- return sizes;
+ result.sizes += ComputeBorders(ConstraintSpace(), Style()).InlineSum();
+ return result;
}
const NGConstraintSpace
@@ -420,8 +426,8 @@ NGFieldsetLayoutAlgorithm::CreateConstraintSpaceForLegend(
builder.SetTextDirection(legend.Style().Direction());
if (ConstraintSpace().HasBlockFragmentation()) {
- SetupFragmentation(ConstraintSpace(), legend, block_offset, &builder,
- /* is_new_fc */ true);
+ SetupSpaceBuilderForFragmentation(ConstraintSpace(), legend, block_offset,
+ &builder, /* is_new_fc */ true);
builder.SetEarlyBreakAppeal(container_builder_.BreakAppeal());
}
return builder.ToConstraintSpace();
@@ -432,6 +438,7 @@ NGFieldsetLayoutAlgorithm::CreateConstraintSpaceForFieldsetContent(
NGBlockNode fieldset_content,
LogicalSize padding_box_size,
LayoutUnit block_offset) {
+ DCHECK(fieldset_content.CreatesNewFormattingContext());
NGConstraintSpaceBuilder builder(ConstraintSpace(),
ConstraintSpace().GetWritingMode(),
/* is_new_fc */ true);
@@ -441,8 +448,9 @@ NGFieldsetLayoutAlgorithm::CreateConstraintSpaceForFieldsetContent(
builder.SetIsFixedBlockSize(padding_box_size.block_size != kIndefiniteSize);
if (ConstraintSpace().HasBlockFragmentation()) {
- SetupFragmentation(ConstraintSpace(), fieldset_content, block_offset,
- &builder, /* is_new_fc */ true);
+ SetupSpaceBuilderForFragmentation(ConstraintSpace(), fieldset_content,
+ block_offset, &builder,
+ /* is_new_fc */ true);
builder.SetEarlyBreakAppeal(container_builder_.BreakAppeal());
}
return builder.ToConstraintSpace();
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm.h b/chromium/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm.h
index c375081737a..a6a6d9996a0 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm.h
@@ -25,8 +25,7 @@ class CORE_EXPORT NGFieldsetLayoutAlgorithm
scoped_refptr<const NGLayoutResult> Layout() override;
- base::Optional<MinMaxSizes> ComputeMinMaxSizes(
- const MinMaxSizesInput&) const override;
+ MinMaxSizesResult ComputeMinMaxSizes(const MinMaxSizesInput&) const override;
private:
NGBreakStatus LayoutChildren();
@@ -37,7 +36,6 @@ class CORE_EXPORT NGFieldsetLayoutAlgorithm
NGBlockNode& fieldset_content,
scoped_refptr<const NGBlockBreakToken> content_break_token,
LogicalSize adjusted_padding_box_size,
- LayoutUnit fragmentainer_block_offset,
bool has_legend);
const NGConstraintSpace CreateConstraintSpaceForLegend(
@@ -62,10 +60,6 @@ class CORE_EXPORT NGFieldsetLayoutAlgorithm
// and padding are only applied to the first fragment.
NGBoxStrut adjusted_border_padding_;
- // The result of borders_ after positioning the fieldset's legend element.
- NGBoxStrut borders_with_legend_;
-
- LayoutUnit block_start_padding_edge_;
LayoutUnit intrinsic_block_size_;
const LayoutUnit consumed_block_size_;
LogicalSize border_box_size_;
@@ -75,9 +69,9 @@ class CORE_EXPORT NGFieldsetLayoutAlgorithm
// the legend.
LayoutUnit minimum_border_box_block_size_;
- // If true, this indicates the block_start_padding_edge_ had changed from its
- // initial value during the current layout pass.
- bool block_start_padding_edge_adjusted_ = false;
+ // The amount of the border block-start that was consumed in previous
+ // fragments.
+ LayoutUnit consumed_border_block_start_;
// If true, this indicates that the legend broke during the current layout
// pass.
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm_test.cc b/chromium/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm_test.cc
index 36789003311..8f88b0d0ee2 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm_test.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm_test.cc
@@ -46,9 +46,7 @@ class NGFieldsetLayoutAlgorithmTest
NGFieldsetLayoutAlgorithm algorithm({node, fragment_geometry, space});
MinMaxSizesInput input(
/* percentage_resolution_block_size */ (LayoutUnit()));
- auto min_max = algorithm.ComputeMinMaxSizes(input);
- EXPECT_TRUE(min_max.has_value());
- return *min_max;
+ return algorithm.ComputeMinMaxSizes(input).sizes;
}
MinMaxSizes RunComputeMinMaxSizes(const char* element_id) {
@@ -1815,6 +1813,7 @@ TEST_F(NGFieldsetLayoutAlgorithmTest, SmallLegendLargeBorderFragmentation) {
expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::.
offset:unplaced size:220x40
offset:60,0 size:10x10
+ offset:60,20 size:100x10
)DUMP";
EXPECT_EQ(expectation, dump);
@@ -1830,9 +1829,7 @@ TEST_F(NGFieldsetLayoutAlgorithmTest, SmallLegendLargeBorderFragmentation) {
fragment = NGBaseLayoutAlgorithmTest::RunFieldsetLayoutAlgorithm(
node, space, fragment->BreakToken());
- // TODO(almaher): There should be no break token here. In this case the bottom
- // border never reduces in size, causing fragmentation to continue infinitely.
- ASSERT_TRUE(fragment->BreakToken());
+ ASSERT_FALSE(fragment->BreakToken());
dump = DumpFragmentTree(fragment.get());
expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::.
@@ -1882,6 +1879,7 @@ TEST_F(NGFieldsetLayoutAlgorithmTest, SmallerLegendLargeBorderFragmentation) {
dump = DumpFragmentTree(fragment.get());
expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::.
offset:unplaced size:220x40
+ offset:60,20 size:100x10
)DUMP";
EXPECT_EQ(expectation, dump);
@@ -1897,9 +1895,7 @@ TEST_F(NGFieldsetLayoutAlgorithmTest, SmallerLegendLargeBorderFragmentation) {
fragment = NGBaseLayoutAlgorithmTest::RunFieldsetLayoutAlgorithm(
node, space, fragment->BreakToken());
- // TODO(almaher): There should be no break token here. In this case the bottom
- // border never reduces in size, causing fragmentation to continue infinitely.
- ASSERT_TRUE(fragment->BreakToken());
+ ASSERT_FALSE(fragment->BreakToken());
dump = DumpFragmentTree(fragment.get());
expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::.
@@ -1949,6 +1945,7 @@ TEST_F(NGFieldsetLayoutAlgorithmTest, SmallerLegendLargeBorderWithBreak) {
dump = DumpFragmentTree(fragment.get());
expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::.
offset:unplaced size:220x40
+ offset:60,20 size:100x10
)DUMP";
EXPECT_EQ(expectation, dump);
@@ -1964,9 +1961,7 @@ TEST_F(NGFieldsetLayoutAlgorithmTest, SmallerLegendLargeBorderWithBreak) {
fragment = NGBaseLayoutAlgorithmTest::RunFieldsetLayoutAlgorithm(
node, space, fragment->BreakToken());
- // TODO(almaher): There should be no break token here. In this case the bottom
- // border never reduces in size, causing fragmentation to continue infinitely.
- ASSERT_TRUE(fragment->BreakToken());
+ ASSERT_FALSE(fragment->BreakToken());
dump = DumpFragmentTree(fragment.get());
expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::.
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_floats_utils.cc b/chromium/third_party/blink/renderer/core/layout/ng/ng_floats_utils.cc
index 3404db2e94f..f772d4d8bbe 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_floats_utils.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_floats_utils.cc
@@ -72,8 +72,9 @@ NGConstraintSpace CreateConstraintSpaceForFloat(
DCHECK(parent_space.HasBlockFragmentation());
DCHECK_EQ(style.GetWritingMode(), parent_space.GetWritingMode());
- SetupFragmentation(parent_space, unpositioned_float.node,
- *origin_block_offset, &builder, /* is_new_fc */ true);
+ SetupSpaceBuilderForFragmentation(parent_space, unpositioned_float.node,
+ *origin_block_offset, &builder,
+ /* is_new_fc */ true);
} else {
builder.SetFragmentationType(NGFragmentationType::kFragmentNone);
}
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_fragment_builder.h b/chromium/third_party/blink/renderer/core/layout/ng/ng_fragment_builder.h
index f0bd55d5bc0..a1ceb920f02 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_fragment_builder.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_fragment_builder.h
@@ -47,9 +47,6 @@ class CORE_EXPORT NGFragmentBuilder {
void SetIsHiddenForPaint(bool value) { is_hidden_for_paint_ = value; }
- // Specify whether this will be the first fragment generated for the node.
- void SetIsFirstForNode(bool is_first) { is_first_for_node_ = is_first; }
-
const LayoutObject* GetLayoutObject() const { return layout_object_; }
protected:
@@ -83,7 +80,6 @@ class CORE_EXPORT NGFragmentBuilder {
LayoutObject* layout_object_ = nullptr;
scoped_refptr<NGBreakToken> break_token_;
bool is_hidden_for_paint_ = false;
- bool is_first_for_node_ = true;
friend class NGPhysicalFragment;
};
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_fragment_child_iterator.cc b/chromium/third_party/blink/renderer/core/layout/ng/ng_fragment_child_iterator.cc
index 167e14136f6..6275cba58ee 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_fragment_child_iterator.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_fragment_child_iterator.cc
@@ -108,10 +108,12 @@ void NGFragmentChildIterator::UpdateSelfFromFragment(
To<NGBlockBreakToken>(previous_fragment->BreakToken());
current_.break_token_for_fragmentainer_only_ = true;
} else {
- // This is a column spanner. We'll leave |current_block_break_token_|
- // alone here, as it will be used as in incoming break token when we get
- // to the next column.
+ // This is a column spanner, or in the case of a fieldset, this could be a
+ // rendered legend. We'll leave |current_block_break_token_| alone here,
+ // as it will be used as in incoming break token when we get to the next
+ // column.
DCHECK(
+ previous_fragment->IsRenderedLegend() ||
NGBlockNode(ToLayoutBox(previous_fragment->GetMutableLayoutObject()))
.IsColumnSpanAll());
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.cc b/chromium/third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.cc
index 327212ca3a8..abc1aa6fc79 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.cc
@@ -163,11 +163,11 @@ NGBreakAppeal CalculateBreakAppealInside(const NGConstraintSpace& space,
return appeal;
}
-void SetupFragmentation(const NGConstraintSpace& parent_space,
- const NGLayoutInputNode& child,
- LayoutUnit fragmentainer_offset_delta,
- NGConstraintSpaceBuilder* builder,
- bool is_new_fc) {
+void SetupSpaceBuilderForFragmentation(const NGConstraintSpace& parent_space,
+ const NGLayoutInputNode& child,
+ LayoutUnit fragmentainer_offset_delta,
+ NGConstraintSpaceBuilder* builder,
+ bool is_new_fc) {
DCHECK(parent_space.HasBlockFragmentation());
// If the child is truly unbreakable, it won't participate in block
@@ -187,6 +187,28 @@ void SetupFragmentation(const NGConstraintSpace& parent_space,
builder->SetIsInColumnBfc();
}
+void SetupFragmentBuilderForFragmentation(
+ const NGConstraintSpace& space,
+ const NGBlockBreakToken* previous_break_token,
+ NGBoxFragmentBuilder* builder) {
+ builder->SetHasBlockFragmentation();
+
+ // The whereabouts of our container's so far best breakpoint is none of our
+ // business, but we store its appeal, so that we don't look for breakpoints
+ // with lower appeal than that.
+ builder->SetBreakAppeal(space.EarlyBreakAppeal());
+
+ if (space.IsInitialColumnBalancingPass())
+ builder->SetIsInitialColumnBalancingPass();
+
+ unsigned sequence_number = 0;
+ if (previous_break_token && !previous_break_token->IsBreakBefore()) {
+ sequence_number = previous_break_token->SequenceNumber() + 1;
+ builder->SetIsFirstForNode(false);
+ }
+ builder->SetSequenceNumber(sequence_number);
+}
+
void FinishFragmentation(const NGConstraintSpace& space,
const NGBlockBreakToken* previous_break_token,
LayoutUnit block_size,
@@ -194,13 +216,8 @@ void FinishFragmentation(const NGConstraintSpace& space,
LayoutUnit space_left,
NGBoxFragmentBuilder* builder) {
LayoutUnit previously_consumed_block_size;
- unsigned sequence_number = 0;
- if (previous_break_token && !previous_break_token->IsBreakBefore()) {
+ if (previous_break_token && !previous_break_token->IsBreakBefore())
previously_consumed_block_size = previous_break_token->ConsumedBlockSize();
- sequence_number = previous_break_token->SequenceNumber() + 1;
- builder->SetIsFirstForNode(false);
- }
- builder->SetSequenceNumber(sequence_number);
if (builder->DidBreak()) {
// One of our children broke. Even if we fit within the remaining space, we
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.h b/chromium/third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.h
index 48ca63e28a5..b12b66333ff 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.h
@@ -47,14 +47,6 @@ inline bool IsResumingLayout(const NGBlockBreakToken* token) {
return token && !token->IsBreakBefore();
}
-// Return true if the fragment to be generated for the specified item is going
-// to be the first fragment for the node.
-inline bool IsFirstForNode(const NGInlineItem& item,
- const NGInlineBreakToken* token) {
- return item.IsFirstForNode() &&
- (!token || item.StartOffset() >= token->TextOffset());
-}
-
// Calculate the final "break-between" value at a class A or C breakpoint. This
// is the combination of all break-before and break-after values that met at the
// breakpoint.
@@ -102,11 +94,22 @@ inline void AdjustForFragmentation(const NGBlockBreakToken* break_token,
// set to the offset from the parent block formatting context, or, if the parent
// formatting context starts in a previous fragmentainer; the offset from the
// current fragmentainer block-start.
-void SetupFragmentation(const NGConstraintSpace& parent_space,
- const NGLayoutInputNode& child,
- LayoutUnit fragmentainer_offset_delta,
- NGConstraintSpaceBuilder*,
- bool is_new_fc);
+void SetupSpaceBuilderForFragmentation(const NGConstraintSpace& parent_space,
+ const NGLayoutInputNode& child,
+ LayoutUnit fragmentainer_offset_delta,
+ NGConstraintSpaceBuilder*,
+ bool is_new_fc);
+
+// Set up a node's fragment builder for block fragmentation. To be done at the
+// beginning of layout.
+void SetupFragmentBuilderForFragmentation(
+ const NGConstraintSpace&,
+ const NGBlockBreakToken* previous_break_token,
+ NGBoxFragmentBuilder*);
+
+inline void SetupFragmentBuilderForFragmentation(const NGConstraintSpace&,
+ const NGInlineBreakToken*,
+ NGLineBoxFragmentBuilder*) {}
// Write fragmentation information to the fragment builder after layout.
void FinishFragmentation(const NGConstraintSpace&,
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_grid_layout_algorithm.cc b/chromium/third_party/blink/renderer/core/layout/ng/ng_grid_layout_algorithm.cc
new file mode 100644
index 00000000000..ee14539bc1c
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_grid_layout_algorithm.cc
@@ -0,0 +1,27 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/layout/ng/ng_grid_layout_algorithm.h"
+
+namespace blink {
+
+NGGridLayoutAlgorithm::NGGridLayoutAlgorithm(
+ const NGLayoutAlgorithmParams& params)
+ : NGLayoutAlgorithm(params) {
+ DCHECK(params.space.IsNewFormattingContext());
+ DCHECK(!params.break_token);
+ container_builder_.SetIsNewFormattingContext(true);
+ container_builder_.SetInitialFragmentGeometry(params.fragment_geometry);
+}
+
+scoped_refptr<const NGLayoutResult> NGGridLayoutAlgorithm::Layout() {
+ return container_builder_.ToBoxFragment();
+}
+
+MinMaxSizesResult NGGridLayoutAlgorithm::ComputeMinMaxSizes(
+ const MinMaxSizesInput& input) const {
+ return {MinMaxSizes(), /* depends_on_percentage_block_size */ true};
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_grid_layout_algorithm.h b/chromium/third_party/blink/renderer/core/layout/ng/ng_grid_layout_algorithm.h
new file mode 100644
index 00000000000..65530019710
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_grid_layout_algorithm.h
@@ -0,0 +1,28 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_GRID_LAYOUT_ALGORITHM_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_GRID_LAYOUT_ALGORITHM_H_
+
+#include "third_party/blink/renderer/core/layout/ng/ng_block_break_token.h"
+#include "third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.h"
+#include "third_party/blink/renderer/core/layout/ng/ng_layout_algorithm.h"
+
+namespace blink {
+
+class CORE_EXPORT NGGridLayoutAlgorithm
+ : public NGLayoutAlgorithm<NGBlockNode,
+ NGBoxFragmentBuilder,
+ NGBlockBreakToken> {
+ public:
+ explicit NGGridLayoutAlgorithm(const NGLayoutAlgorithmParams& params);
+
+ scoped_refptr<const NGLayoutResult> Layout() override;
+
+ MinMaxSizesResult ComputeMinMaxSizes(const MinMaxSizesInput&) const override;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_GRID_LAYOUT_ALGORITHM_H_
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_layout_algorithm.h b/chromium/third_party/blink/renderer/core/layout/ng/ng_layout_algorithm.h
index b04949398e8..90c7bd7b3f0 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_layout_algorithm.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_layout_algorithm.h
@@ -10,6 +10,7 @@
#include "third_party/blink/renderer/core/layout/min_max_sizes.h"
#include "third_party/blink/renderer/core/layout/ng/ng_block_node.h"
#include "third_party/blink/renderer/core/layout/ng/ng_constraint_space.h"
+#include "third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
namespace blink {
@@ -30,13 +31,9 @@ class NGLayoutAlgorithmOperations {
// Computes the min-content and max-content intrinsic sizes for the given box.
// The result will not take any min-width, max-width or width properties into
- // account. If the return value is empty, the caller is expected to synthesize
- // this value from the overflow rect returned from Layout called with an
- // available width of 0 and LayoutUnit::max(), respectively.
- virtual base::Optional<MinMaxSizes> ComputeMinMaxSizes(
- const MinMaxSizesInput&) const {
- return base::nullopt;
- }
+ // account.
+ virtual MinMaxSizesResult ComputeMinMaxSizes(
+ const MinMaxSizesInput&) const = 0;
};
// Parameters to pass when creating a layout algorithm for a block node.
@@ -60,6 +57,7 @@ struct NGLayoutAlgorithmParams {
const NGConstraintSpace& space;
const NGBlockBreakToken* break_token;
const NGEarlyBreak* early_break;
+ const NGLayoutResult* previous_result = nullptr;
};
// Base class for all LayoutNG algorithms.
@@ -80,7 +78,13 @@ class CORE_EXPORT NGLayoutAlgorithm : public NGLayoutAlgorithmOperations {
style,
&space,
space.GetWritingMode(),
- direction) {}
+ direction) {
+ if (UNLIKELY(space.HasBlockFragmentation())) {
+ DCHECK(space.IsAnonymous() || !node.IsMonolithic());
+ SetupFragmentBuilderForFragmentation(space, BreakToken(),
+ &container_builder_);
+ }
+ }
NGLayoutAlgorithm(const NGLayoutAlgorithmParams& params)
: NGLayoutAlgorithm(params.node,
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_layout_input_node.cc b/chromium/third_party/blink/renderer/core/layout/ng/ng_layout_input_node.cc
index 28d5bcce744..fe3212c1b9c 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_layout_input_node.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_layout_input_node.cc
@@ -60,7 +60,7 @@ void AppendNodeToString(NGLayoutInputNode node,
} // namespace
-MinMaxSizes NGLayoutInputNode::ComputeMinMaxSizes(
+MinMaxSizesResult NGLayoutInputNode::ComputeMinMaxSizes(
WritingMode writing_mode,
const MinMaxSizesInput& input,
const NGConstraintSpace* space) {
@@ -95,7 +95,7 @@ NGLayoutInputNode NGLayoutInputNode::NextSibling() {
PhysicalSize NGLayoutInputNode::InitialContainingBlockSize() const {
IntSize icb_size =
- GetDocument().GetLayoutView()->GetLayoutSize(kExcludeScrollbars);
+ GetDocument().GetLayoutView()->GetLayoutSize(kIncludeScrollbars);
return PhysicalSize(icb_size);
}
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_layout_input_node.h b/chromium/third_party/blink/renderer/core/layout/ng/ng_layout_input_node.h
index 45acfcb0f7c..59c09f148d1 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_layout_input_node.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_layout_input_node.h
@@ -27,9 +27,9 @@ class NGPaintFragment;
struct MinMaxSizes;
struct PhysicalSize;
-// Input to the min/max inline size calculation algorithm for child nodes. Child
-// nodes within the same formatting context need to know which floats are beside
-// them.
+// The input to the min/max inline size calculation algorithm for child nodes.
+// Child nodes within the same formatting context need to know which floats are
+// beside them.
struct MinMaxSizesInput {
// The min-max size calculation (un-intuitively) requires a percentage
// resolution size!
@@ -48,6 +48,14 @@ struct MinMaxSizesInput {
LayoutUnit percentage_resolution_block_size;
};
+// The output of the min/max inline size calculation algorithm. Contains the
+// min/max sizes, and if this calculation will change if the
+// |MinMaxSizesInput::percentage_resolution_block_size| value changes.
+struct MinMaxSizesResult {
+ MinMaxSizes sizes;
+ bool depends_on_percentage_block_size = false;
+};
+
// Represents the input to a layout algorithm for a given node. The layout
// engine should use the style, node type to determine which type of layout
// algorithm to use to produce fragments for this node.
@@ -111,6 +119,8 @@ class CORE_EXPORT NGLayoutInputNode {
bool IsFieldsetContainer() const {
return IsBlock() && box_->IsLayoutNGFieldset();
}
+ bool IsRubyRun() const { return IsBlock() && box_->IsRubyRun(); }
+ bool IsRubyText() const { return IsBlock() && box_->IsRubyText(); }
// Return true if this is the legend child of a fieldset that gets special
// treatment (i.e. placed over the block-start border).
@@ -155,10 +165,10 @@ class CORE_EXPORT NGLayoutInputNode {
return false;
}
- // Returns border box.
- MinMaxSizes ComputeMinMaxSizes(WritingMode,
- const MinMaxSizesInput&,
- const NGConstraintSpace* = nullptr);
+ // Returns the border-box min/max content sizes for the node.
+ MinMaxSizesResult ComputeMinMaxSizes(WritingMode,
+ const MinMaxSizesInput&,
+ const NGConstraintSpace* = nullptr);
// Returns intrinsic sizing information for replaced elements.
// ComputeReplacedSize can use it to compute actual replaced size.
@@ -183,6 +193,14 @@ class CORE_EXPORT NGLayoutInputNode {
return box_->ShouldApplySizeContainment();
}
+ // CSS defines certain cases to synthesize inline block baselines from box.
+ // See comments in UseLogicalBottomMarginEdgeForInlineBlockBaseline().
+ bool UseBlockEndMarginEdgeForInlineBlockBaseline() const {
+ if (auto* layout_box = DynamicTo<LayoutBlock>(GetLayoutBox()))
+ return layout_box->UseLogicalBottomMarginEdgeForInlineBlockBaseline();
+ return false;
+ }
+
// CSS intrinsic sizing getters.
// https://drafts.csswg.org/css-sizing-4/#intrinsic-size-override
// Note that this returns kIndefiniteSize if the override was not specified.
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_layout_result.cc b/chromium/third_party/blink/renderer/core/layout/ng/ng_layout_result.cc
index 6dc8f994eee..6f3e2393746 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_layout_result.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_layout_result.cc
@@ -69,7 +69,7 @@ NGLayoutResult::NGLayoutResult(
}
if (builder->overflow_block_size_ != kIndefiniteSize &&
builder->overflow_block_size_ != intrinsic_block_size_) {
- EnsureRareData()->overflow_block_size_ = builder->overflow_block_size_;
+ EnsureRareData()->overflow_block_size = builder->overflow_block_size_;
}
if (builder->custom_layout_data_) {
EnsureRareData()->custom_layout_data =
@@ -254,6 +254,7 @@ void NGLayoutResult::CheckSameForSimplifiedLayout(
To<NGPhysicalBoxFragment>(*other.physical_fragment_),
check_same_block_size);
+ DCHECK(LinesUntilClamp() == other.LinesUntilClamp());
DCHECK(UnpositionedListMarker() == other.UnpositionedListMarker());
ExclusionSpace().CheckSameForSimplifiedLayout(other.ExclusionSpace());
@@ -276,6 +277,8 @@ void NGLayoutResult::CheckSameForSimplifiedLayout(
DCHECK_EQ(bitfields_.subtree_modified_margin_strut,
other.bitfields_.subtree_modified_margin_strut);
+ DCHECK_EQ(CustomLayoutData(), other.CustomLayoutData());
+
DCHECK_EQ(bitfields_.initial_break_before,
other.bitfields_.initial_break_before);
DCHECK_EQ(bitfields_.final_break_after, other.bitfields_.final_break_after);
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_layout_result.h b/chromium/third_party/blink/renderer/core/layout/ng/ng_layout_result.h
index 3faf3aa43aa..5d15b09f808 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_layout_result.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_layout_result.h
@@ -151,8 +151,8 @@ class CORE_EXPORT NGLayoutResult : public RefCounted<NGLayoutResult> {
}
LayoutUnit OverflowBlockSize() const {
- return HasRareData() && rare_data_->overflow_block_size_ != kIndefiniteSize
- ? rare_data_->overflow_block_size_
+ return HasRareData() && rare_data_->overflow_block_size != kIndefiniteSize
+ ? rare_data_->overflow_block_size
: intrinsic_block_size_;
}
@@ -372,7 +372,7 @@ class CORE_EXPORT NGLayoutResult : public RefCounted<NGLayoutResult> {
};
NGExclusionSpace exclusion_space;
scoped_refptr<SerializedScriptValue> custom_layout_data;
- LayoutUnit overflow_block_size_ = kIndefiniteSize;
+ LayoutUnit overflow_block_size = kIndefiniteSize;
#if DCHECK_IS_ON()
bool has_tallest_unbreakable_block_size = false;
#endif
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_layout_result_caching_test.cc b/chromium/third_party/blink/renderer/core/layout/ng/ng_layout_result_caching_test.cc
index 24df10ed942..573498622f7 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_layout_result_caching_test.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_layout_result_caching_test.cc
@@ -1502,22 +1502,25 @@ TEST_F(NGLayoutResultCachingTest, MissIsFixedBlockSizeIndefinite) {
EXPECT_EQ(result.get(), nullptr);
}
-TEST_F(NGLayoutResultCachingTest, HitFlexBoxMeasureAndLayout) {
+TEST_F(NGLayoutResultCachingTest, HitColumnFlexBoxMeasureAndLayout) {
ScopedLayoutNGFlexBoxForTest layout_ng_flex_box(true);
SetBodyInnerHTML(R"HTML(
<!DOCTYPE html>
- <div style="display: flex; flex-direction: column; width: 100px; height: 100px;">
+ <style>
+ .bfc { display: flex; flex-direction: column; width: 100px; height: 100px; }
+ </style>
+ <div class="bfc">
<div id="src1" style="flex-grow: 0;">
<div style="height: 50px;"></div>
</div>
</div>
- <div style="display: flex; flex-direction: column; width: 100px; height: 100px;">
+ <div class="bfc">
<div id="src2" style="flex-grow: 1;">
<div style="height: 50px;"></div>
</div>
</div>
- <div style="display: flex; flex-direction: column; width: 100px; height: 100px;">
+ <div class="bfc">
<div id="test1" style="flex-grow: 2;">
<div style="height: 50px;"></div>
</div>
@@ -1553,5 +1556,152 @@ TEST_F(NGLayoutResultCachingTest, HitFlexBoxMeasureAndLayout) {
EXPECT_NE(result.get(), nullptr);
}
+TEST_F(NGLayoutResultCachingTest, HitRowFlexBoxMeasureAndLayout) {
+ ScopedLayoutNGFlexBoxForTest layout_ng_flex_box(true);
+
+ SetBodyInnerHTML(R"HTML(
+ <!DOCTYPE html>
+ <style>
+ .bfc { display: flex; width: 100px; }
+ </style>
+ <div class="bfc">
+ <div id="src1">
+ <div style="height: 50px;"></div>
+ </div>
+ </div>
+ <div class="bfc">
+ <div id="src2">
+ <div style="height: 70px;"></div>
+ </div>
+ <div style="width: 0px; height: 100px;"></div>
+ </div>
+ <div class="bfc">
+ <div id="test1">
+ <div style="height: 50px;"></div>
+ </div>
+ <div style="width: 0px; height: 100px;"></div>
+ </div>
+ )HTML");
+
+ auto* test1 = To<LayoutBlockFlow>(GetLayoutObjectByElementId("test1"));
+ auto* src1 = To<LayoutBlockFlow>(GetLayoutObjectByElementId("src1"));
+ auto* src2 = To<LayoutBlockFlow>(GetLayoutObjectByElementId("src2"));
+
+ NGLayoutCacheStatus cache_status;
+ base::Optional<NGFragmentGeometry> fragment_geometry;
+
+ // "src1" only had one "measure" pass performed, and should hit the "measure"
+ // cache-slot for "test1".
+ NGConstraintSpace space =
+ src1->GetCachedLayoutResult()->GetConstraintSpaceForCaching();
+ scoped_refptr<const NGLayoutResult> result = test1->CachedLayoutResult(
+ space, nullptr, nullptr, &fragment_geometry, &cache_status);
+
+ EXPECT_EQ(space.CacheSlot(), NGCacheSlot::kMeasure);
+ EXPECT_EQ(cache_status, NGLayoutCacheStatus::kHit);
+ EXPECT_NE(result.get(), nullptr);
+
+ // "src2" had both a "measure" and "layout" pass performed, and should hit
+ // the "layout" cache-slot for "test1".
+ space = src2->GetCachedLayoutResult()->GetConstraintSpaceForCaching();
+ result = test1->CachedLayoutResult(space, nullptr, nullptr,
+ &fragment_geometry, &cache_status);
+
+ EXPECT_EQ(space.CacheSlot(), NGCacheSlot::kLayout);
+ EXPECT_EQ(cache_status, NGLayoutCacheStatus::kHit);
+ EXPECT_NE(result.get(), nullptr);
+}
+
+TEST_F(NGLayoutResultCachingTest, HitFlexLegacyImg) {
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ .bfc { display: flex; flex-direction: column; width: 300px; }
+ .bfc > * { display: flex; }
+ </style>
+ <div class="bfc">
+ <div id="test">
+ <img />
+ </div>
+ </div>
+ <div class="bfc" style="height: 200px;">
+ <div id="src">
+ <img />
+ </div>
+ </div>
+ )HTML");
+
+ auto* test = To<LayoutBlock>(GetLayoutObjectByElementId("test"));
+ auto* src = To<LayoutBlock>(GetLayoutObjectByElementId("src"));
+
+ NGLayoutCacheStatus cache_status;
+ base::Optional<NGFragmentGeometry> fragment_geometry;
+ const NGConstraintSpace& space =
+ src->GetCachedLayoutResult()->GetConstraintSpaceForCaching();
+ scoped_refptr<const NGLayoutResult> result = test->CachedLayoutResult(
+ space, nullptr, nullptr, &fragment_geometry, &cache_status);
+
+ EXPECT_EQ(cache_status, NGLayoutCacheStatus::kHit);
+ EXPECT_NE(result.get(), nullptr);
+}
+
+TEST_F(NGLayoutResultCachingTest, HitFlexLegacyGrid) {
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ .bfc { display: flex; flex-direction: column; width: 300px; }
+ .bfc > * { display: flex; }
+ .grid { display: grid; }
+ </style>
+ <div class="bfc">
+ <div id="test">
+ <div class="grid"></div>
+ </div>
+ </div>
+ <div class="bfc" style="height: 200px;">
+ <div id="src">
+ <div class="grid"></div>
+ </div>
+ </div>
+ )HTML");
+
+ auto* test = To<LayoutBlock>(GetLayoutObjectByElementId("test"));
+ auto* src = To<LayoutBlock>(GetLayoutObjectByElementId("src"));
+
+ NGLayoutCacheStatus cache_status;
+ base::Optional<NGFragmentGeometry> fragment_geometry;
+ const NGConstraintSpace& space =
+ src->GetCachedLayoutResult()->GetConstraintSpaceForCaching();
+ scoped_refptr<const NGLayoutResult> result = test->CachedLayoutResult(
+ space, nullptr, nullptr, &fragment_geometry, &cache_status);
+
+ EXPECT_EQ(cache_status, NGLayoutCacheStatus::kHit);
+ EXPECT_NE(result.get(), nullptr);
+}
+
+TEST_F(NGLayoutResultCachingTest, HitOrthogonalRoot) {
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ span { display: inline-block; width: 20px; height: 250px }
+ </style>
+ <div id="target" style="display: flex;">
+ <div style="writing-mode: vertical-rl; line-height: 0;">
+ <span></span><span></span>
+ </div>
+ </div>
+ )HTML");
+
+ auto* target = To<LayoutBlock>(GetLayoutObjectByElementId("target"));
+
+ NGLayoutCacheStatus cache_status;
+ base::Optional<NGFragmentGeometry> fragment_geometry;
+ const NGConstraintSpace& space =
+ target->GetCachedLayoutResult()->GetConstraintSpaceForCaching();
+ scoped_refptr<const NGLayoutResult> result = target->CachedLayoutResult(
+ space, nullptr, nullptr, &fragment_geometry, &cache_status);
+
+ // We should hit the cache using the same constraint space.
+ EXPECT_EQ(cache_status, NGLayoutCacheStatus::kHit);
+ EXPECT_NE(result.get(), nullptr);
+}
+
} // namespace
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_layout_utils.cc b/chromium/third_party/blink/renderer/core/layout/ng/ng_layout_utils.cc
index 3802930ac23..db86d7af448 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_layout_utils.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_layout_utils.cc
@@ -228,12 +228,17 @@ NGLayoutCacheStatus CalculateSizeBasedLayoutCacheStatusWithGeometry(
block_size = ComputeBlockSizeForFragment(
new_space, style, fragment_geometry.border + fragment_geometry.padding,
- layout_result.IntrinsicBlockSize());
+ layout_result.IntrinsicBlockSize(),
+ fragment_geometry.border_box_size.inline_size);
}
bool is_block_size_equal = block_size == fragment.BlockSize();
if (!is_block_size_equal) {
+ // Only block-flow supports changing the block-size for simplified layout.
+ if (!node.IsBlockFlow() || node.IsLayoutNGCustom())
+ return NGLayoutCacheStatus::kNeedsLayout;
+
// If we are the document or body element in quirks mode, changing our size
// means that a scrollbar was added/removed. Require full layout.
if (node.IsQuirkyAndFillsViewport())
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_layout_utils.h b/chromium/third_party/blink/renderer/core/layout/ng/ng_layout_utils.h
index a1d2b06980d..248895697a5 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_layout_utils.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_layout_utils.h
@@ -19,9 +19,10 @@ class NGLayoutResult;
// See |NGSimplifiedLayoutAlgorithm| for details about the
// |kNeedsSimplifiedLayout| cache miss type.
enum class NGLayoutCacheStatus {
- kHit, // Cache hit, no additional work required.
- kNeedsLayout, // Cache miss, full layout required.
- kNeedsSimplifiedLayout // Cache miss, simplified layout required.
+ kHit, // Cache hit, no additional work required.
+ kNeedsLayout, // Cache miss, full layout required.
+ kNeedsSimplifiedLayout, // Cache miss, simplified layout required.
+ kCanReuseLines // Cache miss, may be possible to reuse lines.
};
// Calculates the |NGLayoutCacheStatus| based on sizing information. Returns:
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_length_utils.cc b/chromium/third_party/blink/renderer/core/layout/ng/ng_length_utils.cc
index e07c07e0d08..25629c7019c 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_length_utils.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_length_utils.cc
@@ -54,24 +54,6 @@ inline EBlockAlignment BlockAlignment(const ComputedStyle& style,
} // anonymous namespace
-bool NeedMinMaxSizeForContentContribution(WritingMode mode,
- const ComputedStyle& style) {
- // During the intrinsic sizes pass percentages/calc() are defined to behave
- // like 'auto'. As a result we need to calculate the intrinsic sizes for any
- // children with percentages. E.g.
- // <div style="float:left;">
- // <div style="width:30%;">text text</div>
- // </div>
- if (mode == WritingMode::kHorizontalTb) {
- return style.Width().IsIntrinsicOrAuto() ||
- style.Width().IsPercentOrCalc() || style.MinWidth().IsIntrinsic() ||
- style.MaxWidth().IsIntrinsic();
- }
- return style.Height().IsIntrinsicOrAuto() ||
- style.Height().IsPercentOrCalc() || style.MinHeight().IsIntrinsic() ||
- style.MaxHeight().IsIntrinsic();
-}
-
// Check if we shouldn't resolve a percentage/calc()/-webkit-fill-available
// if we are in the intrinsic sizes phase.
bool InlineLengthUnresolvable(const Length& length, LengthResolvePhase phase) {
@@ -181,7 +163,6 @@ LayoutUnit ResolveBlockLengthInternal(
const NGBoxStrut& border_padding,
const Length& length,
LayoutUnit content_size,
- LengthResolvePhase phase,
const LayoutUnit* opt_percentage_resolution_block_size_for_min_max) {
DCHECK_EQ(constraint_space.GetWritingMode(), style.GetWritingMode());
@@ -242,11 +223,37 @@ LayoutUnit ResolveBlockLengthInternal(
}
}
-MinMaxSizes ComputeMinAndMaxContentContribution(
+namespace {
+
+LayoutUnit InlineSizeFromAspectRatio(const NGBoxStrut& border_padding,
+ const LogicalSize& aspect_ratio,
+ EBoxSizing box_sizing,
+ LayoutUnit block_size) {
+ if (box_sizing == EBoxSizing::kBorderBox)
+ return block_size * aspect_ratio.inline_size / aspect_ratio.block_size;
+
+ return ((block_size - border_padding.BlockSum()) * aspect_ratio.inline_size /
+ aspect_ratio.block_size) +
+ border_padding.InlineSum();
+}
+
+LayoutUnit BlockSizeFromAspectRatio(const NGBoxStrut& border_padding,
+ const LogicalSize& aspect_ratio,
+ EBoxSizing box_sizing,
+ LayoutUnit inline_size) {
+ if (box_sizing == EBoxSizing::kBorderBox)
+ return inline_size * aspect_ratio.block_size / aspect_ratio.inline_size;
+
+ return ((inline_size - border_padding.InlineSum()) * aspect_ratio.block_size /
+ aspect_ratio.inline_size) +
+ border_padding.BlockSum();
+}
+
+template <typename MinMaxSizesFunc>
+MinMaxSizesResult ComputeMinAndMaxContentContributionInternal(
WritingMode parent_writing_mode,
const ComputedStyle& style,
- const NGBoxStrut& border_padding,
- const base::Optional<MinMaxSizes>& min_max_sizes) {
+ const MinMaxSizesFunc& min_max_sizes_func) {
WritingMode child_writing_mode = style.GetWritingMode();
// Synthesize a zero-sized constraint space for resolving sizes against.
@@ -254,26 +261,31 @@ MinMaxSizes ComputeMinAndMaxContentContribution(
NGConstraintSpaceBuilder(child_writing_mode, child_writing_mode,
/* is_new_fc */ false)
.ToConstraintSpace();
+ NGBoxStrut border_padding =
+ ComputeBorders(space, style) + ComputePadding(space, style);
- LayoutUnit content_size =
- min_max_sizes ? min_max_sizes->max_size : kIndefiniteSize;
-
- MinMaxSizes computed_sizes;
+ MinMaxSizesResult result;
const Length& inline_size = parent_writing_mode == WritingMode::kHorizontalTb
? style.Width()
: style.Height();
if (inline_size.IsAuto() || inline_size.IsPercentOrCalc() ||
inline_size.IsFillAvailable() || inline_size.IsFitContent()) {
- CHECK(min_max_sizes.has_value());
- computed_sizes = *min_max_sizes;
+ result = min_max_sizes_func();
} else {
if (IsParallelWritingMode(parent_writing_mode, child_writing_mode)) {
- computed_sizes = ResolveMainInlineLength(space, style, border_padding,
- min_max_sizes, inline_size);
+ MinMaxSizes sizes;
+ sizes = ResolveMainInlineLength(space, style, border_padding,
+ min_max_sizes_func, inline_size);
+ result = {sizes, /* depends_on_percentage_block_size */ false};
} else {
- computed_sizes =
- ResolveMainBlockLength(space, style, border_padding, inline_size,
- content_size, LengthResolvePhase::kIntrinsic);
+ auto IntrinsicBlockSizeFunc = [&]() -> LayoutUnit {
+ return min_max_sizes_func().sizes.max_size;
+ };
+ MinMaxSizes sizes;
+ sizes = ResolveMainBlockLength(space, style, border_padding, inline_size,
+ IntrinsicBlockSizeFunc,
+ LengthResolvePhase::kIntrinsic);
+ result = {sizes, /* depends_on_percentage_block_size */ false};
}
}
@@ -282,31 +294,47 @@ MinMaxSizes ComputeMinAndMaxContentContribution(
: style.MaxHeight();
LayoutUnit max;
if (IsParallelWritingMode(parent_writing_mode, child_writing_mode)) {
- max = ResolveMaxInlineLength(space, style, border_padding, min_max_sizes,
- max_length, LengthResolvePhase::kIntrinsic);
+ max =
+ ResolveMaxInlineLength(space, style, border_padding, min_max_sizes_func,
+ max_length, LengthResolvePhase::kIntrinsic);
} else {
max = ResolveMaxBlockLength(space, style, border_padding, max_length,
LengthResolvePhase::kIntrinsic);
}
- computed_sizes.Constrain(max);
+ result.sizes.Constrain(max);
const Length& min_length = parent_writing_mode == WritingMode::kHorizontalTb
? style.MinWidth()
: style.MinHeight();
LayoutUnit min;
if (IsParallelWritingMode(parent_writing_mode, child_writing_mode)) {
- min = ResolveMinInlineLength(space, style, border_padding, min_max_sizes,
- min_length, LengthResolvePhase::kIntrinsic);
+ min =
+ ResolveMinInlineLength(space, style, border_padding, min_max_sizes_func,
+ min_length, LengthResolvePhase::kIntrinsic);
} else {
min = ResolveMinBlockLength(space, style, border_padding, min_length,
LengthResolvePhase::kIntrinsic);
}
- computed_sizes.Encompass(min);
+ result.sizes.Encompass(min);
+
+ return result;
+}
- return computed_sizes;
+} // namespace
+
+MinMaxSizes ComputeMinAndMaxContentContributionForTest(
+ WritingMode parent_writing_mode,
+ const ComputedStyle& style,
+ const MinMaxSizes& min_max_sizes) {
+ auto MinMaxSizesFunc = [&]() -> MinMaxSizesResult {
+ return {min_max_sizes, false};
+ };
+ return ComputeMinAndMaxContentContributionInternal(parent_writing_mode, style,
+ MinMaxSizesFunc)
+ .sizes;
}
-MinMaxSizes ComputeMinAndMaxContentContribution(
+MinMaxSizesResult ComputeMinAndMaxContentContribution(
const ComputedStyle& parent_style,
NGLayoutInputNode child,
const MinMaxSizesInput& input) {
@@ -335,14 +363,20 @@ MinMaxSizes ComputeMinAndMaxContentContribution(
if (needs_size_reset)
box->ClearOverrideContainingBlockContentSize();
- return result;
+
+ // Replaced elements which have a percentage block-size use the
+ // |MinMaxSizesInput::percentage_resolution_block_size| field.
+ bool depends_on_percentage_block_size =
+ child_style.LogicalMinHeight().IsPercentOrCalc() ||
+ child_style.LogicalHeight().IsPercentOrCalc() ||
+ child_style.LogicalMaxHeight().IsPercentOrCalc();
+ return {result, depends_on_percentage_block_size};
}
}
- base::Optional<MinMaxSizes> min_max_sizes;
- if (NeedMinMaxSizeForContentContribution(parent_writing_mode, child_style)) {
+ auto MinMaxSizesFunc = [&]() -> MinMaxSizesResult {
// We need to set up a constraint space with correct fallback available
- // inline size in case of orthogonal children.
+ // inline-size in case of orthogonal children.
NGConstraintSpace indefinite_constraint_space;
const NGConstraintSpace* child_constraint_space = nullptr;
if (!IsParallelWritingMode(parent_writing_mode, child_writing_mode)) {
@@ -350,20 +384,28 @@ MinMaxSizes ComputeMinAndMaxContentContribution(
CreateIndefiniteConstraintSpaceForChild(parent_style, child);
child_constraint_space = &indefinite_constraint_space;
}
- min_max_sizes = child.ComputeMinMaxSizes(parent_writing_mode, input,
- child_constraint_space);
- }
- // Synthesize a zero-sized constraint space for determining the borders, and
- // padding.
- NGConstraintSpace space =
- NGConstraintSpaceBuilder(child_writing_mode, child_writing_mode,
- /* is_new_fc */ false)
- .ToConstraintSpace();
- NGBoxStrut border_padding =
- ComputeBorders(space, child_style) + ComputePadding(space, child_style);
+ return child.ComputeMinMaxSizes(parent_writing_mode, input,
+ child_constraint_space);
+ };
+
+ return ComputeMinAndMaxContentContributionInternal(
+ parent_writing_mode, child_style, MinMaxSizesFunc);
+}
- return ComputeMinAndMaxContentContribution(parent_writing_mode, child_style,
- border_padding, min_max_sizes);
+LayoutUnit ComputeInlineSizeFromAspectRatio(const NGConstraintSpace& space,
+ const ComputedStyle& style,
+ const NGBoxStrut& border_padding) {
+ if (UNLIKELY(style.LogicalAspectRatio() && !style.LogicalHeight().IsAuto())) {
+ // Check if we can get an inline size using the aspect ratio
+ LayoutUnit block_size = ComputeBlockSizeForFragment(
+ space, style, border_padding, kIndefiniteSize, base::nullopt);
+ if (block_size != kIndefiniteSize) {
+ return InlineSizeFromAspectRatio(border_padding,
+ *style.LogicalAspectRatio(),
+ style.BoxSizing(), block_size);
+ }
+ }
+ return kIndefiniteSize;
}
LayoutUnit ComputeInlineSizeForFragment(
@@ -376,27 +418,42 @@ LayoutUnit ComputeInlineSizeForFragment(
const ComputedStyle& style = node.Style();
Length logical_width = style.LogicalWidth();
- if (logical_width.IsAuto() && space.IsShrinkToFit())
- logical_width = Length::FitContent();
-
- auto MinMaxSizesFunc = [&]() -> MinMaxSizes {
+ auto MinMaxSizesFunc = [&]() -> MinMaxSizesResult {
if (override_min_max_sizes_for_test)
- return *override_min_max_sizes_for_test;
+ return {*override_min_max_sizes_for_test, false};
return node.ComputeMinMaxSizes(
space.GetWritingMode(),
MinMaxSizesInput(space.PercentageResolutionBlockSize()), &space);
};
- LayoutUnit extent = ResolveMainInlineLength(space, style, border_padding,
- MinMaxSizesFunc, logical_width);
+ Length min_length = style.LogicalMinWidth();
+ // TODO(cbiesinger): Audit callers of ResolveMainInlineLength to see
+ // whether they need to respect aspect ratio and consider adding a helper
+ // function for that.
+ LayoutUnit extent = kIndefiniteSize;
+ if (style.AspectRatio() && logical_width.IsAuto())
+ extent = ComputeInlineSizeFromAspectRatio(space, style, border_padding);
+ if (UNLIKELY(extent != kIndefiniteSize)) {
+ // This means we successfully applied aspect-ratio and now need to check
+ // if we need to apply the implied minimum size:
+ // https://drafts.csswg.org/css-sizing-4/#aspect-ratio-minimum
+ if (style.OverflowInlineDirection() == EOverflow::kVisible &&
+ min_length.IsAuto())
+ min_length = Length::MinContent();
+ } else {
+ if (logical_width.IsAuto() && space.IsShrinkToFit())
+ logical_width = Length::FitContent();
+ extent = ResolveMainInlineLength(space, style, border_padding,
+ MinMaxSizesFunc, logical_width);
+ }
LayoutUnit max = ResolveMaxInlineLength(
space, style, border_padding, MinMaxSizesFunc, style.LogicalMaxWidth(),
LengthResolvePhase::kLayout);
- LayoutUnit min = ResolveMinInlineLength(
- space, style, border_padding, MinMaxSizesFunc, style.LogicalMinWidth(),
- LengthResolvePhase::kLayout);
+ LayoutUnit min =
+ ResolveMinInlineLength(space, style, border_padding, MinMaxSizesFunc,
+ min_length, LengthResolvePhase::kLayout);
return ConstrainByMinMax(extent, min, max);
}
@@ -408,6 +465,7 @@ LayoutUnit ComputeBlockSizeForFragmentInternal(
const ComputedStyle& style,
const NGBoxStrut& border_padding,
LayoutUnit content_size,
+ base::Optional<LayoutUnit> inline_size,
const LayoutUnit* opt_percentage_resolution_block_size_for_min_max =
nullptr) {
LayoutUnit min = ResolveMinBlockLength(
@@ -433,11 +491,25 @@ LayoutUnit ComputeBlockSizeForFragmentInternal(
style.OverflowY() == EOverflow::kScroll))
return min;
+ // TODO(cbiesinger): Audit callers of ResolveMainBlockLength to see whether
+ // they need to respect aspect ratio.
LayoutUnit extent = ResolveMainBlockLength(
constraint_space, style, border_padding, logical_height, content_size,
LengthResolvePhase::kLayout,
opt_percentage_resolution_block_size_for_min_max);
- if (extent == kIndefiniteSize) {
+ if (UNLIKELY((extent == kIndefiniteSize || logical_height.IsAuto()) &&
+ style.LogicalAspectRatio() && inline_size &&
+ !style.LogicalWidth().IsAuto())) {
+ extent =
+ BlockSizeFromAspectRatio(border_padding, *style.LogicalAspectRatio(),
+ style.BoxSizing(), *inline_size);
+ // Apply the automatic minimum size for aspect ratio:
+ // https://drafts.csswg.org/css-sizing-4/#aspect-ratio-minimum
+ if (style.LogicalMinHeight().IsAuto() &&
+ style.OverflowBlockDirection() == EOverflow::kVisible &&
+ content_size != kIndefiniteSize)
+ min = content_size;
+ } else if (extent == kIndefiniteSize) {
DCHECK_EQ(content_size, kIndefiniteSize);
return extent;
}
@@ -456,7 +528,8 @@ LayoutUnit ComputeBlockSizeForFragment(
const NGConstraintSpace& constraint_space,
const ComputedStyle& style,
const NGBoxStrut& border_padding,
- LayoutUnit content_size) {
+ LayoutUnit content_size,
+ base::Optional<LayoutUnit> inline_size) {
// The final block-size of a table-cell is always its intrinsic size.
if (constraint_space.IsTableCell() && content_size != kIndefiniteSize)
return content_size;
@@ -467,8 +540,8 @@ LayoutUnit ComputeBlockSizeForFragment(
if (constraint_space.IsAnonymous())
return content_size;
- return ComputeBlockSizeForFragmentInternal(constraint_space, style,
- border_padding, content_size);
+ return ComputeBlockSizeForFragmentInternal(
+ constraint_space, style, border_padding, content_size, inline_size);
}
// Computes size for a replaced element.
@@ -539,9 +612,9 @@ void ComputeReplacedSize(const NGBlockNode& node,
intrinsic_block = LayoutUnit(150) + border_padding.BlockSum();
if (!intrinsic_inline) {
if (intrinsic_block) {
- intrinsic_inline = ((*intrinsic_block - border_padding.BlockSum()) *
- aspect_ratio.inline_size / aspect_ratio.block_size) +
- border_padding.InlineSum();
+ intrinsic_inline =
+ InlineSizeFromAspectRatio(border_padding, aspect_ratio,
+ EBoxSizing::kContentBox, *intrinsic_block);
} else if (!replaced_inline && !replaced_block) {
// No sizes available, return only the aspect ratio.
*out_aspect_ratio = aspect_ratio;
@@ -550,9 +623,9 @@ void ComputeReplacedSize(const NGBlockNode& node,
}
if (intrinsic_inline && !intrinsic_block) {
DCHECK(!aspect_ratio.IsEmpty());
- intrinsic_block = ((*intrinsic_inline - border_padding.InlineSum()) *
- aspect_ratio.block_size / aspect_ratio.inline_size) +
- border_padding.BlockSum();
+ intrinsic_block =
+ BlockSizeFromAspectRatio(border_padding, aspect_ratio,
+ EBoxSizing::kContentBox, *intrinsic_inline);
}
DCHECK(intrinsic_inline || intrinsic_block || replaced_inline ||
@@ -565,9 +638,8 @@ void ComputeReplacedSize(const NGBlockNode& node,
DCHECK_GE(default_block, border_padding.BlockSum());
return default_block;
}
- return ((*replaced_inline - border_padding.InlineSum()) *
- aspect_ratio.block_size / aspect_ratio.inline_size) +
- border_padding.BlockSum();
+ return BlockSizeFromAspectRatio(border_padding, aspect_ratio,
+ EBoxSizing::kContentBox, *replaced_inline);
};
auto ComputeInlineFromBlock = [&replaced_block, &aspect_ratio,
@@ -576,9 +648,8 @@ void ComputeReplacedSize(const NGBlockNode& node,
DCHECK_GE(default_inline, border_padding.InlineSum());
return default_inline;
}
- return ((*replaced_block - border_padding.BlockSum()) *
- aspect_ratio.inline_size / aspect_ratio.block_size) +
- border_padding.InlineSum();
+ return InlineSizeFromAspectRatio(border_padding, aspect_ratio,
+ EBoxSizing::kContentBox, *replaced_block);
};
if (replaced_inline) {
DCHECK(!replaced_block);
@@ -804,7 +875,6 @@ NGBoxStrut ComputeIntrinsicPadding(const NGConstraintSpace& constraint_space,
const ComputedStyle& style,
const NGBoxStrut& scrollbar) {
DCHECK(constraint_space.IsTableCell());
- DCHECK(!scrollbar.block_start);
// During the "layout" table phase, adjust the given intrinsic-padding to
// accommodate the scrollbar.
@@ -1005,10 +1075,12 @@ NGFragmentGeometry CalculateInitialFragmentGeometry(
LayoutUnit default_block_size = CalculateDefaultBlockSize(
constraint_space, node, border_scrollbar_padding);
+ LayoutUnit inline_size =
+ ComputeInlineSizeForFragment(constraint_space, node, border_padding);
LogicalSize border_box_size(
- ComputeInlineSizeForFragment(constraint_space, node, border_padding),
+ inline_size,
ComputeBlockSizeForFragment(constraint_space, style, border_padding,
- default_block_size));
+ default_block_size, inline_size));
if (UNLIKELY(border_box_size.inline_size <
border_scrollbar_padding.InlineSum() &&
@@ -1120,7 +1192,8 @@ LogicalSize CalculateReplacedChildPercentageSize(
const ComputedStyle& style = node.Style();
if (space.IsTableCell() && style.LogicalHeight().IsFixed()) {
LayoutUnit block_size = ComputeBlockSizeForFragmentInternal(
- space, style, border_padding, kIndefiniteSize /* content_size */);
+ space, style, border_padding, kIndefiniteSize /* content_size */,
+ base::nullopt /* inline_size */);
DCHECK_NE(block_size, kIndefiniteSize);
return {child_available_size.inline_size,
(block_size - border_scrollbar_padding.BlockSum())
@@ -1136,18 +1209,29 @@ LayoutUnit CalculateChildPercentageBlockSizeForMinMax(
const NGConstraintSpace& space,
const NGBlockNode node,
const NGBoxStrut& border_padding,
- LayoutUnit parent_percentage_block_size) {
+ LayoutUnit input_percentage_block_size,
+ bool* uses_input_percentage_block_size) {
+ *uses_input_percentage_block_size = false;
+
// Anonymous block or spaces should pass the percent size straight through.
// If this node is OOF-positioned, our size was pre-calculated and we should
// pass this through to our children.
if (space.IsAnonymous() || node.IsAnonymousBlock() ||
- node.IsOutOfFlowPositioned())
- return parent_percentage_block_size;
+ node.IsOutOfFlowPositioned()) {
+ *uses_input_percentage_block_size = true;
+ return input_percentage_block_size;
+ }
+ const ComputedStyle& style = node.Style();
LayoutUnit block_size = ComputeBlockSizeForFragmentInternal(
- space, node.Style(), border_padding,
- CalculateDefaultBlockSize(space, node, border_padding),
- &parent_percentage_block_size);
+ space, style, border_padding,
+ CalculateDefaultBlockSize(space, node, border_padding), base::nullopt,
+ &input_percentage_block_size);
+
+ if (style.LogicalMinHeight().IsPercentOrCalc() ||
+ style.LogicalHeight().IsPercentOrCalc() ||
+ style.LogicalMaxHeight().IsPercentOrCalc())
+ *uses_input_percentage_block_size = true;
LayoutUnit child_percentage_block_size =
block_size == kIndefiniteSize
@@ -1156,8 +1240,10 @@ LayoutUnit CalculateChildPercentageBlockSizeForMinMax(
// For OOF-positioned nodes, use the parent (containing-block) size.
if (child_percentage_block_size == kIndefiniteSize &&
- node.UseParentPercentageResolutionBlockSizeForChildren())
- child_percentage_block_size = parent_percentage_block_size;
+ node.UseParentPercentageResolutionBlockSizeForChildren()) {
+ *uses_input_percentage_block_size = true;
+ child_percentage_block_size = input_percentage_block_size;
+ }
return child_percentage_block_size;
}
@@ -1200,7 +1286,7 @@ LayoutUnit ClampIntrinsicBlockSize(
return current_intrinsic_block_size;
}
-base::Optional<MinMaxSizes> CalculateMinMaxSizesIgnoringChildren(
+base::Optional<MinMaxSizesResult> CalculateMinMaxSizesIgnoringChildren(
const NGBlockNode& node,
const NGBoxStrut& border_scrollbar_padding) {
MinMaxSizes sizes;
@@ -1211,19 +1297,23 @@ base::Optional<MinMaxSizes> CalculateMinMaxSizesIgnoringChildren(
node.OverrideIntrinsicContentInlineSize();
if (intrinsic_size_override != kIndefiniteSize) {
sizes += intrinsic_size_override;
- return sizes;
+ return MinMaxSizesResult{sizes,
+ /* depends_on_percentage_block_size */ false};
} else {
LayoutUnit default_inline_size = node.DefaultIntrinsicContentInlineSize();
if (default_inline_size != kIndefiniteSize) {
sizes += default_inline_size;
- return sizes;
+ return MinMaxSizesResult{sizes,
+ /* depends_on_percentage_block_size */ false};
}
}
// Size contained elements don't consider children for intrinsic sizing.
// Also, if we don't have children, we can determine the size immediately.
- if (node.ShouldApplySizeContainment() || !node.FirstChild())
- return sizes;
+ if (node.ShouldApplySizeContainment() || !node.FirstChild()) {
+ return MinMaxSizesResult{sizes,
+ /* depends_on_percentage_block_size */ false};
+ }
return base::nullopt;
}
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_length_utils.h b/chromium/third_party/blink/renderer/core/layout/ng/ng_length_utils.h
index 2a618216acc..ef8e775331d 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_length_utils.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_length_utils.h
@@ -41,14 +41,6 @@ inline bool NeedMinMaxSize(const ComputedStyle& style) {
style.LogicalMaxWidth().IsIntrinsic();
}
-// Like NeedMinMaxSize, but for use when calling
-// ComputeMinAndMaxContentContribution.
-// Because content contributions are commonly needed by a block's parent,
-// we also take a writing mode here so we can check this in the parent's
-// coordinate system.
-CORE_EXPORT bool NeedMinMaxSizeForContentContribution(WritingMode mode,
- const ComputedStyle&);
-
// Returns if the given |Length| is unresolvable, e.g. the length is %-based
// during the intrinsic phase. For block lengths we also consider 'auto',
// 'min-content', 'max-content', 'fit-content' and 'none' (for max-block-size)
@@ -83,7 +75,6 @@ CORE_EXPORT LayoutUnit ResolveBlockLengthInternal(
const NGBoxStrut& border_padding,
const Length&,
LayoutUnit content_size,
- LengthResolvePhase,
const LayoutUnit* opt_percentage_resolution_block_size_for_min_max =
nullptr);
@@ -101,7 +92,7 @@ inline LayoutUnit ResolveMinInlineLength(
base::Optional<MinMaxSizes> min_max_sizes;
if (length.IsIntrinsic())
- min_max_sizes = min_max_sizes_func();
+ min_max_sizes = min_max_sizes_func().sizes;
return ResolveInlineLengthInternal(constraint_space, style, border_padding,
min_max_sizes, length);
@@ -136,7 +127,7 @@ inline LayoutUnit ResolveMaxInlineLength(
base::Optional<MinMaxSizes> min_max_sizes;
if (length.IsIntrinsic())
- min_max_sizes = min_max_sizes_func();
+ min_max_sizes = min_max_sizes_func().sizes;
return ResolveInlineLengthInternal(constraint_space, style, border_padding,
min_max_sizes, length);
@@ -167,7 +158,7 @@ inline LayoutUnit ResolveMainInlineLength(
const Length& length) {
base::Optional<MinMaxSizes> min_max_sizes;
if (length.IsIntrinsic())
- min_max_sizes = min_max_sizes_func();
+ min_max_sizes = min_max_sizes_func().sizes;
return ResolveInlineLengthInternal(constraint_space, style, border_padding,
min_max_sizes, length);
@@ -199,7 +190,7 @@ inline LayoutUnit ResolveMinBlockLength(
return border_padding.BlockSum();
return ResolveBlockLengthInternal(
- constraint_space, style, border_padding, length, kIndefiniteSize, phase,
+ constraint_space, style, border_padding, length, kIndefiniteSize,
opt_percentage_resolution_block_size_for_min_max);
}
@@ -218,7 +209,7 @@ inline LayoutUnit ResolveMaxBlockLength(
return LayoutUnit::Max();
return ResolveBlockLengthInternal(
- constraint_space, style, border_padding, length, kIndefiniteSize, phase,
+ constraint_space, style, border_padding, length, kIndefiniteSize,
opt_percentage_resolution_block_size_for_min_max);
}
@@ -239,7 +230,7 @@ inline LayoutUnit ResolveMainBlockLength(
return content_size;
return ResolveBlockLengthInternal(
- constraint_space, style, border_padding, length, content_size, phase,
+ constraint_space, style, border_padding, length, content_size,
opt_percentage_resolution_block_size_for_min_max);
}
@@ -265,7 +256,7 @@ inline LayoutUnit ResolveMainBlockLength(
return ResolveBlockLengthInternal(
constraint_space, style, border_padding, length, intrinsic_block_size,
- phase, opt_percentage_resolution_block_size_for_min_max);
+ opt_percentage_resolution_block_size_for_min_max);
}
// For the given style and min/max content sizes, computes the min and max
@@ -279,10 +270,9 @@ inline LayoutUnit ResolveMainBlockLength(
// we also take a writing mode here so we can compute this in the parent's
// coordinate system.
CORE_EXPORT MinMaxSizes
-ComputeMinAndMaxContentContribution(WritingMode writing_mode,
- const ComputedStyle&,
- const NGBoxStrut& border_padding,
- const base::Optional<MinMaxSizes>&);
+ComputeMinAndMaxContentContributionForTest(WritingMode writing_mode,
+ const ComputedStyle&,
+ const MinMaxSizes&);
// A version of ComputeMinAndMaxContentContribution that does not require you
// to compute the min/max content size of the child. Instead, this function
@@ -292,11 +282,18 @@ ComputeMinAndMaxContentContribution(WritingMode writing_mode,
// parent, we'll still return the inline min/max contribution in the writing
// mode of the parent (i.e. typically something based on the preferred *block*
// size of the child).
-MinMaxSizes ComputeMinAndMaxContentContribution(
+MinMaxSizesResult ComputeMinAndMaxContentContribution(
const ComputedStyle& parent_style,
NGLayoutInputNode child,
const MinMaxSizesInput&);
+// Tries to compute the inline size of a node from its block size and
+// aspect ratio. If there is no aspect ratio or the block size is indefinite,
+// returns kIndefiniteSize.
+LayoutUnit ComputeInlineSizeFromAspectRatio(const NGConstraintSpace&,
+ const ComputedStyle&,
+ const NGBoxStrut& border_padding);
+
// Returns inline size of the node's border box by resolving the computed value
// in style.logicalWidth (Length) to a layout unit, adding border and padding,
// then constraining the result by the resolved min logical width and max
@@ -310,11 +307,14 @@ CORE_EXPORT LayoutUnit ComputeInlineSizeForFragment(
const MinMaxSizes* override_min_max_sizes_for_test = nullptr);
// Same as ComputeInlineSizeForFragment, but uses height instead of width.
+// |inline_size| is necessary to compute the block size when an aspect ratio
+// is in use.
CORE_EXPORT LayoutUnit
ComputeBlockSizeForFragment(const NGConstraintSpace&,
const ComputedStyle&,
const NGBoxStrut& border_padding,
- LayoutUnit content_size);
+ LayoutUnit content_size,
+ base::Optional<LayoutUnit> inline_size);
// Intrinsic size for replaced elements is computed as:
// - |out_replaced_size| intrinsic size of the element. It might have no value.
@@ -525,7 +525,8 @@ LayoutUnit CalculateChildPercentageBlockSizeForMinMax(
const NGConstraintSpace& constraint_space,
const NGBlockNode node,
const NGBoxStrut& border_padding,
- LayoutUnit parent_percentage_block_size);
+ LayoutUnit input_percentage_block_size,
+ bool* uses_input_percentage_block_size);
// The following function clamps the calculated size based on the node
// requirements. Specifically, this adjusts the size based on size containment
@@ -541,7 +542,7 @@ LayoutUnit ClampIntrinsicBlockSize(
// without considering children. If so, it returns the calculated size.
// Otherwise, it returns base::nullopt and the caller has to compute the size
// itself.
-base::Optional<MinMaxSizes> CalculateMinMaxSizesIgnoringChildren(
+base::Optional<MinMaxSizesResult> CalculateMinMaxSizesIgnoringChildren(
const NGBlockNode&,
const NGBoxStrut& border_scrollbar_padding);
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_length_utils_test.cc b/chromium/third_party/blink/renderer/core/layout/ng/ng_length_utils_test.cc
index f374f55a0cb..1c88961a155 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_length_utils_test.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_length_utils_test.cc
@@ -111,15 +111,16 @@ class NGLengthUtilsTestWithNode : public NGLayoutTest {
LayoutUnit ComputeBlockSizeForFragment(
NGConstraintSpace constraint_space = ConstructConstraintSpace(200, 300),
- LayoutUnit content_size = LayoutUnit()) {
+ LayoutUnit content_size = LayoutUnit(),
+ base::Optional<LayoutUnit> inline_size = base::nullopt) {
LayoutBox* body = ToLayoutBox(GetDocument().body()->GetLayoutObject());
body->SetStyle(style_);
body->SetIntrinsicLogicalWidthsDirty();
NGBoxStrut border_padding = ComputeBordersForTest(*style_) +
ComputePadding(constraint_space, *style_);
- return ::blink::ComputeBlockSizeForFragment(constraint_space, *style_,
- border_padding, content_size);
+ return ::blink::ComputeBlockSizeForFragment(
+ constraint_space, *style_, border_padding, content_size, inline_size);
}
scoped_refptr<ComputedStyle> style_;
@@ -172,107 +173,87 @@ TEST_F(NGLengthUtilsTest, testComputeContentContribution) {
sizes.min_size = LayoutUnit(30);
sizes.max_size = LayoutUnit(40);
- NGBoxStrut border_padding;
-
MinMaxSizes expected = sizes;
style_->SetLogicalWidth(Length::Percent(30));
- EXPECT_EQ(expected,
- ComputeMinAndMaxContentContribution(
- style_->GetWritingMode(), *style_, border_padding, sizes));
+ EXPECT_EQ(expected, ComputeMinAndMaxContentContributionForTest(
+ style_->GetWritingMode(), *style_, sizes));
style_->SetLogicalWidth(Length::FillAvailable());
- EXPECT_EQ(expected,
- ComputeMinAndMaxContentContribution(
- style_->GetWritingMode(), *style_, border_padding, sizes));
+ EXPECT_EQ(expected, ComputeMinAndMaxContentContributionForTest(
+ style_->GetWritingMode(), *style_, sizes));
expected = MinMaxSizes{LayoutUnit(150), LayoutUnit(150)};
style_->SetLogicalWidth(Length::Fixed(150));
- EXPECT_EQ(expected,
- ComputeMinAndMaxContentContribution(
- style_->GetWritingMode(), *style_, border_padding, sizes));
+ EXPECT_EQ(expected, ComputeMinAndMaxContentContributionForTest(
+ style_->GetWritingMode(), *style_, sizes));
expected = sizes;
style_->SetLogicalWidth(Length::Auto());
- EXPECT_EQ(expected,
- ComputeMinAndMaxContentContribution(
- style_->GetWritingMode(), *style_, border_padding, sizes));
+ EXPECT_EQ(expected, ComputeMinAndMaxContentContributionForTest(
+ style_->GetWritingMode(), *style_, sizes));
expected = MinMaxSizes{LayoutUnit(430), LayoutUnit(440)};
style_->SetPaddingLeft(Length::Fixed(400));
auto sizes_padding400 = sizes;
sizes_padding400 += LayoutUnit(400);
- NGBoxStrut border_padding400 = {LayoutUnit(400), LayoutUnit(), LayoutUnit(),
- LayoutUnit()};
- EXPECT_EQ(expected, ComputeMinAndMaxContentContribution(
- style_->GetWritingMode(), *style_, border_padding400,
- sizes_padding400));
+ EXPECT_EQ(expected, ComputeMinAndMaxContentContributionForTest(
+ style_->GetWritingMode(), *style_, sizes_padding400));
expected = MinMaxSizes{LayoutUnit(30), LayoutUnit(40)};
style_->SetPaddingLeft(Length::Fixed(0));
style_->SetLogicalWidth(Length(CalculationValue::Create(
PixelsAndPercent(100, -10), kValueRangeNonNegative)));
- EXPECT_EQ(expected,
- ComputeMinAndMaxContentContribution(
- style_->GetWritingMode(), *style_, border_padding, sizes));
+ EXPECT_EQ(expected, ComputeMinAndMaxContentContributionForTest(
+ style_->GetWritingMode(), *style_, sizes));
expected = MinMaxSizes{LayoutUnit(30), LayoutUnit(35)};
style_->SetLogicalWidth(Length::Auto());
style_->SetMaxWidth(Length::Fixed(35));
- EXPECT_EQ(expected,
- ComputeMinAndMaxContentContribution(
- style_->GetWritingMode(), *style_, border_padding, sizes));
+ EXPECT_EQ(expected, ComputeMinAndMaxContentContributionForTest(
+ style_->GetWritingMode(), *style_, sizes));
expected = MinMaxSizes{LayoutUnit(80), LayoutUnit(80)};
style_->SetLogicalWidth(Length::Fixed(50));
style_->SetMinWidth(Length::Fixed(80));
- EXPECT_EQ(expected,
- ComputeMinAndMaxContentContribution(
- style_->GetWritingMode(), *style_, border_padding, sizes));
+ EXPECT_EQ(expected, ComputeMinAndMaxContentContributionForTest(
+ style_->GetWritingMode(), *style_, sizes));
expected = MinMaxSizes{LayoutUnit(150), LayoutUnit(150)};
style_ = ComputedStyle::Create();
style_->SetLogicalWidth(Length::Fixed(100));
style_->SetPaddingLeft(Length::Fixed(50));
auto sizes_padding50 = sizes;
- NGBoxStrut border_padding50 = {LayoutUnit(50), LayoutUnit(), LayoutUnit(),
- LayoutUnit()};
sizes_padding50 += LayoutUnit(50);
- EXPECT_EQ(expected, ComputeMinAndMaxContentContribution(
- style_->GetWritingMode(), *style_, border_padding50,
- sizes_padding50));
+ EXPECT_EQ(expected, ComputeMinAndMaxContentContributionForTest(
+ style_->GetWritingMode(), *style_, sizes_padding50));
expected = MinMaxSizes{LayoutUnit(100), LayoutUnit(100)};
style_->SetBoxSizing(EBoxSizing::kBorderBox);
- EXPECT_EQ(expected, ComputeMinAndMaxContentContribution(
- style_->GetWritingMode(), *style_, border_padding50,
- sizes_padding50));
+ EXPECT_EQ(expected, ComputeMinAndMaxContentContributionForTest(
+ style_->GetWritingMode(), *style_, sizes_padding50));
// Content size should never be below zero, even with box-sizing: border-box
// and a large padding...
expected = MinMaxSizes{LayoutUnit(400), LayoutUnit(400)};
style_->SetPaddingLeft(Length::Fixed(400));
- EXPECT_EQ(expected, ComputeMinAndMaxContentContribution(
- style_->GetWritingMode(), *style_, border_padding400,
- sizes_padding400));
+ EXPECT_EQ(expected, ComputeMinAndMaxContentContributionForTest(
+ style_->GetWritingMode(), *style_, sizes_padding400));
expected.min_size = expected.max_size = sizes.min_size + LayoutUnit(400);
style_->SetLogicalWidth(Length::MinContent());
- EXPECT_EQ(expected, ComputeMinAndMaxContentContribution(
- style_->GetWritingMode(), *style_, border_padding400,
- sizes_padding400));
+ EXPECT_EQ(expected, ComputeMinAndMaxContentContributionForTest(
+ style_->GetWritingMode(), *style_, sizes_padding400));
style_->SetLogicalWidth(Length::Fixed(100));
style_->SetMaxWidth(Length::MaxContent());
// Due to padding and box-sizing, width computes to 400px and max-width to
// 440px, so the result is 400.
expected = MinMaxSizes{LayoutUnit(400), LayoutUnit(400)};
- EXPECT_EQ(expected, ComputeMinAndMaxContentContribution(
- style_->GetWritingMode(), *style_, border_padding400,
- sizes_padding400));
+ EXPECT_EQ(expected, ComputeMinAndMaxContentContributionForTest(
+ style_->GetWritingMode(), *style_, sizes_padding400));
expected = MinMaxSizes{LayoutUnit(40), LayoutUnit(40)};
style_->SetPaddingLeft(Length::Fixed(0));
- EXPECT_EQ(expected,
- ComputeMinAndMaxContentContribution(
- style_->GetWritingMode(), *style_, border_padding, sizes));
+ EXPECT_EQ(expected, ComputeMinAndMaxContentContributionForTest(
+ style_->GetWritingMode(), *style_, sizes));
}
TEST_F(NGLengthUtilsTestWithNode, testComputeInlineSizeForFragment) {
@@ -401,6 +382,27 @@ TEST_F(NGLengthUtilsTestWithNode, testComputeBlockSizeForFragment) {
style_->SetLogicalHeight(Length::FillAvailable());
EXPECT_EQ(LayoutUnit(400), ComputeBlockSizeForFragment());
+ // Now check aspect-ratio.
+ style_ = ComputedStyle::Create();
+ style_->SetLogicalWidth(Length::Fixed(100));
+ style_->SetAspectRatio(IntSize(2, 1));
+ EXPECT_EQ(LayoutUnit(50),
+ ComputeBlockSizeForFragment(ConstructConstraintSpace(200, 300),
+ LayoutUnit(), LayoutUnit(100)));
+
+ // Default box-sizing
+ style_->SetPaddingRight(Length::Fixed(10));
+ style_->SetPaddingBottom(Length::Fixed(20));
+ // Should be (100 - 10) / 2 + 20 = 65.
+ EXPECT_EQ(LayoutUnit(65),
+ ComputeBlockSizeForFragment(ConstructConstraintSpace(200, 300),
+ LayoutUnit(20), LayoutUnit(100)));
+ // With box-sizing: border-box, should be 50.
+ style_->SetBoxSizing(EBoxSizing::kBorderBox);
+ EXPECT_EQ(LayoutUnit(50),
+ ComputeBlockSizeForFragment(ConstructConstraintSpace(200, 300),
+ LayoutUnit(20), LayoutUnit(100)));
+
// TODO(layout-ng): test {min,max}-content on max-height.
}
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.cc b/chromium/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.cc
index 0df01829351..4020a8fd3b7 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.cc
@@ -35,15 +35,14 @@ bool IsAnonymousContainer(const LayoutObject* layout_object) {
// This saves the static-position for an OOF-positioned object into its
// paint-layer.
-void SaveStaticPositionForLegacy(const LayoutBox* layout_box,
- const LayoutObject* container,
- const LogicalOffset& offset) {
+void SaveStaticPositionOnPaintLayer(const LayoutBox* layout_box,
+ const LayoutObject* container,
+ const NGLogicalStaticPosition& position) {
const LayoutObject* parent = layout_box->Parent();
if (parent == container ||
(parent->IsLayoutInline() && parent->ContainingBlock() == container)) {
DCHECK(layout_box->Layer());
- layout_box->Layer()->SetStaticInlinePosition(offset.inline_offset);
- layout_box->Layer()->SetStaticBlockPosition(offset.block_offset);
+ layout_box->Layer()->SetStaticPositionFromNG(position);
}
}
@@ -429,6 +428,9 @@ void NGOutOfFlowLayoutPart::LayoutCandidates(
ComputeInlineContainingBlocks(*candidates);
for (auto& candidate : *candidates) {
const LayoutBox* layout_box = candidate.node.GetLayoutBox();
+ SaveStaticPositionOnPaintLayer(layout_box,
+ container_builder_->GetLayoutObject(),
+ candidate.static_position);
if (IsContainingBlockForCandidate(candidate) &&
(!only_layout || layout_box == only_layout)) {
scoped_refptr<const NGLayoutResult> result =
@@ -440,9 +442,6 @@ void NGOutOfFlowLayoutPart::LayoutCandidates(
if (layout_box != only_layout)
candidate.node.UseLegacyOutOfFlowPositioning();
} else {
- SaveStaticPositionForLegacy(layout_box,
- container_builder_->GetLayoutObject(),
- candidate.static_position.offset);
container_builder_->AddOutOfFlowDescendant(candidate);
}
}
@@ -605,7 +604,8 @@ scoped_refptr<const NGLayoutResult> NGOutOfFlowLayoutPart::Layout(
}
min_max_sizes = node.ComputeMinMaxSizes(candidate_writing_mode, input,
- &candidate_constraint_space);
+ &candidate_constraint_space)
+ .sizes;
}
base::Optional<LogicalSize> replaced_size;
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_page_layout_algorithm.cc b/chromium/third_party/blink/renderer/core/layout/ng/ng_page_layout_algorithm.cc
index 5328304e619..27aa6125ce8 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_page_layout_algorithm.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_page_layout_algorithm.cc
@@ -66,7 +66,8 @@ scoped_refptr<const NGLayoutResult> NGPageLayoutAlgorithm::Layout() {
// Recompute the block-axis size now that we know our content size.
border_box_size.block_size = ComputeBlockSizeForFragment(
- ConstraintSpace(), Style(), border_padding_, intrinsic_block_size);
+ ConstraintSpace(), Style(), border_padding_, intrinsic_block_size,
+ border_box_size.inline_size);
container_builder_.SetBlockSize(border_box_size.block_size);
NGOutOfFlowLayoutPart(
@@ -80,7 +81,7 @@ scoped_refptr<const NGLayoutResult> NGPageLayoutAlgorithm::Layout() {
return container_builder_.ToBoxFragment();
}
-base::Optional<MinMaxSizes> NGPageLayoutAlgorithm::ComputeMinMaxSizes(
+MinMaxSizesResult NGPageLayoutAlgorithm::ComputeMinMaxSizes(
const MinMaxSizesInput& input) const {
NGFragmentGeometry fragment_geometry =
CalculateInitialMinMaxFragmentGeometry(ConstraintSpace(), Node());
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_page_layout_algorithm.h b/chromium/third_party/blink/renderer/core/layout/ng/ng_page_layout_algorithm.h
index 8797b3ba1ac..4b9ebf55713 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_page_layout_algorithm.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_page_layout_algorithm.h
@@ -25,8 +25,7 @@ class CORE_EXPORT NGPageLayoutAlgorithm
scoped_refptr<const NGLayoutResult> Layout() override;
- base::Optional<MinMaxSizes> ComputeMinMaxSizes(
- const MinMaxSizesInput&) const override;
+ MinMaxSizesResult ComputeMinMaxSizes(const MinMaxSizesInput&) const override;
private:
NGConstraintSpace CreateConstraintSpaceForPages(
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.cc b/chromium/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.cc
index 2092c9bbe84..fd78b87d9c6 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.cc
@@ -56,8 +56,11 @@ scoped_refptr<const NGPhysicalBoxFragment> NGPhysicalBoxFragment::Create(
sizeof(NGLink) * builder->children_.size() +
(borders.IsZero() ? 0 : sizeof(borders)) +
(padding.IsZero() ? 0 : sizeof(padding));
- if (builder->ItemsBuilder())
- byte_size += sizeof(NGFragmentItems);
+ if (const NGFragmentItemsBuilder* items_builder = builder->ItemsBuilder()) {
+ // Omit |NGFragmentItems| if there were no items; e.g., display-lock.
+ if (items_builder->Size())
+ byte_size += NGFragmentItems::ByteSizeFor(items_builder->Size());
+ }
// We store the children list inline in the fragment as a flexible
// array. Therefore, we need to make sure to allocate enough space for
// that array here, which requires a manual allocation + placement new.
@@ -83,15 +86,19 @@ NGPhysicalBoxFragment::NGPhysicalBoxFragment(
builder->BoxType()) {
DCHECK(layout_object_);
DCHECK(layout_object_->IsBoxModelObject());
+
+ has_fragment_items_ = false;
if (NGFragmentItemsBuilder* items_builder = builder->ItemsBuilder()) {
- has_fragment_items_ = true;
- NGFragmentItems* items =
- const_cast<NGFragmentItems*>(ComputeItemsAddress());
- items_builder->ToFragmentItems(block_or_line_writing_mode,
- builder->Direction(), Size(), items);
- } else {
- has_fragment_items_ = false;
+ // Omit |NGFragmentItems| if there were no items; e.g., display-lock.
+ if (items_builder->Size()) {
+ has_fragment_items_ = true;
+ NGFragmentItems* items =
+ const_cast<NGFragmentItems*>(ComputeItemsAddress());
+ items_builder->ToFragmentItems(block_or_line_writing_mode,
+ builder->Direction(), Size(), items);
+ }
}
+
has_borders_ = !borders.IsZero();
if (has_borders_)
*const_cast<NGPhysicalBoxStrut*>(ComputeBordersAddress()) = borders;
@@ -105,7 +112,7 @@ NGPhysicalBoxFragment::NGPhysicalBoxFragment(
builder->space_ && builder->space_->IsPaintedAtomically();
border_edge_ = builder->border_edges_.ToPhysical(builder->GetWritingMode());
is_inline_formatting_context_ = builder->is_inline_formatting_context_;
- is_generated_text_or_math_fraction_ = builder->is_math_fraction_;
+ is_math_fraction_ = builder->is_math_fraction_;
bool has_layout_containment = layout_object_->ShouldApplyLayoutContainment();
if (builder->baseline_.has_value() && !has_layout_containment) {
@@ -302,7 +309,8 @@ PhysicalRect NGPhysicalBoxFragment::ScrollableOverflowFromChildren() const {
// Traverse child items.
if (items) {
- for (NGInlineCursor cursor(*items); cursor; cursor.MoveToNextSibling()) {
+ for (NGInlineCursor cursor(*items); cursor;
+ cursor.MoveToNextSkippingChildren()) {
const NGFragmentItem* item = cursor.CurrentItem();
if (item->Type() == NGFragmentItem::kLine) {
context.AddLineBoxChild(*item, cursor);
@@ -480,6 +488,7 @@ void NGPhysicalBoxFragment::CheckSameForSimplifiedLayout(
DCHECK_EQ(type_, other.type_);
DCHECK_EQ(sub_type_, other.sub_type_);
DCHECK_EQ(style_variant_, other.style_variant_);
+ DCHECK_EQ(is_hidden_for_paint_, other.is_hidden_for_paint_);
// |has_floating_descendants_for_paint_| can change during simplified layout.
DCHECK_EQ(has_orthogonal_flow_roots_, other.has_orthogonal_flow_roots_);
@@ -489,10 +498,13 @@ void NGPhysicalBoxFragment::CheckSameForSimplifiedLayout(
other.depends_on_percentage_block_size_);
DCHECK_EQ(is_inline_formatting_context_, other.is_inline_formatting_context_);
+ DCHECK_EQ(has_fragment_items_, other.has_fragment_items_);
+ DCHECK_EQ(border_edge_, other.border_edge_);
+ DCHECK_EQ(is_math_fraction_, other.is_math_fraction_);
+
DCHECK_EQ(is_fieldset_container_, other.is_fieldset_container_);
DCHECK_EQ(is_legacy_layout_root_, other.is_legacy_layout_root_);
DCHECK_EQ(is_painted_atomically_, other.is_painted_atomically_);
- DCHECK_EQ(border_edge_, other.border_edge_);
// The oof_positioned_descendants_ vector can change during "simplified"
// layout. This occurs when an OOF-descendant changes from "fixed" to
@@ -501,7 +513,13 @@ void NGPhysicalBoxFragment::CheckSameForSimplifiedLayout(
// Legacy layout can (incorrectly) shift baseline position(s) during
// "simplified" layout.
DCHECK(IsLegacyLayoutRoot() || Baseline() == other.Baseline());
- DCHECK(IsLegacyLayoutRoot() || LastBaseline() == other.LastBaseline());
+ if (check_same_block_size) {
+ DCHECK(IsLegacyLayoutRoot() || LastBaseline() == other.LastBaseline());
+ } else {
+ DCHECK(IsLegacyLayoutRoot() || LastBaseline() == other.LastBaseline() ||
+ NGBlockNode(ToLayoutBox(GetMutableLayoutObject()))
+ .UseBlockEndMarginEdgeForInlineBlockBaseline());
+ }
DCHECK(Borders() == other.Borders());
DCHECK(Padding() == other.Padding());
}
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h b/chromium/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h
index 21527728c01..8b034f8a7db 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h
@@ -144,6 +144,9 @@ class CORE_EXPORT NGPhysicalBoxFragment final
unsigned BorderEdges() const { return border_edge_; }
NGPixelSnappedPhysicalBoxStrut BorderWidths() const;
+ // Return true if this is the first fragment generated from a node.
+ bool IsFirstForNode() const { return is_first_for_node_; }
+
#if DCHECK_IS_ON()
void CheckSameForSimplifiedLayout(const NGPhysicalBoxFragment&,
bool check_same_block_size) const;
@@ -159,9 +162,10 @@ class CORE_EXPORT NGPhysicalBoxFragment final
const NGPhysicalBoxStrut* ComputeBordersAddress() const {
DCHECK(has_borders_ || has_padding_);
const NGFragmentItems* items = ComputeItemsAddress();
- if (has_fragment_items_)
- ++items;
- return reinterpret_cast<const NGPhysicalBoxStrut*>(items);
+ if (!has_fragment_items_)
+ return reinterpret_cast<const NGPhysicalBoxStrut*>(items);
+ return reinterpret_cast<const NGPhysicalBoxStrut*>(
+ reinterpret_cast<const uint8_t*>(items) + items->ByteSize());
}
const NGPhysicalBoxStrut* ComputePaddingAddress() const {
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_physical_container_fragment.cc b/chromium/third_party/blink/renderer/core/layout/ng/ng_physical_container_fragment.cc
index 82f57612ce4..929f8b346b1 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_physical_container_fragment.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_physical_container_fragment.cc
@@ -73,11 +73,18 @@ NGPhysicalContainerFragment::NGPhysicalContainerFragment(
// storage be part of the subclass.
wtf_size_t i = 0;
for (auto& child : builder->children_) {
- buffer[i].fragment = child.fragment.get();
- buffer[i].fragment->AddRef();
buffer[i].offset = child.offset.ConvertToPhysical(
block_or_line_writing_mode, builder->Direction(), size,
child.fragment->Size());
+ // Call the move constructor to move without |AddRef|. Fragments in
+ // |builder| are not used after |this| was constructed.
+ static_assert(
+ sizeof(buffer[0].fragment) ==
+ sizeof(scoped_refptr<const NGPhysicalFragment>),
+ "scoped_refptr must be the size of a pointer for this to work");
+ new (&buffer[i].fragment)
+ scoped_refptr<const NGPhysicalFragment>(std::move(child.fragment));
+ DCHECK(!child.fragment); // Ensure it was moved.
++i;
}
}
@@ -275,8 +282,10 @@ void NGPhysicalContainerFragment::AddOutlineRectsForDescendant(
// the LayoutInline needs to add rects for children and continuations
// only.
if (NGOutlineUtils::ShouldPaintOutline(*descendant_box)) {
+ // We don't pass additional_offset here because the function requires
+ // additional_offset to be the offset from the containing block.
descendant_layout_inline->AddOutlineRectsForChildrenAndContinuations(
- *outline_rects, additional_offset, outline_type);
+ *outline_rects, PhysicalOffset(), outline_type);
}
return;
}
@@ -288,7 +297,7 @@ void NGPhysicalContainerFragment::AddOutlineRectsForDescendant(
containing_block);
if (!descendant_line_box->Size().IsEmpty()) {
- outline_rects->emplace_back(additional_offset,
+ outline_rects->emplace_back(additional_offset + descendant.Offset(),
descendant_line_box->Size().ToLayoutSize());
} else if (descendant_line_box->Children().empty()) {
// Special-case for when the first continuation does not generate
@@ -315,6 +324,13 @@ bool NGPhysicalContainerFragment::DependsOnPercentageBlockSize(
if (!node || node.IsInline())
return builder.has_descendant_that_depends_on_percentage_block_size_;
+ // For the below if-stmt we only want to consider legacy *containers* as
+ // potentially having %-dependent children - i.e. an image doesn't have any
+ // children.
+ bool is_legacy_container_with_percent_height_descendants =
+ builder.is_legacy_layout_root_ && !node.IsReplaced() &&
+ node.GetLayoutBox()->MaybeHasPercentHeightDescendant();
+
// NOTE: If an element is OOF positioned, and has top/bottom constraints
// which are percentage based, this function will return false.
//
@@ -339,7 +355,7 @@ bool NGPhysicalContainerFragment::DependsOnPercentageBlockSize(
// We only need to know about if this flex-item has a %-block-size child if
// the "definiteness" changes, not if the percentage resolution size changes.
if ((builder.has_descendant_that_depends_on_percentage_block_size_ ||
- builder.is_legacy_layout_root_) &&
+ is_legacy_container_with_percent_height_descendants) &&
(node.UseParentPercentageResolutionBlockSizeForChildren() ||
node.IsFlexItem()))
return true;
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_physical_container_fragment.h b/chromium/third_party/blink/renderer/core/layout/ng/ng_physical_container_fragment.h
index b3c7624f494..f025de6caf1 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_physical_container_fragment.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_physical_container_fragment.h
@@ -5,6 +5,8 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_PHYSICAL_CONTAINER_FRAGMENT_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_PHYSICAL_CONTAINER_FRAGMENT_H_
+#include <iterator>
+
#include "base/containers/span.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/layout/geometry/physical_rect.h"
@@ -31,10 +33,17 @@ class CORE_EXPORT NGPhysicalContainerFragment : public NGPhysicalFragment {
PostLayoutChildLinkList(wtf_size_t count, const NGLink* buffer)
: count_(count), buffer_(buffer) {}
- class ConstIterator {
+ class ConstIterator
+ : public std::iterator<std::input_iterator_tag, NGLink> {
STACK_ALLOCATED();
public:
+ using iterator_category = std::bidirectional_iterator_tag;
+ using value_type = NGLink;
+ using difference_type = ptrdiff_t;
+ using pointer = value_type*;
+ using reference = value_type&;
+
ConstIterator(const NGLink* current) : current_(current) {}
const NGLink& operator*() const { return *PostLayoutOrCurrent(); }
@@ -114,6 +123,7 @@ class CORE_EXPORT NGPhysicalContainerFragment : public NGPhysicalFragment {
return has_adjoining_object_descendants_;
}
+ // TODO(ikilpatrick): Remove this flag as its not used anymore.
bool HasOrthogonalFlowRoots() const { return has_orthogonal_flow_roots_; }
// Returns true if we have a descendant within this formatting context, which
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_physical_fragment.cc b/chromium/third_party/blink/renderer/core/layout/ng/ng_physical_fragment.cc
index d5f70584bc9..4d3daa543ce 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_physical_fragment.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_physical_fragment.cc
@@ -219,7 +219,6 @@ NGPhysicalFragment::NGPhysicalFragment(NGFragmentBuilder* builder,
sub_type_(sub_type),
style_variant_((unsigned)builder->style_variant_),
is_hidden_for_paint_(builder->is_hidden_for_paint_),
- is_first_for_node_(true),
has_floating_descendants_for_paint_(false),
is_fieldset_container_(false),
is_legacy_layout_root_(false),
@@ -306,15 +305,13 @@ bool NGPhysicalFragment::IsPlacedByLayoutNG() const {
const FragmentData* NGPhysicalFragment::GetFragmentData() const {
DCHECK(CanTraverse());
- const LayoutObject* layout_object = GetLayoutObject();
- if (!layout_object)
+ const LayoutBox* box = ToLayoutBoxOrNull(GetLayoutObject());
+ if (!box) {
+ DCHECK(!GetLayoutObject());
return nullptr;
- // TODO(mstensho): Actually return the correct FragmentData. For now this
- // method only behaves if there's just one FragmentData associated with the
- // LayoutObject.
- const FragmentData& first_fragment_data = layout_object->FirstFragment();
- DCHECK(!first_fragment_data.NextFragment());
- return &first_fragment_data;
+ }
+ return box->FragmentDataFromPhysicalFragment(
+ To<NGPhysicalBoxFragment>(*this));
}
const NGPhysicalFragment* NGPhysicalFragment::PostLayout() const {
@@ -461,8 +458,8 @@ const Vector<NGInlineItem>& NGPhysicalFragment::InlineItemsOfContainingBlock()
}
TouchAction NGPhysicalFragment::EffectiveAllowedTouchAction() const {
- DCHECK(GetLayoutObject());
- return GetLayoutObject()->EffectiveAllowedTouchAction();
+ DCHECK(layout_object_);
+ return layout_object_->EffectiveAllowedTouchAction();
}
UBiDiLevel NGPhysicalFragment::BidiLevel() const {
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_physical_fragment.h b/chromium/third_party/blink/renderer/core/layout/ng/ng_physical_fragment.h
index 2fcd7049c96..4cebbebf948 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_physical_fragment.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_physical_fragment.h
@@ -121,9 +121,7 @@ class CORE_EXPORT NGPhysicalFragment
bool IsRenderedLegend() const {
return IsBox() && BoxType() == NGBoxType::kRenderedLegend;
}
- bool IsMathMLFraction() const {
- return IsBox() && is_generated_text_or_math_fraction_;
- }
+ bool IsMathMLFraction() const { return IsBox() && is_math_fraction_; }
// Return true if this fragment corresponds directly to an entry in the CSS
// box tree [1]. Note that anonymous blocks also exist in the CSS box
@@ -168,9 +166,6 @@ class CORE_EXPORT NGPhysicalFragment
// |LayoutNGBlockFlow::UpdateBlockLayout()| and crbug.com/788590
bool IsPlacedByLayoutNG() const;
- // Return true if this is the first fragment generated from a node.
- bool IsFirstForNode() const { return is_first_for_node_; }
-
// The accessors in this class shouldn't be used by layout code directly,
// instead should be accessed by the NGFragmentBase classes. These accessors
// exist for paint, hit-testing, etc.
@@ -244,7 +239,15 @@ class CORE_EXPORT NGPhysicalFragment
}
bool IsFragmentationContextRoot() const {
- return !IsColumnBox() && IsBlockFlow() && Style().SpecifiesColumns();
+ // We have no bit that tells us whether this is a fragmentation context
+ // root, so some additional checking is necessary here, to make sure that
+ // we're actually establishing one. We check that we're not a custom layout
+ // box, as specifying columns on such a box has no effect. Note that
+ // specifying columns together with a display value of e.g. 'flex', 'grid'
+ // or 'table' also has no effect, but we don't need to check for that here,
+ // since such display types don't create a block flow (block container).
+ return IsCSSBox() && Style().SpecifiesColumns() && IsBlockFlow() &&
+ !layout_object_->IsLayoutNGCustom();
}
// Return whether we can traverse this fragment and its children directly, for
@@ -282,6 +285,11 @@ class CORE_EXPORT NGPhysicalFragment
LayoutObject* GetMutableLayoutObject() const {
return IsCSSBox() ? layout_object_ : nullptr;
}
+ // Similar to |GetLayoutObject|, but returns the |LayoutObject| of its
+ // container for |!IsCSSBox()| fragments instead of |nullptr|.
+ const LayoutObject* GetSelfOrContainerLayoutObject() const {
+ return layout_object_;
+ }
const FragmentData* GetFragmentData() const;
@@ -385,7 +393,6 @@ class CORE_EXPORT NGPhysicalFragment
const unsigned sub_type_ : 3; // NGBoxType, NGTextType, or NGLineBoxType
const unsigned style_variant_ : 2; // NGStyleVariant
const unsigned is_hidden_for_paint_ : 1;
- unsigned is_first_for_node_ : 1;
// The following bitfields are only to be used by NGPhysicalContainerFragment
// (it's defined here to save memory, since that class has no bitfields).
@@ -409,6 +416,8 @@ class CORE_EXPORT NGPhysicalFragment
unsigned border_edge_ : 4; // NGBorderEdges::Physical
unsigned has_borders_ : 1;
unsigned has_padding_ : 1;
+ unsigned is_math_fraction_ : 1;
+ unsigned is_first_for_node_ : 1;
// The following are only used by NGPhysicalBoxFragment but are initialized
// for all types to allow methods using them to be inlined.
@@ -418,10 +427,6 @@ class CORE_EXPORT NGPhysicalFragment
unsigned has_baseline_ : 1;
unsigned has_last_baseline_ : 1;
- // The following bitfield is shared between NGPhysicalTextFragment and
- // NGPhysicalBoxFragment.
- unsigned is_generated_text_or_math_fraction_ : 1;
-
// The following bitfields are only to be used by NGPhysicalTextFragment
// (it's defined here to save memory, since that class has no bitfields).
mutable unsigned ink_overflow_computed_ : 1;
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_simplified_layout_algorithm.cc b/chromium/third_party/blink/renderer/core/layout/ng/ng_simplified_layout_algorithm.cc
index a2bec293a78..58f9ccbd1c8 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_simplified_layout_algorithm.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_simplified_layout_algorithm.cc
@@ -15,6 +15,7 @@
#include "third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.h"
#include "third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h"
#include "third_party/blink/renderer/core/layout/ng/ng_space_utils.h"
+#include "third_party/blink/renderer/core/paint/paint_layer.h"
namespace blink {
@@ -23,74 +24,113 @@ NGSimplifiedLayoutAlgorithm::NGSimplifiedLayoutAlgorithm(
const NGLayoutResult& result)
: NGLayoutAlgorithm(params),
previous_result_(result),
- border_scrollbar_padding_(params.fragment_geometry.border +
- params.fragment_geometry.scrollbar +
- params.fragment_geometry.padding),
writing_mode_(Style().GetWritingMode()),
- direction_(Style().Direction()),
- exclusion_space_(ConstraintSpace().ExclusionSpace()) {
+ direction_(Style().Direction()) {
// Currently this only supports block-flow layout due to the static-position
// calculations. If support for other layout types is added this logic will
// need to be changed.
- DCHECK(Node().IsBlockFlow());
+ bool is_block_flow = Node().IsBlockFlow();
const NGPhysicalBoxFragment& physical_fragment =
To<NGPhysicalBoxFragment>(result.PhysicalFragment());
- container_builder_.SetIsInlineFormattingContext(
- Node().IsInlineFormattingContextRoot());
- container_builder_.SetStyleVariant(physical_fragment.StyleVariant());
+ container_builder_.SetInitialFragmentGeometry(params.fragment_geometry);
container_builder_.SetIsNewFormattingContext(
physical_fragment.IsFormattingContextRoot());
- container_builder_.SetInitialFragmentGeometry(params.fragment_geometry);
- NGExclusionSpace exclusion_space = result.ExclusionSpace();
- container_builder_.SetExclusionSpace(std::move(exclusion_space));
+ if (is_block_flow) {
+ container_builder_.SetIsInlineFormattingContext(
+ Node().IsInlineFormattingContextRoot());
+ container_builder_.SetStyleVariant(physical_fragment.StyleVariant());
+
+ if (result.SubtreeModifiedMarginStrut())
+ container_builder_.SetSubtreeModifiedMarginStrut();
+ container_builder_.SetEndMarginStrut(result.EndMarginStrut());
+
+ // Ensure that the parent layout hasn't asked us to move our BFC position.
+ DCHECK_EQ(ConstraintSpace().BfcOffset(),
+ previous_result_.GetConstraintSpaceForCaching().BfcOffset());
+ container_builder_.SetBfcLineOffset(result.BfcLineOffset());
+ if (result.BfcBlockOffset())
+ container_builder_.SetBfcBlockOffset(*result.BfcBlockOffset());
+
+ if (result.LinesUntilClamp())
+ container_builder_.SetLinesUntilClamp(result.LinesUntilClamp());
+
+ NGExclusionSpace exclusion_space = result.ExclusionSpace();
+ container_builder_.SetExclusionSpace(std::move(exclusion_space));
+
+ if (result.IsSelfCollapsing())
+ container_builder_.SetIsSelfCollapsing();
+ if (result.IsPushedByFloats())
+ container_builder_.SetIsPushedByFloats();
+ container_builder_.SetAdjoiningObjectTypes(result.AdjoiningObjectTypes());
+ container_builder_.SetUnpositionedListMarker(
+ result.UnpositionedListMarker());
+
+ if (physical_fragment.LastBaseline())
+ container_builder_.SetLastBaseline(*physical_fragment.LastBaseline());
+ } else {
+ // Only block-flow layout sets the following fields.
+ DCHECK(physical_fragment.IsFormattingContextRoot());
+ DCHECK(!Node().IsInlineFormattingContextRoot());
+ DCHECK_EQ(physical_fragment.StyleVariant(), NGStyleVariant::kStandard);
+
+ DCHECK(!result.SubtreeModifiedMarginStrut());
+ DCHECK(result.EndMarginStrut().IsEmpty());
- // Ensure that the parent layout hasn't asked us to move our BFC position.
- DCHECK_EQ(ConstraintSpace().BfcOffset(),
- previous_result_.GetConstraintSpaceForCaching().BfcOffset());
+ DCHECK_EQ(ConstraintSpace().BfcOffset(), NGBfcOffset());
+ DCHECK_EQ(result.BfcLineOffset(), LayoutUnit());
+ DCHECK_EQ(result.BfcBlockOffset().value_or(LayoutUnit()), LayoutUnit());
- if (result.SubtreeModifiedMarginStrut())
- container_builder_.SetSubtreeModifiedMarginStrut();
+ DCHECK(!result.LinesUntilClamp());
- container_builder_.SetBfcLineOffset(result.BfcLineOffset());
- if (result.BfcBlockOffset())
- container_builder_.SetBfcBlockOffset(*result.BfcBlockOffset());
+ DCHECK(result.ExclusionSpace().IsEmpty());
- container_builder_.SetEndMarginStrut(result.EndMarginStrut());
- container_builder_.SetIntrinsicBlockSize(result.IntrinsicBlockSize());
- container_builder_.SetUnpositionedListMarker(result.UnpositionedListMarker());
+ DCHECK(!result.IsSelfCollapsing());
+ DCHECK(!result.IsPushedByFloats());
+ DCHECK_EQ(result.AdjoiningObjectTypes(), kAdjoiningNone);
+ DCHECK(!result.UnpositionedListMarker());
+
+ DCHECK(!physical_fragment.LastBaseline());
- if (result.IsSelfCollapsing())
- container_builder_.SetIsSelfCollapsing();
- if (result.IsPushedByFloats())
- container_builder_.SetIsPushedByFloats();
- container_builder_.SetAdjoiningObjectTypes(result.AdjoiningObjectTypes());
+ if (physical_fragment.IsFieldsetContainer())
+ container_builder_.SetIsFieldsetContainer();
+
+ if (physical_fragment.IsMathMLFraction())
+ container_builder_.SetIsMathMLFraction();
+
+ container_builder_.SetCustomLayoutData(result.CustomLayoutData());
+ }
+
+ if (physical_fragment.IsHiddenForPaint())
+ container_builder_.SetIsHiddenForPaint(true);
if (physical_fragment.Baseline())
container_builder_.SetBaseline(*physical_fragment.Baseline());
- if (physical_fragment.LastBaseline())
- container_builder_.SetLastBaseline(*physical_fragment.LastBaseline());
- container_builder_.SetBlockSize(ComputeBlockSizeForFragment(
+ container_builder_.SetIntrinsicBlockSize(result.IntrinsicBlockSize());
+ container_builder_.SetOverflowBlockSize(result.OverflowBlockSize());
+
+ LayoutUnit new_block_size = ComputeBlockSizeForFragment(
ConstraintSpace(), Style(),
container_builder_.Borders() + container_builder_.Padding(),
- result.IntrinsicBlockSize()));
+ result.IntrinsicBlockSize(),
+ container_builder_.InitialBorderBoxSize().inline_size);
- child_available_inline_size_ =
- ShrinkAvailableSize(container_builder_.InitialBorderBoxSize(),
- border_scrollbar_padding_)
- .inline_size;
+ // Only block-flow is allowed to change its block-size during "simplified"
+ // layout, all other layout types must remain the same size.
+ if (is_block_flow) {
+ container_builder_.SetBlockSize(new_block_size);
+ } else {
+ LayoutUnit old_block_size =
+ NGFragment(writing_mode_, physical_fragment).BlockSize();
+ DCHECK_EQ(old_block_size, new_block_size);
+ container_builder_.SetBlockSize(old_block_size);
+ }
// We need the previous physical container size to calculate the position of
// any child fragments.
previous_physical_container_size_ = physical_fragment.Size();
-
- // The static-position needs to account for any intrinsic-padding.
- if (ConstraintSpace().IsTableCell()) {
- border_scrollbar_padding_ += ComputeIntrinsicPadding(
- ConstraintSpace(), Style(), container_builder_.Scrollbar());
- }
}
scoped_refptr<const NGLayoutResult> NGSimplifiedLayoutAlgorithm::Layout() {
@@ -99,53 +139,27 @@ scoped_refptr<const NGLayoutResult> NGSimplifiedLayoutAlgorithm::Layout() {
if (Node().LayoutBlockedByDisplayLock(DisplayLockLifecycleTarget::kChildren))
return container_builder_.ToBoxFragment();
- const auto previous_child_fragments =
- To<NGPhysicalBoxFragment>(previous_result_.PhysicalFragment()).Children();
+ const auto& previous_fragment =
+ To<NGPhysicalBoxFragment>(previous_result_.PhysicalFragment());
- auto it = previous_child_fragments.begin();
- auto end = previous_child_fragments.end();
-
- // We may have a list-marker as our first child. This may have been
- // propagated up to this container by an arbitrary child. As we don't know
- // where it came from initially add it as the first child again.
- if (it != end && (*it)->IsListMarker()) {
- AddChildFragment(*it, *To<NGPhysicalContainerFragment>(it->get()));
- ++it;
- }
-
- // Initialize the static block-offset for any OOF-positioned children.
- static_block_offset_ = border_scrollbar_padding_.block_start;
-
- for (NGLayoutInputNode child = Node().FirstChild(); child;
- child = child.NextSibling()) {
- // We've already dealt with any list-markers, so just skip this node.
- if (child.IsListMarker())
- continue;
+ for (const auto& child_link : previous_fragment.Children()) {
+ const auto& child_fragment =
+ *To<NGPhysicalContainerFragment>(child_link.get());
- if (child.IsOutOfFlowPositioned()) {
- HandleOutOfFlowPositioned(To<NGBlockNode>(child));
+ // We'll add OOF-positioned candidates below.
+ if (child_fragment.IsOutOfFlowPositioned())
continue;
- }
- DCHECK(it != end);
-
- if (child.IsInline()) {
- // Simplified layout will only run if none of the lineboxes are dirty.
- while (it != end && (*it)->IsLineBox()) {
- // NOTE: When we remove continuations it'll be necessary for lineboxes
- // to keep track of any exclusions they've added (and update the
- // exclusion space).
- AddChildFragment(*it, *To<NGPhysicalContainerFragment>(it->get()));
- ++it;
- }
+ // We don't need to relayout list-markers, or line-box fragments.
+ if (child_fragment.IsListMarker() || child_fragment.IsLineBox()) {
+ AddChildFragment(child_link, child_fragment);
continue;
}
- DCHECK_EQ((*it)->GetLayoutObject(), child.GetLayoutBox());
-
// Add the (potentially updated) layout result.
scoped_refptr<const NGLayoutResult> result =
- To<NGBlockNode>(child).SimplifiedLayout();
+ NGBlockNode(ToLayoutBox(child_fragment.GetMutableLayoutObject()))
+ .SimplifiedLayout(child_fragment);
// The child may have failed "simplified" layout! (Due to adding/removing
// scrollbars). In this case we also return a nullptr, indicating a full
@@ -153,28 +167,36 @@ scoped_refptr<const NGLayoutResult> NGSimplifiedLayoutAlgorithm::Layout() {
if (!result)
return nullptr;
- const NGPhysicalContainerFragment& fragment = result->PhysicalFragment();
- AddChildFragment(*it, fragment);
-
- // Update the static block-offset for any OOF-positioned children.
- // Only consider inflow children (floats don't contribute to the intrinsic
- // block-size).
- if (!child.IsFloating()) {
- const ComputedStyle& child_style = child.Style();
- NGBoxStrut child_margins = ComputeMarginsFor(
- child_style, child_available_inline_size_, writing_mode_, direction_);
-
- NGMarginStrut margin_strut = result->EndMarginStrut();
- margin_strut.Append(child_margins.block_end,
- child_style.HasMarginBeforeQuirk());
- static_block_offset_ += margin_strut.Sum();
- }
+ AddChildFragment(child_link, result->PhysicalFragment());
+ }
+
+ // Iterate through all our OOF-positioned children and add them as candidates.
+ for (NGLayoutInputNode child = Node().FirstChild(); child;
+ child = child.NextSibling()) {
+ if (!child.IsOutOfFlowPositioned())
+ continue;
+
+ // TODO(ikilpatrick): Accessing the static-position from the layer isn't
+ // ideal. We should save this on the physical fragment which initially
+ // calculated it.
+ const auto* layer = child.GetLayoutBox()->Layer();
+ NGLogicalStaticPosition position = layer->GetStaticPosition();
- // Only take exclusion spaces from children which don't establish their own
- // formatting context.
- if (!fragment.IsFormattingContextRoot())
- exclusion_space_ = result->ExclusionSpace();
- ++it;
+ container_builder_.AddOutOfFlowChildCandidate(
+ To<NGBlockNode>(child), position.offset, position.inline_edge,
+ position.block_edge, /* needs_block_offset_adjustment */ false);
+ }
+
+ // We add both items and line-box fragments for existing mechanisms to work.
+ // We may revisit this in future. See also |NGBoxFragmentBuilder::AddResult|.
+ if (RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()) {
+ if (const NGFragmentItems* previous_items = previous_fragment.Items()) {
+ auto* items_builder = container_builder_.ItemsBuilder();
+ DCHECK(items_builder);
+ items_builder->AddPreviousItems(*previous_items, writing_mode_,
+ direction_,
+ previous_physical_container_size_);
+ }
}
NGOutOfFlowLayoutPart(
@@ -183,28 +205,26 @@ scoped_refptr<const NGLayoutResult> NGSimplifiedLayoutAlgorithm::Layout() {
&container_builder_)
.Run();
+ // The block size may have been changed. This may affect the inline block
+ // baseline if it is from the logical bottom margin edge.
+ DCHECK_EQ(previous_fragment.LastBaseline().has_value(),
+ container_builder_.LastBaseline().has_value());
+ if (container_builder_.LastBaseline())
+ container_builder_.SetLastBaselineToBlockEndMarginEdgeIfNeeded();
+
return container_builder_.ToBoxFragment();
}
-void NGSimplifiedLayoutAlgorithm::HandleOutOfFlowPositioned(
- const NGBlockNode& child) {
- LogicalOffset static_offset = {border_scrollbar_padding_.inline_start,
- static_block_offset_};
-
- if (child.Style().IsOriginalDisplayInlineType()) {
- NGBfcOffset origin_bfc_offset = {
- container_builder_.BfcLineOffset() +
- border_scrollbar_padding_.LineLeft(direction_),
- container_builder_.BfcBlockOffset().value_or(
- ConstraintSpace().ExpectedBfcBlockOffset()) +
- static_block_offset_};
-
- static_offset.inline_offset += CalculateOutOfFlowStaticInlineLevelOffset(
- Style(), origin_bfc_offset, exclusion_space_,
- child_available_inline_size_);
- }
-
- container_builder_.AddOutOfFlowChildCandidate(child, static_offset);
+NOINLINE scoped_refptr<const NGLayoutResult>
+NGSimplifiedLayoutAlgorithm::LayoutWithItemsBuilder() {
+ NGFragmentItemsBuilder items_builder;
+ container_builder_.SetItemsBuilder(&items_builder);
+ scoped_refptr<const NGLayoutResult> result = Layout();
+ // Ensure stack-allocated |NGFragmentItemsBuilder| is not used anymore.
+ // TODO(kojii): Revisit when the storage of |NGFragmentItemsBuilder| is
+ // finalized.
+ container_builder_.SetItemsBuilder(nullptr);
+ return result;
}
void NGSimplifiedLayoutAlgorithm::AddChildFragment(
@@ -212,58 +232,13 @@ void NGSimplifiedLayoutAlgorithm::AddChildFragment(
const NGPhysicalContainerFragment& new_fragment) {
DCHECK_EQ(old_fragment->Size(), new_fragment.Size());
- PhysicalSize physical_child_size = new_fragment.Size();
- LogicalSize child_size = physical_child_size.ConvertToLogical(writing_mode_);
-
// Determine the previous position in the logical coordinate system.
LogicalOffset child_offset = old_fragment.Offset().ConvertToLogical(
writing_mode_, direction_, previous_physical_container_size_,
- physical_child_size);
+ new_fragment.Size());
// Add the new fragment to the builder.
container_builder_.AddChild(new_fragment, child_offset);
-
- if (!new_fragment.IsFloating()) {
- // Update the static block-offset for any OOF-positioned children.
- // Only consider inflow children (floats don't contribute to the intrinsic
- // block-size).
- static_block_offset_ = child_offset.block_offset + child_size.block_size;
- } else {
- // We need to add the float to the exclusion space so that any inline-level
- // OOF-positioned nodes can correctly determine their static-position.
- const ComputedStyle& child_style = new_fragment.Style();
- NGBoxStrut child_margins = ComputeMarginsFor(
- child_style, child_available_inline_size_, writing_mode_, direction_);
-
- LayoutUnit child_line_offset = IsLtr(direction_)
- ? child_offset.inline_offset
- : container_builder_.InlineSize() -
- child_size.inline_size -
- child_offset.inline_offset;
-
- NGBfcOffset container_bfc_offset = {
- container_builder_.BfcLineOffset(),
- container_builder_.BfcBlockOffset().value_or(
- ConstraintSpace().ExpectedBfcBlockOffset())};
-
- // Determine the offsets for the exclusion (the margin-box of the float).
- NGBfcOffset start_offset = {
- container_bfc_offset.line_offset + child_line_offset -
- child_margins.LineLeft(direction_),
- container_bfc_offset.block_offset + child_offset.block_offset -
- child_margins.block_start};
- NGBfcOffset end_offset = {
- start_offset.line_offset +
- (child_size.inline_size + child_margins.InlineSum())
- .ClampNegativeToZero(),
- start_offset.block_offset +
- (child_size.block_size + child_margins.BlockSum())
- .ClampNegativeToZero()};
-
- exclusion_space_.Add(
- NGExclusion::Create(NGBfcRect(start_offset, end_offset),
- child_style.Floating(Style()), nullptr));
- }
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_simplified_layout_algorithm.h b/chromium/third_party/blink/renderer/core/layout/ng/ng_simplified_layout_algorithm.h
index 6921bc3e87e..bebbcf7425c 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_simplified_layout_algorithm.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_simplified_layout_algorithm.h
@@ -43,10 +43,14 @@ class CORE_EXPORT NGSimplifiedLayoutAlgorithm
const NGLayoutResult&);
scoped_refptr<const NGLayoutResult> Layout() override;
+ MinMaxSizesResult ComputeMinMaxSizes(const MinMaxSizesInput&) const override {
+ NOTREACHED();
+ return {MinMaxSizes(), true};
+ }
- private:
- void HandleOutOfFlowPositioned(const NGBlockNode&);
+ NOINLINE scoped_refptr<const NGLayoutResult> LayoutWithItemsBuilder();
+ private:
void AddChildFragment(const NGLink& old_fragment,
const NGPhysicalContainerFragment& new_fragment);
@@ -56,11 +60,7 @@ class CORE_EXPORT NGSimplifiedLayoutAlgorithm
const WritingMode writing_mode_;
const TextDirection direction_;
- LayoutUnit child_available_inline_size_;
PhysicalSize previous_physical_container_size_;
-
- LayoutUnit static_block_offset_;
- NGExclusionSpace exclusion_space_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_space_utils.cc b/chromium/third_party/blink/renderer/core/layout/ng/ng_space_utils.cc
index 11eec2a89c9..bcda1289de2 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_space_utils.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_space_utils.cc
@@ -35,6 +35,7 @@ NGConstraintSpace CreateIndefiniteConstraintSpaceForChild(
child.CreatesNewFormattingContext());
SetOrthogonalFallbackInlineSizeIfNeeded(container_style, child, &builder);
+ builder.SetCacheSlot(NGCacheSlot::kMeasure);
builder.SetAvailableSize(indefinite_size);
builder.SetPercentageResolutionSize(indefinite_size);
builder.SetReplacedPercentageResolutionSize(indefinite_size);
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table.cc b/chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table.cc
new file mode 100644
index 00000000000..5fed73b3c50
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table.cc
@@ -0,0 +1,73 @@
+// 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/core/layout/ng/table/layout_ng_table.h"
+
+#include "third_party/blink/renderer/core/layout/layout_analyzer.h"
+#include "third_party/blink/renderer/core/layout/layout_object_factory.h"
+#include "third_party/blink/renderer/core/layout/layout_view.h"
+#include "third_party/blink/renderer/core/layout/ng/ng_layout_result.h"
+#include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_caption.h"
+#include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_column.h"
+#include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_section.h"
+
+namespace blink {
+
+LayoutNGTable::LayoutNGTable(Element* element)
+ : LayoutNGMixin<LayoutBlock>(element) {}
+
+wtf_size_t LayoutNGTable::ColumnCount() const {
+ // TODO(atotic) land implementation.
+ NOTIMPLEMENTED();
+ return 0;
+}
+
+void LayoutNGTable::UpdateBlockLayout(bool relayout_children) {
+ LayoutAnalyzer::BlockScope analyzer(*this);
+
+ if (IsOutOfFlowPositioned()) {
+ UpdateOutOfFlowBlockLayout();
+ return;
+ }
+ UpdateInFlowBlockLayout();
+}
+
+bool LayoutNGTable::IsFirstCell(const LayoutNGTableCellInterface& cell) const {
+ const LayoutNGTableRowInterface* row = cell.RowInterface();
+ if (row->FirstCellInterface() != &cell)
+ return false;
+ const LayoutNGTableSectionInterface* section = row->SectionInterface();
+ if (section->FirstRowInterface() != row)
+ return false;
+ // TODO(atotic) Should be TopNonEmptyInterface?
+ if (TopSectionInterface() != section)
+ return false;
+ return true;
+}
+
+// Only called from AXLayoutObject::IsDataTable()
+LayoutNGTableSectionInterface* LayoutNGTable::FirstBodyInterface() const {
+ for (LayoutObject* child = FirstChild(); child;
+ child = child->NextSibling()) {
+ if (child->StyleRef().Display() == EDisplay::kTableRowGroup)
+ return ToInterface<LayoutNGTableSectionInterface>(child);
+ }
+ return nullptr;
+}
+
+// Called from many AXLayoutObject methods.
+LayoutNGTableSectionInterface* LayoutNGTable::TopSectionInterface() const {
+ // TODO(atotic) implement.
+ return nullptr;
+}
+
+// Called from many AXLayoutObject methods.
+LayoutNGTableSectionInterface* LayoutNGTable::SectionBelowInterface(
+ const LayoutNGTableSectionInterface* target,
+ SkipEmptySectionsValue skip) const {
+ // TODO(atotic) implement.
+ return nullptr;
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table.h b/chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table.h
new file mode 100644
index 00000000000..06186b60675
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table.h
@@ -0,0 +1,139 @@
+// 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_CORE_LAYOUT_NG_TABLE_LAYOUT_NG_TABLE_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_TABLE_LAYOUT_NG_TABLE_H_
+
+#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/core/layout/layout_block.h"
+#include "third_party/blink/renderer/core/layout/ng/layout_ng_mixin.h"
+#include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_interface.h"
+
+namespace blink {
+
+class CORE_EXPORT LayoutNGTable : public LayoutNGMixin<LayoutBlock>,
+ public LayoutNGTableInterface {
+ public:
+ explicit LayoutNGTable(Element*);
+
+ // TODO(atotic) Replace all H/VBorderSpacing with BorderSpacing?
+ LogicalSize BorderSpacing() const {
+ if (ShouldCollapseBorders())
+ return LogicalSize();
+ return LogicalSize(LayoutUnit(HBorderSpacing()),
+ LayoutUnit(VBorderSpacing()));
+ }
+
+ wtf_size_t ColumnCount() const;
+
+ // LayoutBlock methods start.
+
+ const char* GetName() const override { return "LayoutNGTable"; }
+
+ void UpdateBlockLayout(bool relayout_children) override;
+
+ // LayoutBlock methods end.
+
+ // LayoutNGTableInterface methods start.
+
+ const LayoutNGTableInterface* ToLayoutNGTableInterface() const final {
+ return this;
+ }
+ const LayoutObject* ToLayoutObject() const final { return this; }
+ // Non-const version required by TextAutosizer, AXLayoutObject.
+ LayoutObject* ToMutableLayoutObject() final { return this; }
+ bool ShouldCollapseBorders() const final {
+ return StyleRef().BorderCollapse() == EBorderCollapse::kCollapse;
+ }
+ // Used in table painting for invalidation. Should not be needed by NG.
+ bool HasCollapsedBorders() const final {
+ NOTREACHED();
+ return false;
+ }
+ bool HasColElements() const final {
+ NOTREACHED();
+ return false;
+ }
+
+ bool IsFixedTableLayout() const final {
+ return StyleRef().TableLayout() == ETableLayout::kFixed &&
+ !StyleRef().LogicalWidth().IsAuto();
+ }
+ int16_t HBorderSpacing() const final {
+ return ShouldCollapseBorders() ? 0 : StyleRef().HorizontalBorderSpacing();
+ }
+ int16_t VBorderSpacing() const final {
+ return ShouldCollapseBorders() ? 0 : StyleRef().VerticalBorderSpacing();
+ }
+
+ // Legacy had a concept of colspan column compression. This is a legacy
+ // method to map between absolute and compressed columns.
+ // Because NG does not compress columns, absolute and effective are the same.
+ unsigned AbsoluteColumnToEffectiveColumn(
+ unsigned absolute_column_index) const final {
+ return absolute_column_index;
+ }
+
+ // Legacy caches sections. Might not be needed by NG.
+ void RecalcSectionsIfNeeded() const final {}
+ // Legacy caches sections. Might not be needed by NG.
+ void ForceSectionsRecalc() final {}
+
+ // Used in paint for printing. Should not be needed by NG.
+ LayoutUnit RowOffsetFromRepeatingFooter() const final {
+ NOTIMPLEMENTED(); // OK, never used.
+ return LayoutUnit();
+ }
+ // Used in paint for printing. Should not be needed by NG.
+ LayoutUnit RowOffsetFromRepeatingHeader() const final {
+ NOTIMPLEMENTED(); // OK, never used.
+ return LayoutUnit();
+ }
+
+ bool IsFirstCell(const LayoutNGTableCellInterface&) const final;
+
+ LayoutNGTableSectionInterface* FirstBodyInterface() const final;
+
+ LayoutNGTableSectionInterface* TopSectionInterface() const final;
+
+ LayoutNGTableSectionInterface* SectionBelowInterface(
+ const LayoutNGTableSectionInterface*,
+ SkipEmptySectionsValue) const final;
+
+ // Following methods are called during printing, not in TablesNG.
+ LayoutNGTableSectionInterface* TopNonEmptySectionInterface() const final {
+ NOTREACHED();
+ return nullptr;
+ }
+
+ LayoutNGTableSectionInterface* BottomSectionInterface() const final {
+ NOTREACHED();
+ return nullptr;
+ }
+
+ LayoutNGTableSectionInterface* BottomNonEmptySectionInterface() const final {
+ NOTREACHED();
+ return nullptr;
+ }
+
+ // LayoutNGTableInterface methods end.
+
+ protected:
+ bool IsOfType(LayoutObjectType type) const override {
+ return type == kLayoutObjectTable ||
+ LayoutNGMixin<LayoutBlock>::IsOfType(type);
+ }
+};
+
+// wtf/casting.h helper.
+template <>
+struct DowncastTraits<LayoutNGTable> {
+ static bool AllowFrom(const LayoutObject& object) {
+ return object.IsTable() && object.IsLayoutNGObject();
+ }
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_TABLE_LAYOUT_NG_TABLE_H_
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_table_caption.cc b/chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_caption.cc
index 2a611c31d3a..2151b48d83c 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_table_caption.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_caption.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "third_party/blink/renderer/core/layout/ng/layout_ng_table_caption.h"
+#include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_caption.h"
#include "third_party/blink/renderer/core/layout/layout_analyzer.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
@@ -19,6 +19,7 @@ namespace blink {
LayoutNGTableCaption::LayoutNGTableCaption(Element* element)
: LayoutNGBlockFlowMixin<LayoutTableCaption>(element) {}
+// Legacy method.
void LayoutNGTableCaption::CalculateAndSetMargins(
const NGConstraintSpace& constraint_space,
const NGPhysicalFragment& physical_fragment) {
@@ -66,7 +67,8 @@ void LayoutNGTableCaption::UpdateBlockLayout(bool relayout_children) {
// NGBoxFragmentPainter::Paint will have to handle it until table layout is
// implemented in NG, in which case that algorithm will set each child's
// offsets. See https://crbug.com/788590 for more info.
- DCHECK(!result->PhysicalFragment().IsPlacedByLayoutNG())
+ DCHECK(RuntimeEnabledFeatures::LayoutNGTableEnabled() ||
+ !result->PhysicalFragment().IsPlacedByLayoutNG())
<< "Only a table should be placing table caption fragments and the ng "
"table algorithm doesn't exist yet!";
}
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_table_caption.h b/chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_caption.h
index 35ee8e2d78e..d4a6018f372 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_table_caption.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_caption.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_LAYOUT_NG_TABLE_CAPTION_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_LAYOUT_NG_TABLE_CAPTION_H_
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_TABLE_LAYOUT_NG_TABLE_CAPTION_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_TABLE_LAYOUT_NG_TABLE_CAPTION_H_
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/layout/layout_table_caption.h"
@@ -25,6 +25,14 @@ class CORE_EXPORT LayoutNGTableCaption final
const NGPhysicalFragment&);
};
+// wtf/casting.h helper.
+template <>
+struct DowncastTraits<LayoutNGTableCaption> {
+ static bool AllowFrom(const LayoutObject& object) {
+ return object.IsTableCaption() && object.IsLayoutNGObject();
+ }
+};
+
} // namespace blink
-#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_LAYOUT_NG_TABLE_CAPTION_H_
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_TABLE_LAYOUT_NG_TABLE_CAPTION_H_
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_cell.cc b/chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_cell.cc
new file mode 100644
index 00000000000..8f501b93c79
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_cell.cc
@@ -0,0 +1,124 @@
+// 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/core/layout/ng/table/layout_ng_table_cell.h"
+
+#include "third_party/blink/renderer/core/html/html_table_cell_element.h"
+#include "third_party/blink/renderer/core/html/table_constants.h"
+#include "third_party/blink/renderer/core/layout/layout_analyzer.h"
+#include "third_party/blink/renderer/core/layout/layout_object_factory.h"
+#include "third_party/blink/renderer/core/layout/layout_view.h"
+#include "third_party/blink/renderer/core/layout/ng/ng_block_node.h"
+#include "third_party/blink/renderer/core/layout/ng/ng_constraint_space.h"
+#include "third_party/blink/renderer/core/layout/ng/ng_out_of_flow_positioned_node.h"
+#include "third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h"
+#include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_row.h"
+
+namespace blink {
+
+LayoutNGTableCell::LayoutNGTableCell(Element* element)
+ : LayoutNGBlockFlowMixin<LayoutBlockFlow>(element) {
+ UpdateColAndRowSpanFlags();
+}
+
+void LayoutNGTableCell::UpdateBlockLayout(bool relayout_children) {
+ LayoutAnalyzer::BlockScope analyzer(*this);
+
+ if (IsOutOfFlowPositioned()) {
+ UpdateOutOfFlowBlockLayout();
+ return;
+ }
+ UpdateInFlowBlockLayout();
+}
+
+void LayoutNGTableCell::ColSpanOrRowSpanChanged() {
+ // TODO(atotic) Invalidate layout?
+ UpdateColAndRowSpanFlags();
+}
+
+Length LayoutNGTableCell::StyleOrColLogicalWidth() const {
+ // TODO(atotic) TablesNG cannot easily get col width before layout.
+ return StyleRef().LogicalWidth();
+}
+
+// TODO(crbug.com/1079133): Used by AXLayoutObject::RowIndex,
+// verify behaviour is correct.
+unsigned LayoutNGTableCell::RowIndex() const {
+ return To<LayoutNGTableRow>(Parent())->RowIndex();
+}
+
+// TODO(crbug.com/1079133): Used by AXLayoutObject::CellForColumnAndRow,
+// verify behaviour is correct.
+unsigned LayoutNGTableCell::ResolvedRowSpan() const {
+ return ParsedRowSpan();
+}
+
+// TODO(crbug.com/1079133): Used by AXLayoutObject,
+// verify behaviour is correct.
+unsigned LayoutNGTableCell::AbsoluteColumnIndex() const {
+ unsigned index = 0;
+ for (LayoutObject* child = Parent()->SlowFirstChild(); child;
+ child = child->NextSibling()) {
+ if (child == this)
+ return index;
+ ++index;
+ }
+ NOTREACHED() << "AbsoluteColumnIndex did not find cell";
+ return 0;
+}
+
+unsigned LayoutNGTableCell::ColSpan() const {
+ if (!has_col_span_)
+ return 1;
+ return ParseColSpanFromDOM();
+}
+
+unsigned LayoutNGTableCell::ParseColSpanFromDOM() const {
+ if (const auto* cell_element = DynamicTo<HTMLTableCellElement>(GetNode())) {
+ unsigned span = cell_element->colSpan();
+ DCHECK_GE(span, kMinColSpan);
+ DCHECK_LE(span, kMaxColSpan);
+ return span;
+ }
+ return kDefaultRowSpan;
+}
+
+unsigned LayoutNGTableCell::ParseRowSpanFromDOM() const {
+ if (const auto* cell_element = DynamicTo<HTMLTableCellElement>(GetNode())) {
+ unsigned span = cell_element->rowSpan();
+ DCHECK_GE(span, kMinRowSpan);
+ DCHECK_LE(span, kMaxRowSpan);
+ return span;
+ }
+ return kDefaultColSpan;
+}
+
+void LayoutNGTableCell::UpdateColAndRowSpanFlags() {
+ // Colspan or rowspan are rare, so we keep the values in DOM.
+ has_col_span_ = ParseColSpanFromDOM() != kDefaultColSpan;
+ has_rowspan_ = ParseRowSpanFromDOM() != kDefaultRowSpan;
+}
+
+LayoutNGTableInterface* LayoutNGTableCell::TableInterface() const {
+ return ToInterface<LayoutNGTableInterface>(Parent()->Parent()->Parent());
+}
+
+LayoutNGTableCellInterface* LayoutNGTableCell::NextCellInterface() const {
+ return ToInterface<LayoutNGTableCellInterface>(LayoutObject::NextSibling());
+}
+
+LayoutNGTableCellInterface* LayoutNGTableCell::PreviousCellInterface() const {
+ return ToInterface<LayoutNGTableCellInterface>(
+ LayoutObject::PreviousSibling());
+}
+
+LayoutNGTableRowInterface* LayoutNGTableCell::RowInterface() const {
+ return ToInterface<LayoutNGTableRowInterface>(Parent());
+}
+
+LayoutNGTableSectionInterface* LayoutNGTableCell::SectionInterface() const {
+ return ToInterface<LayoutNGTableSectionInterface>(Parent()->Parent());
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_cell.h b/chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_cell.h
new file mode 100644
index 00000000000..4c70aef0a31
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_cell.h
@@ -0,0 +1,118 @@
+// 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_CORE_LAYOUT_NG_TABLE_LAYOUT_NG_TABLE_CELL_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_TABLE_LAYOUT_NG_TABLE_CELL_H_
+
+#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/core/html/table_constants.h"
+#include "third_party/blink/renderer/core/layout/layout_block_flow.h"
+#include "third_party/blink/renderer/core/layout/ng/layout_ng_block_flow_mixin.h"
+#include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_cell_interface.h"
+
+namespace blink {
+
+class CORE_EXPORT LayoutNGTableCell
+ : public LayoutNGBlockFlowMixin<LayoutBlockFlow>,
+ public LayoutNGTableCellInterface {
+ public:
+ explicit LayoutNGTableCell(Element*);
+
+ unsigned ComputedRowSpan() const {
+ if (!has_rowspan_)
+ return 1;
+ unsigned rowspan = ParseRowSpanFromDOM();
+ if (rowspan == 0) // rowspan == 0 means all rows.
+ rowspan = kMaxRowSpan;
+ return rowspan;
+ }
+
+ // LayoutBlockFlow methods start.
+
+ void UpdateBlockLayout(bool relayout_children) override;
+
+ // TODO(atotic) Remove "New" from name.
+ // Currently, LayoutNGTableCellLegacy is named LayoutNGTableCell for test
+ // compat.
+ const char* GetName() const final { return "LayoutNGTableCellNew"; }
+
+ // LayoutBlockFlow methods end.
+
+ // LayoutNGTableCellInterface methods start.
+
+ const LayoutTableCell* ToLayoutTableCell() const final {
+ NOTREACHED();
+ return nullptr;
+ }
+
+ const LayoutNGTableCellInterface* ToLayoutNGTableCellInterface() const final {
+ return this;
+ }
+ const LayoutObject* ToLayoutObject() const final { return this; }
+
+ LayoutObject* ToMutableLayoutObject() final { return this; }
+
+ LayoutNGTableInterface* TableInterface() const final;
+
+ void ColSpanOrRowSpanChanged() final;
+
+ Length StyleOrColLogicalWidth() const final;
+
+ // Not used in LayoutNG.
+ int IntrinsicPaddingBefore() const final { return 0; }
+ // Not used in LayoutNG.
+ int IntrinsicPaddingAfter() const final { return 0; }
+
+ unsigned RowIndex() const final;
+
+ unsigned ResolvedRowSpan() const final;
+
+ unsigned AbsoluteColumnIndex() const final;
+
+ unsigned ColSpan() const final;
+
+ LayoutNGTableCellInterface* NextCellInterface() const final;
+
+ LayoutNGTableCellInterface* PreviousCellInterface() const final;
+
+ LayoutNGTableRowInterface* RowInterface() const final;
+
+ LayoutNGTableSectionInterface* SectionInterface() const final;
+
+ // LayoutNGTableCellInterface methods end.
+
+ protected:
+ bool IsOfType(LayoutObjectType type) const final {
+ return type == kLayoutObjectTableCell ||
+ LayoutNGBlockFlowMixin<LayoutBlockFlow>::IsOfType(type);
+ }
+
+ private:
+ void UpdateColAndRowSpanFlags();
+
+ unsigned ParseRowSpanFromDOM() const;
+
+ unsigned ParseColSpanFromDOM() const;
+ // Use ComputedRowSpan instead
+ unsigned ParsedRowSpan() const {
+ if (!has_rowspan_)
+ return 1;
+ return ParseRowSpanFromDOM();
+ }
+
+ unsigned has_col_span_ : 1;
+ unsigned has_rowspan_ : 1;
+};
+
+// wtf/casting.h helper.
+template <>
+struct DowncastTraits<LayoutNGTableCell> {
+ static bool AllowFrom(const LayoutObject& object) {
+ return object.IsTableCell() && !object.IsTableCellLegacy();
+ }
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_TABLE_LAYOUT_NG_TABLE_CELL_H_
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_table_cell.cc b/chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_cell_legacy.cc
index 87eec6dff43..4e5d2eb6456 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_table_cell.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_cell_legacy.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "third_party/blink/renderer/core/layout/ng/layout_ng_table_cell.h"
+#include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_cell_legacy.h"
#include "third_party/blink/renderer/core/layout/layout_analyzer.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
@@ -15,10 +15,10 @@
namespace blink {
-LayoutNGTableCell::LayoutNGTableCell(Element* element)
+LayoutNGTableCellLegacy::LayoutNGTableCellLegacy(Element* element)
: LayoutNGBlockFlowMixin<LayoutTableCell>(element) {}
-void LayoutNGTableCell::UpdateBlockLayout(bool relayout_children) {
+void LayoutNGTableCellLegacy::UpdateBlockLayout(bool relayout_children) {
LayoutAnalyzer::BlockScope analyzer(*this);
SetOverrideLogicalWidth(LogicalWidth());
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_cell_legacy.h b/chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_cell_legacy.h
new file mode 100644
index 00000000000..d485d54531d
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_cell_legacy.h
@@ -0,0 +1,39 @@
+// 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_CORE_LAYOUT_NG_TABLE_LAYOUT_NG_TABLE_CELL_LEGACY_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_TABLE_LAYOUT_NG_TABLE_CELL_LEGACY_H_
+
+#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/core/layout/layout_table_cell.h"
+#include "third_party/blink/renderer/core/layout/ng/layout_ng_block_flow_mixin.h"
+
+namespace blink {
+
+// This is a LayoutNG variant of LayoutTableCell.
+// There are 3 table cell classes in Chrome
+// LayoutNGTableCell - TablesNG cell, whole table is NG.
+// LayoutNGTableCellLegacy - NG cell inside a legacy table.
+// LayoutTableCell - Legacy cell inside legacy table.
+class CORE_EXPORT LayoutNGTableCellLegacy final
+ : public LayoutNGBlockFlowMixin<LayoutTableCell> {
+ public:
+ explicit LayoutNGTableCellLegacy(Element*);
+
+ void UpdateBlockLayout(bool relayout_children) override;
+
+ // This class used to be called LayoutNGTableCell, and many test baselines
+ // expect its name to be LayoutNGTableCell, not LayoutNGTableCellLegacy.
+ const char* GetName() const override { return "LayoutNGTableCell"; }
+
+ protected:
+ bool IsOfType(LayoutObjectType type) const final {
+ return type == kLayoutObjectTableCellLegacy ||
+ LayoutNGBlockFlowMixin<LayoutTableCell>::IsOfType(type);
+ }
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_TABLE_LAYOUT_NG_TABLE_CELL_LEGACY_H_
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_column.cc b/chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_column.cc
new file mode 100644
index 00000000000..c72d3fd679d
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_column.cc
@@ -0,0 +1,82 @@
+// 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/core/layout/ng/table/layout_ng_table_column.h"
+
+#include "third_party/blink/renderer/core/html/html_table_col_element.h"
+#include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table.h"
+
+namespace blink {
+
+LayoutNGTableColumn::LayoutNGTableColumn(Element* element)
+ : LayoutBox(element) {
+ UpdateFromElement();
+}
+
+void LayoutNGTableColumn::StyleDidChange(StyleDifference diff,
+ const ComputedStyle* old_style) {
+ if (diff.NeedsPaintInvalidation() && old_style) {
+ // Could also call SetShouldDoFullPaintInvalidationWithoutGeometryChange?
+ // TODO(atotic+paint_team) Need paint team review.
+ // Is this how to invalidate background only?
+ if (LayoutNGTable* table = Table()) {
+ table->SetShouldDoFullPaintInvalidationWithoutGeometryChange(
+ PaintInvalidationReason::kBackground);
+ }
+ }
+ LayoutBoxModelObject::StyleDidChange(diff, old_style);
+}
+
+void LayoutNGTableColumn::ImageChanged(WrappedImagePtr, CanDeferInvalidation) {
+ // TODO(atotic+paint_team) Need paint team review.
+ // LayoutBox::ImageChanged is a lot more sophisticated.
+ // Should I call SetShouldDoFullPaintInvalidationWithoutGeometryChange
+ // instead?
+ if (LayoutNGTable* table = Table())
+ table->SetShouldDoFullPaintInvalidation(PaintInvalidationReason::kImage);
+}
+
+bool LayoutNGTableColumn::IsChildAllowed(LayoutObject* child,
+ const ComputedStyle& style) const {
+ return child->IsLayoutTableCol() && style.Display() == EDisplay::kTableColumn;
+}
+
+bool LayoutNGTableColumn::CanHaveChildren() const {
+ // <col> cannot have children.
+ return IsColumnGroup();
+}
+
+void LayoutNGTableColumn::ClearNeedsLayoutForChildren() const {
+ LayoutObject* child = FirstChild();
+ while (child) {
+ child->ClearNeedsLayout();
+ child = child->NextSibling();
+ }
+}
+
+LayoutNGTable* LayoutNGTableColumn::Table() const {
+ LayoutObject* table = Parent();
+ if (table && !table->IsTable())
+ table = table->Parent();
+ if (table) {
+ DCHECK(table->IsTable());
+ return To<LayoutNGTable>(table);
+ }
+ return nullptr;
+}
+
+void LayoutNGTableColumn::UpdateFromElement() {
+ unsigned old_span = span_;
+ if (const auto* tc = DynamicTo<HTMLTableColElement>(GetNode())) {
+ span_ = tc->span();
+ } else {
+ span_ = 1;
+ }
+ if (span_ != old_span && Style() && Parent()) {
+ SetNeedsLayoutAndIntrinsicWidthsRecalcAndFullPaintInvalidation(
+ layout_invalidation_reason::kAttributeChanged);
+ }
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_column.h b/chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_column.h
new file mode 100644
index 00000000000..311a47c395c
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_column.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_CORE_LAYOUT_NG_TABLE_LAYOUT_NG_TABLE_COLUMN_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_TABLE_LAYOUT_NG_TABLE_COLUMN_H_
+
+#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/core/layout/layout_box.h"
+
+namespace blink {
+
+class LayoutNGTable;
+
+// Represents <col> and <colgroup> elements.
+class CORE_EXPORT LayoutNGTableColumn : public LayoutBox {
+ public:
+ explicit LayoutNGTableColumn(Element*);
+
+ LayoutNGTable* Table() const;
+
+ bool IsColumn() const {
+ return StyleRef().Display() == EDisplay::kTableColumn;
+ }
+
+ bool IsColumnGroup() const {
+ return StyleRef().Display() == EDisplay::kTableColumnGroup;
+ }
+
+ unsigned Span() const { return span_; }
+
+ // Clears needs-layout for child columns too.
+ void ClearNeedsLayoutForChildren() const;
+
+ // LayoutObject methods start.
+
+ const char* GetName() const override {
+ if (IsColumn())
+ return "LayoutNGTableCol";
+ else
+ return "LayoutNGTableColGroup";
+ }
+
+ bool IsLayoutNGObject() const final { return true; }
+
+ void StyleDidChange(StyleDifference diff,
+ const ComputedStyle* old_style) final;
+
+ void ImageChanged(WrappedImagePtr, CanDeferInvalidation) final;
+
+ LayoutObject* FirstChild() const { return children_.FirstChild(); }
+
+ void SlowFirstChild() const = delete;
+
+ protected:
+ // Required by LayoutBox, but not used.
+ MinMaxSizes ComputeIntrinsicLogicalWidths() const override {
+ NOTIMPLEMENTED();
+ return MinMaxSizes();
+ }
+
+ bool IsOfType(LayoutObjectType type) const override {
+ return type == kLayoutObjectLayoutTableCol || LayoutBox::IsOfType(type);
+ }
+
+ private:
+ bool IsChildAllowed(LayoutObject*, const ComputedStyle&) const override;
+
+ bool CanHaveChildren() const override;
+
+ void UpdateFromElement() override;
+
+ PaintLayerType LayerTypeRequired() const override { return kNoPaintLayer; }
+
+ LayoutObjectChildList* VirtualChildren() override { return &children_; }
+
+ // LayoutObject methods end
+
+ unsigned span_ = 1;
+ LayoutObjectChildList children_;
+};
+
+// wtf/casting.h helper.
+template <>
+struct DowncastTraits<LayoutNGTableColumn> {
+ static bool AllowFrom(const LayoutObject& object) {
+ return object.IsLayoutTableCol() && object.IsLayoutNGObject();
+ }
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_TABLE_LAYOUT_NG_TABLE_COLUMN_H_
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_interface.h b/chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_interface.h
index 3ee91ff13bb..f600a05afc9 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_interface.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_interface.h
@@ -23,21 +23,27 @@ class LayoutNGTableInterface {
// Non-const version required by TextAutosizer, AXLayoutObject.
virtual LayoutObject* ToMutableLayoutObject() = 0;
virtual bool ShouldCollapseBorders() const = 0;
+ // TODO(crbug.com/1081425) Method not used by NG, should be removed.
virtual bool HasCollapsedBorders() const = 0;
virtual bool IsFixedTableLayout() const = 0;
virtual int16_t HBorderSpacing() const = 0;
virtual int16_t VBorderSpacing() const = 0;
+ // TODO(crbug.com/1081425) Method not used by NG, should be removed.
virtual bool HasColElements() const = 0;
virtual unsigned AbsoluteColumnToEffectiveColumn(
unsigned absolute_column_index) const = 0;
virtual void RecalcSectionsIfNeeded() const = 0;
virtual void ForceSectionsRecalc() = 0;
+ // TODO(crbug.com/1081425) Method not used by NG, should be removed.
virtual LayoutUnit RowOffsetFromRepeatingFooter() const = 0;
+ // TODO(crbug.com/1081425) Method not used by NG, should be removed.
virtual LayoutUnit RowOffsetFromRepeatingHeader() const = 0;
virtual LayoutNGTableSectionInterface* FirstBodyInterface() const = 0;
virtual LayoutNGTableSectionInterface* TopSectionInterface() const = 0;
+ // TODO(crbug.com/1081425) Method not used by NG, should be removed.
virtual LayoutNGTableSectionInterface* TopNonEmptySectionInterface()
const = 0;
+ // TODO(crbug.com/1081425) Method not used by NG, should be removed.
virtual LayoutNGTableSectionInterface* BottomSectionInterface() const = 0;
virtual LayoutNGTableSectionInterface* BottomNonEmptySectionInterface()
const = 0;
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_row.cc b/chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_row.cc
new file mode 100644
index 00000000000..48db1645c21
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_row.cc
@@ -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.
+
+#include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_row.h"
+
+#include "third_party/blink/renderer/core/layout/layout_analyzer.h"
+#include "third_party/blink/renderer/core/layout/layout_view.h"
+#include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_cell.h"
+#include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_row_interface.h"
+#include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_section.h"
+#include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_section_interface.h"
+
+namespace blink {
+
+LayoutNGTableRow::LayoutNGTableRow(Element* element)
+ : LayoutNGMixin<LayoutBlock>(element) {}
+
+bool LayoutNGTableRow::IsEmpty() const {
+ return !FirstChild();
+}
+
+unsigned LayoutNGTableRow::RowIndex() const {
+ unsigned index = 0;
+ for (LayoutObject* child = Parent()->SlowFirstChild(); child;
+ child = child->NextSibling()) {
+ if (child == this)
+ return index;
+ ++index;
+ }
+ NOTREACHED();
+ return 0;
+}
+
+LayoutNGTableCell* LayoutNGTableRow::LastCell() const {
+ return To<LayoutNGTableCell>(LastChild());
+}
+
+LayoutNGTableSectionInterface* LayoutNGTableRow::SectionInterface() const {
+ return To<LayoutNGTableSection>(Parent());
+}
+
+LayoutNGTableRowInterface* LayoutNGTableRow::PreviousRowInterface() const {
+ return ToInterface<LayoutNGTableRowInterface>(PreviousSibling());
+}
+
+LayoutNGTableRowInterface* LayoutNGTableRow::NextRowInterface() const {
+ return ToInterface<LayoutNGTableRowInterface>(NextSibling());
+}
+
+LayoutNGTableCellInterface* LayoutNGTableRow::FirstCellInterface() const {
+ return ToInterface<LayoutNGTableCellInterface>(FirstChild());
+}
+
+LayoutNGTableCellInterface* LayoutNGTableRow::LastCellInterface() const {
+ return ToInterface<LayoutNGTableCellInterface>(LastChild());
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_row.h b/chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_row.h
new file mode 100644
index 00000000000..8b08dd07582
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_row.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_CORE_LAYOUT_NG_TABLE_LAYOUT_NG_TABLE_ROW_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_TABLE_LAYOUT_NG_TABLE_ROW_H_
+
+#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/core/layout/layout_block.h"
+#include "third_party/blink/renderer/core/layout/ng/layout_ng_mixin.h"
+
+namespace blink {
+
+class LayoutNGTableCell;
+// NOTE:
+// Legacy table row inherits from LayoutBox, not LayoutBlock.
+// Every child of LayoutNGTableRow must be LayoutNGTableCell.
+class CORE_EXPORT LayoutNGTableRow : public LayoutNGMixin<LayoutBlock>,
+ public LayoutNGTableRowInterface {
+ public:
+ explicit LayoutNGTableRow(Element*);
+
+ bool IsEmpty() const;
+
+ // LayoutBlock methods start.
+
+ void UpdateBlockLayout(bool relayout_children) override { NOTREACHED(); }
+
+ const char* GetName() const override { return "LayoutNGTableRow"; }
+
+ // Whether a row has opaque background depends on many factors, e.g. border
+ // spacing, border collapsing, missing cells, etc.
+ // For simplicity, just conservatively assume all table rows are not opaque.
+ // Copied from Legacy's LayoutTableRow
+ bool BackgroundIsKnownToBeOpaqueInRect(const PhysicalRect&) const override {
+ return false;
+ }
+
+ bool AllowsOverflowClip() const override { return false; }
+
+ // LayoutBlock methods end.
+
+ // LayoutNGTableRowInterface methods start.
+
+ const LayoutObject* ToLayoutObject() const final { return this; }
+
+ const LayoutTableRow* ToLayoutTableRow() const final {
+ NOTREACHED();
+ return nullptr;
+ }
+
+ const LayoutNGTableRowInterface* ToLayoutNGTableRowInterface() const final {
+ return this;
+ }
+
+ LayoutNGTableInterface* TableInterface() const final {
+ return SectionInterface()->TableInterface();
+ }
+
+ unsigned RowIndex() const final;
+
+ LayoutNGTableSectionInterface* SectionInterface() const final;
+
+ LayoutNGTableRowInterface* PreviousRowInterface() const final;
+
+ LayoutNGTableRowInterface* NextRowInterface() const final;
+
+ LayoutNGTableCellInterface* FirstCellInterface() const final;
+
+ LayoutNGTableCellInterface* LastCellInterface() const final;
+
+ // LayoutNGTableRowInterface methods end.
+
+ protected:
+ LayoutNGTableCell* LastCell() const;
+
+ bool IsOfType(LayoutObjectType type) const override {
+ return type == kLayoutObjectTableRow ||
+ LayoutNGMixin<LayoutBlock>::IsOfType(type);
+ }
+};
+
+// wtf/casting.h helper.
+template <>
+struct DowncastTraits<LayoutNGTableRow> {
+ static bool AllowFrom(const LayoutObject& object) {
+ return object.IsTableRow() && object.IsLayoutNGObject();
+ }
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_TABLE_LAYOUT_NG_TABLE_ROW_H_
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_section.cc b/chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_section.cc
new file mode 100644
index 00000000000..06225acabcb
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_section.cc
@@ -0,0 +1,101 @@
+// 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/core/layout/ng/table/layout_ng_table_section.h"
+
+#include "third_party/blink/renderer/core/layout/layout_analyzer.h"
+#include "third_party/blink/renderer/core/layout/layout_view.h"
+#include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table.h"
+#include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_cell.h"
+#include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_interface.h"
+#include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_row.h"
+
+namespace blink {
+
+LayoutNGTableSection::LayoutNGTableSection(Element* element)
+ : LayoutNGMixin<LayoutBlock>(element) {}
+
+bool LayoutNGTableSection::IsEmpty() const {
+ for (LayoutObject* child = FirstChild(); child;
+ child = child->NextSibling()) {
+ if (!To<LayoutNGTableRow>(child)->IsEmpty())
+ return false;
+ }
+ return true;
+}
+
+LayoutNGTableInterface* LayoutNGTableSection::TableInterface() const {
+ return ToInterface<LayoutNGTableInterface>(Parent());
+}
+
+void LayoutNGTableSection::SetNeedsCellRecalc() {
+ SetNeedsLayout(layout_invalidation_reason::kDomChanged);
+}
+
+LayoutNGTableRowInterface* LayoutNGTableSection::FirstRowInterface() const {
+ return ToInterface<LayoutNGTableRowInterface>(FirstChild());
+}
+
+LayoutNGTableRowInterface* LayoutNGTableSection::LastRowInterface() const {
+ return ToInterface<LayoutNGTableRowInterface>(LastChild());
+}
+
+const LayoutNGTableCellInterface* LayoutNGTableSection::PrimaryCellInterfaceAt(
+ unsigned row,
+ unsigned column) const {
+ unsigned current_row = 0;
+ for (LayoutObject* layout_row = FirstChild(); layout_row;
+ layout_row = layout_row->NextSibling()) {
+ DCHECK(layout_row->IsTableRow());
+ if (current_row++ == row) {
+ unsigned current_column = 0;
+ for (LayoutObject* layout_cell = layout_row->SlowFirstChild();
+ layout_cell; layout_cell = layout_cell->NextSibling()) {
+ if (current_column++ == column) {
+ return ToInterface<LayoutNGTableCellInterface>(layout_cell);
+ }
+ }
+ return nullptr;
+ }
+ }
+ return nullptr;
+}
+
+// TODO(crbug.com/1079133): Used by AXLayoutObject::IsDataTable, verify
+// behaviour is correct. Consider removing these methods.
+unsigned LayoutNGTableSection::NumEffectiveColumns() const {
+ return To<LayoutNGTable>(TableInterface()->ToLayoutObject())->ColumnCount();
+}
+
+// TODO(crbug.com/1079133): Used by AXLayoutObject::IsDataTable/ColumnCount,
+// verify behaviour is correct.
+unsigned LayoutNGTableSection::NumCols(unsigned row) const {
+ unsigned current_row = 0;
+ for (LayoutObject* layout_row = FirstChild(); layout_row;
+ layout_row = layout_row->NextSibling()) {
+ if (current_row++ == row) {
+ unsigned current_column = 0;
+ for (LayoutObject* layout_cell = FirstChild(); layout_cell;
+ layout_cell = layout_cell->NextSibling()) {
+ ++current_column;
+ }
+ return current_column;
+ }
+ }
+ return 0;
+}
+
+// TODO(crbug.com/1079133): Used by AXLayoutObject, verify behaviour is
+// correct, and if caching is required.
+unsigned LayoutNGTableSection::NumRows() const {
+ unsigned num_rows = 0;
+ for (LayoutObject* layout_row = FirstChild(); layout_row;
+ layout_row = layout_row->NextSibling()) {
+ // TODO(crbug.com/1079133) skip for abspos?
+ ++num_rows;
+ }
+ return num_rows;
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_section.h b/chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_section.h
new file mode 100644
index 00000000000..64136c51551
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_section.h
@@ -0,0 +1,103 @@
+// 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_CORE_LAYOUT_NG_TABLE_LAYOUT_NG_TABLE_SECTION_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_TABLE_LAYOUT_NG_TABLE_SECTION_H_
+
+#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/core/layout/layout_block.h"
+#include "third_party/blink/renderer/core/layout/ng/layout_ng_mixin.h"
+#include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_section_interface.h"
+
+namespace blink {
+
+// NOTE:
+// Every child of LayoutNGTableSection must be LayoutNGTableRow.
+class CORE_EXPORT LayoutNGTableSection : public LayoutNGMixin<LayoutBlock>,
+ public LayoutNGTableSectionInterface {
+ public:
+ explicit LayoutNGTableSection(Element*);
+
+ bool IsEmpty() const;
+
+ // LayoutBlock methods start.
+
+ void UpdateBlockLayout(bool relayout_children) override { NOTREACHED(); }
+
+ const char* GetName() const override { return "LayoutNGTableSection"; }
+
+ bool AllowsOverflowClip() const override { return false; }
+
+ bool BackgroundIsKnownToBeOpaqueInRect(const PhysicalRect&) const override {
+ return false;
+ }
+
+ // LayoutBlock methods end.
+
+ // LayoutNGTableSectionInterface methods start.
+
+ const LayoutTableSection* ToLayoutTableSection() const final {
+ DCHECK(false);
+ return nullptr;
+ }
+ const LayoutNGTableSectionInterface* ToLayoutNGTableSectionInterface()
+ const final {
+ return this;
+ }
+ LayoutNGTableSectionInterface* ToLayoutNGTableSectionInterface() {
+ return this;
+ }
+ const LayoutObject* ToLayoutObject() const final { return this; }
+
+ LayoutObject* ToMutableLayoutObject() final { return this; }
+
+ LayoutNGTableInterface* TableInterface() const final;
+
+ void SetNeedsCellRecalc() final;
+
+ bool IsRepeatingHeaderGroup() const final {
+ // Used in printing, not used in LayoutNG
+ return false;
+ }
+
+ bool IsRepeatingFooterGroup() const final {
+ // Used in printing, not used in LayoutNG
+ return false;
+ }
+
+ unsigned NumRows() const final;
+
+ unsigned NumCols(unsigned) const final;
+
+ unsigned NumEffectiveColumns() const final;
+
+ LayoutNGTableRowInterface* FirstRowInterface() const final;
+
+ LayoutNGTableRowInterface* LastRowInterface() const final;
+
+ // Called by ax_layout_object.cc.
+ const LayoutNGTableCellInterface* PrimaryCellInterfaceAt(
+ unsigned row,
+ unsigned column) const final;
+
+ // LayoutNGTableSectionInterface methods end.
+
+ protected:
+ bool IsOfType(LayoutObjectType type) const override {
+ return type == kLayoutObjectTableSection ||
+ LayoutNGMixin<LayoutBlock>::IsOfType(type);
+ }
+};
+
+// wtf/casting.h helper.
+template <>
+struct DowncastTraits<LayoutNGTableSection> {
+ static bool AllowFrom(const LayoutObject& object) {
+ return object.IsTableSection() && object.IsLayoutNGObject();
+ }
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_TABLE_LAYOUT_NG_TABLE_SECTION_H_
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_section_interface.h b/chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_section_interface.h
index 341a3f2a2f1..823dd88eed6 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_section_interface.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_section_interface.h
@@ -22,8 +22,12 @@ class LayoutNGTableSectionInterface {
virtual const LayoutObject* ToLayoutObject() const = 0;
virtual LayoutObject* ToMutableLayoutObject() = 0;
virtual LayoutNGTableInterface* TableInterface() const = 0;
+ // TODO(crbug.com/1081425) Existing methods can be used by NG, should be
+ // removed. Single caller is MarkBoxForRelayoutAfterSplit.
virtual void SetNeedsCellRecalc() = 0;
+ // TODO(crbug.com/1081425) Method not used by NG, should be removed.
virtual bool IsRepeatingHeaderGroup() const = 0;
+ // TODO(crbug.com/1081425) Method not used by NG, should be removed.
virtual bool IsRepeatingFooterGroup() const = 0;
virtual unsigned NumRows() const = 0;
virtual unsigned NumCols(unsigned row) const = 0;
diff --git a/chromium/third_party/blink/renderer/core/layout/scroll_anchor.cc b/chromium/third_party/blink/renderer/core/layout/scroll_anchor.cc
index d796a7f10bb..3cc716658b7 100644
--- a/chromium/third_party/blink/renderer/core/layout/scroll_anchor.cc
+++ b/chromium/third_party/blink/renderer/core/layout/scroll_anchor.cc
@@ -315,7 +315,11 @@ ScrollAnchor::ExamineResult ScrollAnchor::Examine(
void ScrollAnchor::FindAnchor() {
TRACE_EVENT0("blink", "ScrollAnchor::findAnchor");
SCOPED_BLINK_UMA_HISTOGRAM_TIMER("Layout.ScrollAnchor.TimeToFindAnchor");
- FindAnchorRecursive(ScrollerLayoutBox(scroller_));
+
+ bool found_priority_anchor = FindAnchorInPriorityCandidates();
+ if (!found_priority_anchor)
+ FindAnchorRecursive(ScrollerLayoutBox(scroller_));
+
if (anchor_object_) {
anchor_object_->SetIsScrollAnchorObject();
saved_relative_offset_ =
@@ -323,6 +327,65 @@ void ScrollAnchor::FindAnchor() {
}
}
+bool ScrollAnchor::FindAnchorInPriorityCandidates() {
+ auto* scroller_box = ScrollerLayoutBox(scroller_);
+ if (!scroller_box)
+ return false;
+
+ auto& document = scroller_box->GetDocument();
+
+ // Focused area.
+ LayoutObject* candidate =
+ PriorityCandidateFromNode(document.FocusedElement());
+ auto result = ExaminePriorityCandidate(candidate);
+ if (result.viable) {
+ anchor_object_ = candidate;
+ corner_ = result.corner;
+ return true;
+ }
+
+ // Active find-in-page match.
+ candidate =
+ PriorityCandidateFromNode(document.GetFindInPageActiveMatchNode());
+ result = ExaminePriorityCandidate(candidate);
+ if (result.viable) {
+ anchor_object_ = candidate;
+ corner_ = result.corner;
+ return true;
+ }
+ return false;
+}
+
+LayoutObject* ScrollAnchor::PriorityCandidateFromNode(const Node* node) const {
+ while (node) {
+ if (auto* layout_object = node->GetLayoutObject()) {
+ if (!layout_object->IsAnonymous() &&
+ (!layout_object->IsInline() ||
+ layout_object->IsAtomicInlineLevel())) {
+ return layout_object;
+ }
+ }
+ node = FlatTreeTraversal::Parent(*node);
+ }
+ return nullptr;
+}
+
+ScrollAnchor::ExamineResult ScrollAnchor::ExaminePriorityCandidate(
+ const LayoutObject* candidate) const {
+ auto* ancestor = candidate;
+ auto* scroller_box = ScrollerLayoutBox(scroller_);
+ while (ancestor && ancestor != scroller_box) {
+ if (ancestor->StyleRef().OverflowAnchor() == EOverflowAnchor::kNone)
+ return ExamineResult(kSkip);
+
+ if (!CandidateMayMoveWithScroller(ancestor, scroller_))
+ return ExamineResult(kSkip);
+
+ ancestor = ancestor->Parent();
+ }
+ return ancestor ? Examine(candidate) : ExamineResult(kSkip);
+}
+
bool ScrollAnchor::FindAnchorRecursive(LayoutObject* candidate) {
ExamineResult result = Examine(candidate);
if (result.viable) {
diff --git a/chromium/third_party/blink/renderer/core/layout/scroll_anchor.h b/chromium/third_party/blink/renderer/core/layout/scroll_anchor.h
index c637c9c9e20..463b1749bfe 100644
--- a/chromium/third_party/blink/renderer/core/layout/scroll_anchor.h
+++ b/chromium/third_party/blink/renderer/core/layout/scroll_anchor.h
@@ -116,6 +116,14 @@ class CORE_EXPORT ScrollAnchor final {
bool FindAnchorRecursive(LayoutObject*);
bool ComputeScrollAnchorDisablingStyleChanged();
+ // Find viable anchor among the priority candidates. Returns true if anchor
+ // has been found; returns false if anchor was not found, and we should look
+ // for an anchor in the DOM order traversal.
+ bool FindAnchorInPriorityCandidates();
+ // Returns a closest ancestor layout object from the given node which isn't a
+ // non-atomic inline and is not anonymous.
+ LayoutObject* PriorityCandidateFromNode(const Node*) const;
+
enum WalkStatus { kSkip = 0, kConstrain, kContinue, kReturn };
struct ExamineResult {
ExamineResult(WalkStatus s)
@@ -130,6 +138,11 @@ class CORE_EXPORT ScrollAnchor final {
};
ExamineResult Examine(const LayoutObject*) const;
+ // Examines a given priority candidate. Note that this is similar to Examine()
+ // but it also checks that the given object is a descendant of the scroller
+ // and that there is no object that has overflow-anchor: none between the
+ // given object and the scroller.
+ ExamineResult ExaminePriorityCandidate(const LayoutObject*) const;
IntSize ComputeAdjustment() const;
diff --git a/chromium/third_party/blink/renderer/core/layout/scroll_anchor_test.cc b/chromium/third_party/blink/renderer/core/layout/scroll_anchor_test.cc
index e14100e6593..02472dc4cc3 100644
--- a/chromium/third_party/blink/renderer/core/layout/scroll_anchor_test.cc
+++ b/chromium/third_party/blink/renderer/core/layout/scroll_anchor_test.cc
@@ -7,8 +7,12 @@
#include "build/build_config.h"
#include "third_party/blink/public/common/input/web_mouse_event.h"
#include "third_party/blink/renderer/core/dom/static_node_list.h"
+#include "third_party/blink/renderer/core/editing/finder/text_finder.h"
+#include "third_party/blink/renderer/core/frame/find_in_page.h"
+#include "third_party/blink/renderer/core/frame/frame_test_helpers.h"
#include "third_party/blink/renderer/core/frame/root_frame_viewport.h"
#include "third_party/blink/renderer/core/frame/visual_viewport.h"
+#include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
#include "third_party/blink/renderer/core/geometry/dom_rect.h"
#include "third_party/blink/renderer/core/layout/layout_box.h"
#include "third_party/blink/renderer/core/page/print_context.h"
@@ -17,6 +21,7 @@
#include "third_party/blink/renderer/core/testing/core_unit_test_helper.h"
#include "third_party/blink/renderer/platform/testing/histogram_tester.h"
#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
+#include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
namespace blink {
@@ -101,7 +106,7 @@ class ScrollAnchorTest : public testing::WithParamInterface<bool>,
->ConvertFromScrollbarToContainingEmbeddedContentView(
*scrollbar, IntPoint(0, thumb_center)));
scrollbar->MouseDown(blink::WebMouseEvent(
- blink::WebInputEvent::kMouseDown, *scrollbar_drag_point_,
+ blink::WebInputEvent::Type::kMouseDown, *scrollbar_drag_point_,
*scrollbar_drag_point_, blink::WebPointerProperties::Button::kLeft, 0,
blink::WebInputEvent::kNoModifiers, base::TimeTicks::Now()));
}
@@ -116,7 +121,7 @@ class ScrollAnchorTest : public testing::WithParamInterface<bool>,
(scroller->MaximumScrollOffset().Height() -
scroller->MinimumScrollOffset().Height()));
scrollbar->MouseMoved(blink::WebMouseEvent(
- blink::WebInputEvent::kMouseMove, *scrollbar_drag_point_,
+ blink::WebInputEvent::Type::kMouseMove, *scrollbar_drag_point_,
*scrollbar_drag_point_, blink::WebPointerProperties::Button::kLeft, 0,
blink::WebInputEvent::kNoModifiers, base::TimeTicks::Now()));
}
@@ -124,7 +129,7 @@ class ScrollAnchorTest : public testing::WithParamInterface<bool>,
void MouseUpOnVerticalScrollbar(Scrollbar* scrollbar) {
DCHECK(scrollbar_drag_point_);
scrollbar->MouseDown(blink::WebMouseEvent(
- blink::WebInputEvent::kMouseUp, *scrollbar_drag_point_,
+ blink::WebInputEvent::Type::kMouseUp, *scrollbar_drag_point_,
*scrollbar_drag_point_, blink::WebPointerProperties::Button::kLeft, 0,
blink::WebInputEvent::kNoModifiers, base::TimeTicks::Now()));
scrollbar_drag_point_.reset();
@@ -1066,4 +1071,233 @@ TEST_P(ScrollAnchorTest, ClampAdjustsAnchorAnimation) {
->GetScrollAnimator()
.ImplOnlyAnimationAdjustmentForTesting());
}
+
+class ScrollAnchorTestFindInPageClient : public mojom::blink::FindInPageClient {
+ public:
+ ~ScrollAnchorTestFindInPageClient() override = default;
+
+ void SetFrame(WebLocalFrameImpl* frame) {
+ frame->GetFindInPage()->SetClient(receiver_.BindNewPipeAndPassRemote());
+ }
+
+ void SetNumberOfMatches(
+ int request_id,
+ unsigned int current_number_of_matches,
+ mojom::blink::FindMatchUpdateType final_update) final {
+ count_ = current_number_of_matches;
+ }
+
+ void SetActiveMatch(int request_id,
+ const gfx::Rect& active_match_rect,
+ int active_match_ordinal,
+ mojom::blink::FindMatchUpdateType final_update) final {}
+
+ int Count() const { return count_; }
+ void Reset() { count_ = -1; }
+
+ private:
+ int count_ = -1;
+ mojo::Receiver<mojom::blink::FindInPageClient> receiver_{this};
+};
+
+class ScrollAnchorFindInPageTest : public testing::Test {
+ public:
+ void SetUp() override { web_view_helper_.Initialize(); }
+ void TearDown() override { web_view_helper_.Reset(); }
+
+ Document& GetDocument() {
+ return *static_cast<Document*>(
+ web_view_helper_.LocalMainFrame()->GetDocument());
+ }
+ FindInPage* GetFindInPage() {
+ return web_view_helper_.LocalMainFrame()->GetFindInPage();
+ }
+ WebLocalFrameImpl* LocalMainFrame() {
+ return web_view_helper_.LocalMainFrame();
+ }
+
+ void UpdateAllLifecyclePhasesForTest() {
+ GetDocument().View()->UpdateAllLifecyclePhases(DocumentUpdateReason::kTest);
+ }
+
+ void SetHtmlInnerHTML(const char* content) {
+ GetDocument().documentElement()->setInnerHTML(String::FromUTF8(content));
+ UpdateAllLifecyclePhasesForTest();
+ }
+
+ void ResizeAndFocus() {
+ web_view_helper_.Resize(WebSize(640, 480));
+ web_view_helper_.GetWebView()->MainFrameWidget()->SetFocus(true);
+ test::RunPendingTasks();
+ }
+
+ mojom::blink::FindOptionsPtr FindOptions(bool find_next = false) {
+ auto find_options = mojom::blink::FindOptions::New();
+ find_options->run_synchronously_for_testing = true;
+ find_options->find_next = find_next;
+ find_options->forward = true;
+ return find_options;
+ }
+
+ void Find(String search_text,
+ ScrollAnchorTestFindInPageClient& client,
+ bool find_next = false) {
+ client.Reset();
+ GetFindInPage()->Find(FAKE_FIND_ID, search_text, FindOptions(find_next));
+ test::RunPendingTasks();
+ }
+
+ ScrollableArea* LayoutViewport() {
+ return GetDocument().View()->LayoutViewport();
+ }
+
+ const int FAKE_FIND_ID = 1;
+
+ private:
+ frame_test_helpers::WebViewHelper web_view_helper_;
+};
+
+TEST_F(ScrollAnchorFindInPageTest, FindInPageResultPrioritized) {
+ ResizeAndFocus();
+ SetHtmlInnerHTML(R"HTML(
+ <style>
+ body { height: 4000px }
+ .spacer { height: 100px }
+ #growing { height: 100px }
+ </style>
+
+ <div class=spacer></div>
+ <div class=spacer></div>
+ <div class=spacer></div>
+ <div class=spacer></div>
+ <div id=growing></div>
+ <div class=spacer></div>
+ <div id=target>findme</div>
+ <div class=spacer></div>
+ <div class=spacer></div>
+ )HTML");
+
+ LayoutViewport()->SetScrollOffset(ScrollOffset(0, 150),
+ mojom::blink::ScrollType::kUser);
+
+ const String search_text = "findme";
+ ScrollAnchorTestFindInPageClient client;
+ client.SetFrame(LocalMainFrame());
+ Find(search_text, client);
+ ASSERT_EQ(1, client.Count());
+
+ // Save the old bounds for comparison.
+ auto* old_bounds =
+ GetDocument().getElementById("target")->getBoundingClientRect();
+
+ GetDocument().getElementById("growing")->setAttribute(html_names::kStyleAttr,
+ "height: 3000px");
+ UpdateAllLifecyclePhasesForTest();
+
+ auto* new_bounds =
+ GetDocument().getElementById("target")->getBoundingClientRect();
+
+ // The y coordinate of the target should not change.
+ EXPECT_EQ(old_bounds->y(), new_bounds->y());
+}
+
+TEST_F(ScrollAnchorFindInPageTest, FocusPrioritizedOverFindInPage) {
+ ResizeAndFocus();
+ SetHtmlInnerHTML(R"HTML(
+ <style>
+ body { height: 4000px }
+ .spacer { height: 100px }
+ #growing { height: 100px }
+ #focus_target { height: 10px }
+ </style>
+
+ <div class=spacer></div>
+ <div class=spacer></div>
+ <div class=spacer></div>
+ <div class=spacer></div>
+ <div id=focus_target tabindex=0></div>
+ <div id=growing></div>
+ <div id=find_target>findme</div>
+ <div class=spacer></div>
+ <div class=spacer></div>
+ )HTML");
+
+ LayoutViewport()->SetScrollOffset(ScrollOffset(0, 150),
+ mojom::blink::ScrollType::kUser);
+
+ const String search_text = "findme";
+ ScrollAnchorTestFindInPageClient client;
+ client.SetFrame(LocalMainFrame());
+ Find(search_text, client);
+ ASSERT_EQ(1, client.Count());
+
+ GetDocument().getElementById("focus_target")->focus();
+
+ // Save the old bounds for comparison.
+ auto* old_focus_bounds =
+ GetDocument().getElementById("focus_target")->getBoundingClientRect();
+ auto* old_find_bounds =
+ GetDocument().getElementById("find_target")->getBoundingClientRect();
+
+ GetDocument().getElementById("growing")->setAttribute(html_names::kStyleAttr,
+ "height: 3000px");
+ UpdateAllLifecyclePhasesForTest();
+
+ auto* new_focus_bounds =
+ GetDocument().getElementById("focus_target")->getBoundingClientRect();
+ auto* new_find_bounds =
+ GetDocument().getElementById("find_target")->getBoundingClientRect();
+
+ // `focus_target` should remain where it is, since it is prioritized.
+ // `find_target`, however, is shifted.
+ EXPECT_EQ(old_focus_bounds->y(), new_focus_bounds->y());
+ EXPECT_NE(old_find_bounds->y(), new_find_bounds->y());
+}
+
+TEST_F(ScrollAnchorFindInPageTest, FocusedUnderStickyIsSkipped) {
+ ResizeAndFocus();
+ SetHtmlInnerHTML(R"HTML(
+ <style>
+ body { height: 4000px; position: relative; }
+ .spacer { height: 100px }
+ #growing { height: 100px }
+ .sticky { position: sticky; top: 10px; }
+ #target { width: 10px; height: 10px; }
+ </style>
+
+ <div class=spacer></div>
+ <div class=spacer></div>
+ <div class=spacer></div>
+ <div class=spacer></div>
+ <div id=growing></div>
+ <div class=spacer></div>
+ <div id=check></div>
+ <div class=sticky>
+ <div id=target tabindex=0></div>
+ </div>
+ <div class=spacer></div>
+ <div class=spacer></div>
+ )HTML");
+
+ LayoutViewport()->SetScrollOffset(ScrollOffset(0, 150),
+ mojom::blink::ScrollType::kUser);
+
+ GetDocument().getElementById("target")->focus();
+
+ // Save the old bounds for comparison. Use #check, since sticky won't move
+ // regardless of scroll anchoring.
+ auto* old_bounds =
+ GetDocument().getElementById("check")->getBoundingClientRect();
+
+ GetDocument().getElementById("growing")->setAttribute(html_names::kStyleAttr,
+ "height: 3000px");
+ UpdateAllLifecyclePhasesForTest();
+
+ auto* new_bounds =
+ GetDocument().getElementById("check")->getBoundingClientRect();
+
+ // The y coordinate of #check should change since #target is not a valid
+ // anchor, so we should have selected one of the spacers as the anchor.
+ EXPECT_NE(old_bounds->y(), new_bounds->y());
+}
}
diff --git a/chromium/third_party/blink/renderer/core/layout/scrollbars_test.cc b/chromium/third_party/blink/renderer/core/layout/scrollbars_test.cc
index 5ffb764ec5e..455216a3abc 100644
--- a/chromium/third_party/blink/renderer/core/layout/scrollbars_test.cc
+++ b/chromium/third_party/blink/renderer/core/layout/scrollbars_test.cc
@@ -5,8 +5,8 @@
#include "build/build_config.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/features.h"
+#include "third_party/blink/public/common/input/web_coalesced_input_event.h"
#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
-#include "third_party/blink/public/platform/web_coalesced_input_event.h"
#include "third_party/blink/public/platform/web_float_rect.h"
#include "third_party/blink/public/platform/web_theme_engine.h"
#include "third_party/blink/public/web/web_script_source.h"
@@ -31,7 +31,7 @@
#include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
#include "third_party/blink/renderer/platform/testing/url_test_helpers.h"
#include "ui/base/cursor/cursor.h"
-#include "ui/base/mojom/cursor_type.mojom-blink.h"
+#include "ui/base/cursor/mojom/cursor_type.mojom-blink.h"
namespace blink {
@@ -119,7 +119,7 @@ class ScrollbarsTest : public SimTest {
}
HitTestResult HitTest(int x, int y) {
- return WebView().CoreHitTestResultAt(gfx::Point(x, y));
+ return WebView().CoreHitTestResultAt(gfx::PointF(x, y));
}
EventHandler& GetEventHandler() {
@@ -127,7 +127,7 @@ class ScrollbarsTest : public SimTest {
}
void HandleMouseMoveEvent(int x, int y) {
- WebMouseEvent event(WebInputEvent::kMouseMove, gfx::PointF(x, y),
+ WebMouseEvent event(WebInputEvent::Type::kMouseMove, gfx::PointF(x, y),
gfx::PointF(x, y),
WebPointerProperties::Button::kNoButton, 0,
WebInputEvent::kNoModifiers, base::TimeTicks::Now());
@@ -137,7 +137,7 @@ class ScrollbarsTest : public SimTest {
}
void HandleMousePressEvent(int x, int y) {
- WebMouseEvent event(WebInputEvent::kMouseDown, gfx::PointF(x, y),
+ WebMouseEvent event(WebInputEvent::Type::kMouseDown, gfx::PointF(x, y),
gfx::PointF(x, y), WebPointerProperties::Button::kLeft,
0, WebInputEvent::Modifiers::kLeftButtonDown,
base::TimeTicks::Now());
@@ -147,7 +147,7 @@ class ScrollbarsTest : public SimTest {
void HandleContextMenuEvent(int x, int y) {
WebMouseEvent event(
- WebInputEvent::kMouseDown, gfx::PointF(x, y), gfx::PointF(x, y),
+ WebInputEvent::Type::kMouseDown, gfx::PointF(x, y), gfx::PointF(x, y),
WebPointerProperties::Button::kNoButton, 0,
WebInputEvent::Modifiers::kNoModifiers, base::TimeTicks::Now());
event.SetFrameScale(1);
@@ -155,7 +155,7 @@ class ScrollbarsTest : public SimTest {
}
void HandleMouseReleaseEvent(int x, int y) {
- WebMouseEvent event(WebInputEvent::kMouseUp, gfx::PointF(x, y),
+ WebMouseEvent event(WebInputEvent::Type::kMouseUp, gfx::PointF(x, y),
gfx::PointF(x, y), WebPointerProperties::Button::kLeft,
0, WebInputEvent::Modifiers::kNoModifiers,
base::TimeTicks::Now());
@@ -165,7 +165,7 @@ class ScrollbarsTest : public SimTest {
void HandleMouseMiddlePressEvent(int x, int y) {
WebMouseEvent event(
- WebInputEvent::kMouseDown, gfx::PointF(x, y), gfx::PointF(x, y),
+ WebInputEvent::Type::kMouseDown, gfx::PointF(x, y), gfx::PointF(x, y),
WebPointerProperties::Button::kMiddle, 0,
WebInputEvent::Modifiers::kMiddleButtonDown, base::TimeTicks::Now());
event.SetFrameScale(1);
@@ -174,7 +174,7 @@ class ScrollbarsTest : public SimTest {
void HandleMouseMiddleReleaseEvent(int x, int y) {
WebMouseEvent event(
- WebInputEvent::kMouseUp, gfx::PointF(x, y), gfx::PointF(x, y),
+ WebInputEvent::Type::kMouseUp, gfx::PointF(x, y), gfx::PointF(x, y),
WebPointerProperties::Button::kMiddle, 0,
WebInputEvent::Modifiers::kMiddleButtonDown, base::TimeTicks::Now());
event.SetFrameScale(1);
@@ -182,7 +182,7 @@ class ScrollbarsTest : public SimTest {
}
void HandleMouseLeaveEvent() {
- WebMouseEvent event(WebInputEvent::kMouseLeave, gfx::PointF(1, 1),
+ WebMouseEvent event(WebInputEvent::Type::kMouseLeave, gfx::PointF(1, 1),
gfx::PointF(1, 1), WebPointerProperties::Button::kLeft,
0, WebInputEvent::Modifiers::kLeftButtonDown,
base::TimeTicks::Now());
@@ -228,14 +228,14 @@ class ScrollbarsTest : public SimTest {
event.SetPositionInWidget(gfx::PointF(position.X(), position.Y()));
- if (type == WebInputEvent::kGestureScrollUpdate) {
+ if (type == WebInputEvent::Type::kGestureScrollUpdate) {
event.data.scroll_update.delta_x = offset.Width();
event.data.scroll_update.delta_y = offset.Height();
- } else if (type == WebInputEvent::kGestureScrollBegin) {
+ } else if (type == WebInputEvent::Type::kGestureScrollBegin) {
event.data.scroll_begin.delta_x_hint = offset.Width();
event.data.scroll_begin.delta_y_hint = offset.Height();
}
- return WebCoalescedInputEvent(event);
+ return WebCoalescedInputEvent(event, ui::LatencyInfo());
}
private:
@@ -630,7 +630,7 @@ TEST_F(ScrollbarsTest, scrollbarIsNotHandlingTouchpadScroll) {
ToLayoutBox(scrollable->GetLayoutObject())->GetScrollableArea();
DCHECK(scrollable_area->VerticalScrollbar());
WebGestureEvent scroll_begin(
- WebInputEvent::kGestureScrollBegin, WebInputEvent::kNoModifiers,
+ WebInputEvent::Type::kGestureScrollBegin, WebInputEvent::kNoModifiers,
base::TimeTicks::Now(), WebGestureDevice::kTouchpad);
scroll_begin.SetPositionInWidget(
gfx::PointF(scrollable->OffsetLeft() + scrollable->OffsetWidth() - 2,
@@ -1616,8 +1616,11 @@ TEST_P(ScrollbarAppearanceTest, NativeScrollbarChangeToMobileByEmulator) {
height: 2000px;
}
</style>
- <div id='d1'>
- <div id='d2'/>
+ <!-- flex creates DelayScrollOffsetClampScope to increase test coverge -->
+ <div style='display: flex'>
+ <div id='d1'>
+ <div id='d2'/>
+ </div>
</div>
)HTML");
@@ -2347,7 +2350,7 @@ TEST_F(ScrollbarsTest, MiddleDownShouldNotAffectScrollbarPress) {
EXPECT_EQ(scrollbar->PressedPart(), ScrollbarPart::kThumbPart);
// Move mouse out of scrollbar with press.
- WebMouseEvent event(WebInputEvent::kMouseMove, gfx::PointF(5, 5),
+ WebMouseEvent event(WebInputEvent::Type::kMouseMove, gfx::PointF(5, 5),
gfx::PointF(5, 5), WebPointerProperties::Button::kLeft, 0,
WebInputEvent::Modifiers::kLeftButtonDown,
base::TimeTicks::Now());
@@ -2394,13 +2397,13 @@ TEST_F(ScrollbarsTest, UseCounterNegativeWhenThumbIsNotScrolledWithMouse) {
// Scrolling the page with a mouse wheel won't trigger the UseCounter.
WebView().MainFrameWidget()->HandleInputEvent(
- GenerateWheelGestureEvent(WebInputEvent::kGestureScrollBegin,
+ GenerateWheelGestureEvent(WebInputEvent::Type::kGestureScrollBegin,
IntPoint(100, 100), ScrollOffset(0, -100)));
WebView().MainFrameWidget()->HandleInputEvent(
- GenerateWheelGestureEvent(WebInputEvent::kGestureScrollUpdate,
+ GenerateWheelGestureEvent(WebInputEvent::Type::kGestureScrollUpdate,
IntPoint(100, 100), ScrollOffset(0, -100)));
WebView().MainFrameWidget()->HandleInputEvent(GenerateWheelGestureEvent(
- WebInputEvent::kGestureScrollEnd, IntPoint(100, 100)));
+ WebInputEvent::Type::kGestureScrollEnd, IntPoint(100, 100)));
EXPECT_FALSE(GetDocument().IsUseCounted(
WebFeature::kVerticalScrollbarThumbScrollingWithMouse));
@@ -2518,39 +2521,39 @@ TEST_F(ScrollbarsTest, UseCounterNegativeWhenThumbIsNotScrolledWithTouch) {
// Tapping on the vertical scrollbar won't trigger the UseCounter.
WebView().MainFrameWidget()->HandleInputEvent(GenerateTouchGestureEvent(
- WebInputEvent::kGestureTapDown, IntPoint(195, 175)));
+ WebInputEvent::Type::kGestureTapDown, IntPoint(195, 175)));
EXPECT_EQ(vertical_scrollbar->PressedPart(),
ScrollbarPart::kForwardTrackPart);
WebView().MainFrameWidget()->HandleInputEvent(GenerateTouchGestureEvent(
- WebInputEvent::kGestureTapCancel, IntPoint(195, 175)));
+ WebInputEvent::Type::kGestureTapCancel, IntPoint(195, 175)));
EXPECT_FALSE(GetDocument().IsUseCounted(
WebFeature::kVerticalScrollbarThumbScrollingWithTouch));
// Tapping on the horizontal scrollbar won't trigger the UseCounter.
WebView().MainFrameWidget()->HandleInputEvent(GenerateTouchGestureEvent(
- WebInputEvent::kGestureTapDown, IntPoint(175, 195)));
+ WebInputEvent::Type::kGestureTapDown, IntPoint(175, 195)));
EXPECT_EQ(horizontal_scrollbar->PressedPart(),
ScrollbarPart::kForwardTrackPart);
WebView().MainFrameWidget()->HandleInputEvent(GenerateTouchGestureEvent(
- WebInputEvent::kGestureTapCancel, IntPoint(175, 195)));
+ WebInputEvent::Type::kGestureTapCancel, IntPoint(175, 195)));
EXPECT_FALSE(GetDocument().IsUseCounted(
WebFeature::kHorizontalScrollbarThumbScrollingWithTouch));
// Tapping outside the scrollbar and then releasing over the thumb of the
// vertical scrollbar won't trigger the UseCounter.
WebView().MainFrameWidget()->HandleInputEvent(GenerateTouchGestureEvent(
- WebInputEvent::kGestureTapDown, IntPoint(50, 50)));
+ WebInputEvent::Type::kGestureTapDown, IntPoint(50, 50)));
WebView().MainFrameWidget()->HandleInputEvent(GenerateTouchGestureEvent(
- WebInputEvent::kGestureTapCancel, IntPoint(195, 5)));
+ WebInputEvent::Type::kGestureTapCancel, IntPoint(195, 5)));
EXPECT_FALSE(GetDocument().IsUseCounted(
WebFeature::kVerticalScrollbarThumbScrollingWithTouch));
// Tapping outside the scrollbar and then releasing over the thumb of the
// horizontal scrollbar won't trigger the UseCounter.
WebView().MainFrameWidget()->HandleInputEvent(GenerateTouchGestureEvent(
- WebInputEvent::kGestureTapDown, IntPoint(50, 50)));
+ WebInputEvent::Type::kGestureTapDown, IntPoint(50, 50)));
WebView().MainFrameWidget()->HandleInputEvent(GenerateTouchGestureEvent(
- WebInputEvent::kGestureTapCancel, IntPoint(5, 195)));
+ WebInputEvent::Type::kGestureTapCancel, IntPoint(5, 195)));
EXPECT_FALSE(GetDocument().IsUseCounted(
WebFeature::kHorizontalScrollbarThumbScrollingWithTouch));
}
@@ -2584,23 +2587,65 @@ TEST_F(ScrollbarsTest, UseCounterPositiveWhenThumbIsScrolledWithTouch) {
// Clicking the thumb on the vertical scrollbar will trigger the UseCounter.
WebView().MainFrameWidget()->HandleInputEvent(GenerateTouchGestureEvent(
- WebInputEvent::kGestureTapDown, IntPoint(195, 5)));
+ WebInputEvent::Type::kGestureTapDown, IntPoint(195, 5)));
EXPECT_EQ(vertical_scrollbar->PressedPart(), ScrollbarPart::kThumbPart);
WebView().MainFrameWidget()->HandleInputEvent(GenerateTouchGestureEvent(
- WebInputEvent::kGestureTapCancel, IntPoint(195, 5)));
+ WebInputEvent::Type::kGestureTapCancel, IntPoint(195, 5)));
EXPECT_TRUE(GetDocument().IsUseCounted(
WebFeature::kVerticalScrollbarThumbScrollingWithTouch));
// Clicking the thumb on the horizontal scrollbar will trigger the UseCounter.
WebView().MainFrameWidget()->HandleInputEvent(GenerateTouchGestureEvent(
- WebInputEvent::kGestureTapDown, IntPoint(5, 195)));
+ WebInputEvent::Type::kGestureTapDown, IntPoint(5, 195)));
EXPECT_EQ(horizontal_scrollbar->PressedPart(), ScrollbarPart::kThumbPart);
WebView().MainFrameWidget()->HandleInputEvent(GenerateTouchGestureEvent(
- WebInputEvent::kGestureTapCancel, IntPoint(5, 195)));
+ WebInputEvent::Type::kGestureTapCancel, IntPoint(5, 195)));
EXPECT_TRUE(GetDocument().IsUseCounted(
WebFeature::kHorizontalScrollbarThumbScrollingWithTouch));
}
+TEST_F(ScrollbarsTest, UseCounterCustomScrollbarPercentSize) {
+ WebView().MainFrameWidget()->Resize(WebSize(200, 200));
+ SimRequest request("https://example.com/test.html", "text/html");
+ LoadURL("https://example.com/test.html");
+ request.Complete(R"HTML(
+ <!DOCTYPE html>
+ <style>
+ ::-webkit-scrollbar { width: 10px; height: 10%; }
+ ::-webkit-scrollbar-thumb { min-width: 10%; min-height: 10px; }
+ </style>
+ <div id="target" style="width: 100px; height: 100px; overflow: auto">
+ <div id="child" style="width: 50px; height: 50px"></div>
+ </div>
+ )HTML");
+ Compositor().BeginFrame();
+
+ // No scrollbars initially.
+ EXPECT_FALSE(
+ GetDocument().IsUseCounted(WebFeature::kCustomScrollbarPercentThickness));
+ EXPECT_FALSE(GetDocument().IsUseCounted(
+ WebFeature::kCustomScrollbarPartPercentLength));
+
+ // Show vertical scrollbar which uses fixed lengths for thickness
+ // (width: 10px) and thumb minimum length (min-height: 10px).
+ auto* child = GetDocument().getElementById("child");
+ child->setAttribute(html_names::kStyleAttr, "width: 50px; height: 200px");
+ Compositor().BeginFrame();
+ EXPECT_FALSE(
+ GetDocument().IsUseCounted(WebFeature::kCustomScrollbarPercentThickness));
+ EXPECT_FALSE(GetDocument().IsUseCounted(
+ WebFeature::kCustomScrollbarPartPercentLength));
+
+ // Show horizontal scrollbar which uses percent lengths for thickness
+ // (height: 10%) and thumb minimum length (min-width: 10%).
+ child->setAttribute(html_names::kStyleAttr, "width: 200px; height: 50px");
+ Compositor().BeginFrame();
+ EXPECT_TRUE(
+ GetDocument().IsUseCounted(WebFeature::kCustomScrollbarPercentThickness));
+ EXPECT_TRUE(GetDocument().IsUseCounted(
+ WebFeature::kCustomScrollbarPartPercentLength));
+}
+
TEST_F(ScrollbarsTest, CheckScrollCornerIfThereIsNoScrollbar) {
// This test is specifically checking the behavior when overlay scrollbars
// are enabled.
diff --git a/chromium/third_party/blink/renderer/core/layout/subtree_layout_scope.cc b/chromium/third_party/blink/renderer/core/layout/subtree_layout_scope.cc
index 91cfa08a58c..c4db18ac217 100644
--- a/chromium/third_party/blink/renderer/core/layout/subtree_layout_scope.cc
+++ b/chromium/third_party/blink/renderer/core/layout/subtree_layout_scope.cc
@@ -30,6 +30,7 @@
#include "third_party/blink/renderer/core/layout/subtree_layout_scope.h"
+#include "third_party/blink/renderer/core/display_lock/display_lock_utilities.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
#include "third_party/blink/renderer/core/layout/layout_object.h"
@@ -46,8 +47,17 @@ SubtreeLayoutScope::~SubtreeLayoutScope() {
DisplayLockLifecycleTarget::kChildren));
#if DCHECK_IS_ON()
- for (auto* layout_object : layout_objects_to_layout_)
- layout_object->AssertLaidOut();
+ for (auto* layout_object : layout_objects_to_layout_) {
+ // There are situations where the object to layout was never laid out, such
+ // as if there was a display-locked descendant of the root and ancestor of
+ // the object which prevented layout. This can happen in quirks mode, where
+ // an ancestor can mark a descendant as dirty through its
+ // PercentHeightDescendants() list, which will not get cleared because
+ // traversal is blocked by a display lock. This finds such cases and allows
+ // these objects to be dirty.
+ if (!DisplayLockUtilities::LockedAncestorPreventingLayout(*layout_object))
+ layout_object->AssertLaidOut();
+ }
#endif
}
diff --git a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_container.cc b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_container.cc
index da375b67877..9ce624f2957 100644
--- a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_container.cc
+++ b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_container.cc
@@ -49,7 +49,11 @@ void LayoutSVGContainer::UpdateLayout() {
LayoutAnalyzer::Scope analyzer(*this);
// Update the local transform in subclasses.
- SVGTransformChange transform_change = CalculateLocalTransform();
+ // At this point our bounding box may be incorrect, so any box relative
+ // transforms will be incorrect. Since descendants only require the scaling
+ // components to be correct, this should be fine. We update the transform
+ // again, if needed, after computing the bounding box below.
+ SVGTransformChange transform_change = CalculateLocalTransform(false);
did_screen_scale_factor_change_ =
transform_change == SVGTransformChange::kFull ||
SVGLayoutSupport::ScreenScaleFactorChanged(Parent());
@@ -71,6 +75,7 @@ void LayoutSVGContainer::UpdateLayout() {
if (needs_boundaries_update_ ||
transform_change != SVGTransformChange::kNone) {
UpdateCachedBoundaries();
+ CalculateLocalTransform(needs_boundaries_update_);
needs_boundaries_update_ = false;
// If our bounds changed, notify the parents.
@@ -212,7 +217,8 @@ bool LayoutSVGContainer::NodeAtPoint(HitTestResult& result,
return false;
}
-SVGTransformChange LayoutSVGContainer::CalculateLocalTransform() {
+SVGTransformChange LayoutSVGContainer::CalculateLocalTransform(
+ bool bounds_changed) {
return SVGTransformChange::kNone;
}
diff --git a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_container.h b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_container.h
index c0ec38b1592..d68caa64171 100644
--- a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_container.h
+++ b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_container.h
@@ -89,7 +89,7 @@ class LayoutSVGContainer : public LayoutSVGModelObject {
HitTestAction) override;
// Called during layout to update the local transform.
- virtual SVGTransformChange CalculateLocalTransform();
+ virtual SVGTransformChange CalculateLocalTransform(bool bounds_changed);
void UpdateCachedBoundaries();
diff --git a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_rect.cc b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_rect.cc
index f65bb230fa5..c264b972386 100644
--- a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_rect.cc
+++ b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_rect.cc
@@ -74,6 +74,9 @@ void LayoutSVGRect::UpdateShapeFromElement() {
}
}
+ if (!use_path_fallback_)
+ ClearPath();
+
fill_bounding_box_ = FloatRect(
length_context.ResolveLengthPair(svg_style.X(), svg_style.Y(), style),
bounding_box_size);
diff --git a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_resource_container.cc b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_resource_container.cc
index da7fd935d74..de5ed70a011 100644
--- a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_resource_container.cc
+++ b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_resource_container.cc
@@ -97,7 +97,7 @@ bool LayoutSVGResourceContainer::FindCycle(
bool LayoutSVGResourceContainer::FindCycleInResources(
SVGResourcesCycleSolver& solver,
- const LayoutObject& layout_object) const {
+ const LayoutObject& layout_object) {
SVGResources* resources =
SVGResourcesCache::CachedResourcesForLayoutObject(layout_object);
if (!resources)
@@ -116,28 +116,35 @@ bool LayoutSVGResourceContainer::FindCycleInResources(
bool LayoutSVGResourceContainer::FindCycleFromSelf(
SVGResourcesCycleSolver& solver) const {
- if (FindCycleInResources(solver, *this))
- return true;
- return FindCycleInDescendants(solver);
+ return FindCycleInSubtree(solver, *this);
}
bool LayoutSVGResourceContainer::FindCycleInDescendants(
- SVGResourcesCycleSolver& solver) const {
- LayoutObject* node = FirstChild();
+ SVGResourcesCycleSolver& solver,
+ const LayoutObject& root) {
+ LayoutObject* node = root.SlowFirstChild();
while (node) {
// Skip subtrees which are themselves resources. (They will be
// processed - if needed - when they are actually referenced.)
if (node->IsSVGResourceContainer()) {
- node = node->NextInPreOrderAfterChildren(this);
+ node = node->NextInPreOrderAfterChildren(&root);
continue;
}
if (FindCycleInResources(solver, *node))
return true;
- node = node->NextInPreOrder(this);
+ node = node->NextInPreOrder(&root);
}
return false;
}
+bool LayoutSVGResourceContainer::FindCycleInSubtree(
+ SVGResourcesCycleSolver& solver,
+ const LayoutObject& root) {
+ if (FindCycleInResources(solver, root))
+ return true;
+ return FindCycleInDescendants(solver, root);
+}
+
void LayoutSVGResourceContainer::MarkAllClientsForInvalidation(
InvalidationModeMask invalidation_mask) {
if (is_invalidating_)
diff --git a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_resource_container.h b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_resource_container.h
index 9e5ef616025..6874d6e97fc 100644
--- a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_resource_container.h
+++ b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_resource_container.h
@@ -81,10 +81,13 @@ class LayoutSVGResourceContainer : public LayoutSVGHiddenContainer {
// Used from RemoveAllClientsFromCache methods.
void MarkAllClientsForInvalidation(InvalidationModeMask);
- bool FindCycleFromSelf(SVGResourcesCycleSolver&) const;
- bool FindCycleInDescendants(SVGResourcesCycleSolver&) const;
- bool FindCycleInResources(SVGResourcesCycleSolver&,
- const LayoutObject&) const;
+ virtual bool FindCycleFromSelf(SVGResourcesCycleSolver&) const;
+ static bool FindCycleInDescendants(SVGResourcesCycleSolver&,
+ const LayoutObject& root);
+ static bool FindCycleInResources(SVGResourcesCycleSolver&,
+ const LayoutObject& object);
+ static bool FindCycleInSubtree(SVGResourcesCycleSolver&,
+ const LayoutObject& root);
void StyleDidChange(StyleDifference, const ComputedStyle* old_style) override;
void WillBeDestroyed() override;
diff --git a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_resource_filter.cc b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_resource_filter.cc
index 09784e4b5e8..f275e5646e8 100644
--- a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_resource_filter.cc
+++ b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_resource_filter.cc
@@ -23,6 +23,8 @@
#include "third_party/blink/renderer/core/layout/svg/layout_svg_resource_filter.h"
+#include "third_party/blink/renderer/core/dom/element_traversal.h"
+#include "third_party/blink/renderer/core/svg/svg_fe_image_element.h"
#include "third_party/blink/renderer/core/svg/svg_filter_element.h"
namespace blink {
@@ -63,6 +65,23 @@ SVGUnitTypes::SVGUnitType LayoutSVGResourceFilter::PrimitiveUnits() const {
->EnumValue();
}
+bool LayoutSVGResourceFilter::FindCycleFromSelf(
+ SVGResourcesCycleSolver& solver) const {
+ // Traverse and check all <feImage> 'href' element references.
+ for (auto& feimage_element :
+ Traversal<SVGFEImageElement>::ChildrenOf(*GetElement())) {
+ const SVGElement* target = feimage_element.TargetElement();
+ if (!target)
+ continue;
+ const LayoutObject* target_layout_object = target->GetLayoutObject();
+ if (!target_layout_object)
+ continue;
+ if (FindCycleInSubtree(solver, *target_layout_object))
+ return true;
+ }
+ return false;
+}
+
LayoutSVGResourceFilter* GetFilterResourceForSVG(const ComputedStyle& style) {
if (!style.HasFilter())
return nullptr;
diff --git a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_resource_filter.h b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_resource_filter.h
index e1584b2f26c..467c1935989 100644
--- a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_resource_filter.h
+++ b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_resource_filter.h
@@ -49,6 +49,9 @@ class LayoutSVGResourceFilter final : public LayoutSVGResourceContainer {
static const LayoutSVGResourceType kResourceType = kFilterResourceType;
LayoutSVGResourceType ResourceType() const override { return kResourceType; }
+
+ private:
+ bool FindCycleFromSelf(SVGResourcesCycleSolver&) const override;
};
// Get the LayoutSVGResourceFilter from the 'filter' property iff the 'filter'
diff --git a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_resource_marker.cc b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_resource_marker.cc
index 491b18a5c92..9b7c605caa0 100644
--- a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_resource_marker.cc
+++ b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_resource_marker.cc
@@ -138,7 +138,8 @@ void LayoutSVGResourceMarker::SetNeedsTransformUpdate() {
needs_transform_update_ = true;
}
-SVGTransformChange LayoutSVGResourceMarker::CalculateLocalTransform() {
+SVGTransformChange LayoutSVGResourceMarker::CalculateLocalTransform(
+ bool bounds_changed) {
if (!needs_transform_update_)
return SVGTransformChange::kNone;
diff --git a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_resource_marker.h b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_resource_marker.h
index 58a23afc549..eadd407e7d5 100644
--- a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_resource_marker.h
+++ b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_resource_marker.h
@@ -65,7 +65,7 @@ class LayoutSVGResourceMarker final : public LayoutSVGResourceContainer {
private:
void UpdateLayout() override;
- SVGTransformChange CalculateLocalTransform() final;
+ SVGTransformChange CalculateLocalTransform(bool bounds_changed) final;
AffineTransform local_to_parent_transform_;
FloatSize viewport_size_;
diff --git a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_root.cc b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_root.cc
index 551f84f910c..d38f416ffc2 100644
--- a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_root.cc
+++ b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_root.cc
@@ -135,7 +135,11 @@ LayoutUnit LayoutSVGRoot::ComputeReplacedLogicalWidth(
if (IsEmbeddedThroughFrameContainingSVGDocument())
return ContainingBlock()->AvailableLogicalWidth();
- return LayoutReplaced::ComputeReplacedLogicalWidth(should_compute_preferred);
+ LayoutUnit width =
+ LayoutReplaced::ComputeReplacedLogicalWidth(should_compute_preferred);
+ if (StyleRef().LogicalWidth().IsPercentOrCalc())
+ width *= LogicalSizeScaleFactorForPercentageLengths();
+ return width;
}
LayoutUnit LayoutSVGRoot::ComputeReplacedLogicalHeight(
@@ -152,14 +156,29 @@ LayoutUnit LayoutSVGRoot::ComputeReplacedLogicalHeight(
const Length& logical_height = StyleRef().LogicalHeight();
if (IsDocumentElement() && logical_height.IsPercentOrCalc()) {
- return ValueForLength(
+ LayoutUnit height = ValueForLength(
logical_height,
GetDocument().GetLayoutView()->ViewLogicalHeightForPercentages());
+ height *= LogicalSizeScaleFactorForPercentageLengths();
+ return height;
}
return LayoutReplaced::ComputeReplacedLogicalHeight(estimated_used_width);
}
+double LayoutSVGRoot::LogicalSizeScaleFactorForPercentageLengths() const {
+ if (!IsDocumentElement() || !GetDocument().IsInMainFrame())
+ return 1;
+ if (GetDocument().GetLayoutView()->ShouldUsePrintingLayout())
+ return 1;
+ // This will return the zoom factor which is different from the typical usage
+ // of "zoom factor" in blink (e.g., |LocalFrame::PageZoomFactor()|) which
+ // includes CSS zoom and the device scale factor (if use-zoom-for-dsf is
+ // enabled). For this special-case, we only want to include the user's zoom
+ // factor, as all other types of zoom should not scale a percentage-sized svg.
+ return GetFrame()->GetChromeClient().UserZoomFactor();
+}
+
void LayoutSVGRoot::UpdateLayout() {
DCHECK(NeedsLayout());
LayoutAnalyzer::Scope analyzer(*this);
diff --git a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_root.h b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_root.h
index 4bba76f4efb..959fd1c6ac7 100644
--- a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_root.h
+++ b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_root.h
@@ -161,6 +161,10 @@ class CORE_EXPORT LayoutSVGRoot final : public LayoutReplaced {
PositionWithAffinity PositionForPoint(const PhysicalOffset&) const final;
+ // This is a special case for SVG documents with percentage dimensions which
+ // would normally not change under zoom. See: https://crbug.com/222786.
+ double LogicalSizeScaleFactorForPercentageLengths() const;
+
LayoutObjectChildList children_;
LayoutSize container_size_;
FloatRect object_bounding_box_;
diff --git a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_shape.cc b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_shape.cc
index 66bff8d5bd1..ca7059737f1 100644
--- a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_shape.cc
+++ b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_shape.cc
@@ -69,6 +69,19 @@ void LayoutSVGShape::StyleDidChange(StyleDifference diff,
TransformHelper::DependsOnReferenceBox(StyleRef());
LayoutSVGModelObject::StyleDidChange(diff, old_style);
SVGResources::UpdatePaints(*GetElement(), old_style, StyleRef());
+
+ // Most of the stroke attributes (caps, joins, miters, width, etc.) will cause
+ // a re-layout which will clear the stroke-path cache; however, there are a
+ // couple of additional properties that *won't* cause a layout, but are
+ // significant enough to require invalidating the cache.
+ if (!diff.NeedsFullLayout() && old_style && stroke_path_cache_) {
+ const auto& old_svg_style = old_style->SvgStyle();
+ const auto& svg_style = StyleRef().SvgStyle();
+ if (old_svg_style.StrokeDashOffset() != svg_style.StrokeDashOffset() ||
+ *old_svg_style.StrokeDashArray() != *svg_style.StrokeDashArray()) {
+ stroke_path_cache_.reset();
+ }
+ }
}
void LayoutSVGShape::WillBeDestroyed() {
@@ -76,10 +89,20 @@ void LayoutSVGShape::WillBeDestroyed() {
LayoutSVGModelObject::WillBeDestroyed();
}
+void LayoutSVGShape::ClearPath() {
+ path_.reset();
+ stroke_path_cache_.reset();
+}
+
void LayoutSVGShape::CreatePath() {
if (!path_)
path_ = std::make_unique<Path>();
*path_ = To<SVGGeometryElement>(GetElement())->AsPath();
+
+ // When the path changes, we need to ensure the stale stroke path cache is
+ // cleared. Because this is done in all callsites, we can just DCHECK that it
+ // has been cleared here.
+ DCHECK(!stroke_path_cache_);
}
float LayoutSVGShape::DashScaleFactor() const {
@@ -150,24 +173,40 @@ FloatRect LayoutSVGShape::HitTestStrokeBoundingBox() const {
bool LayoutSVGShape::ShapeDependentStrokeContains(
const HitTestLocation& location) {
- // In case the subclass didn't create path during UpdateShapeFromElement()
- // for optimization but still calls this method.
- if (!HasPath())
- CreatePath();
-
- StrokeData stroke_data;
- SVGLayoutSupport::ApplyStrokeStyleToStrokeData(stroke_data, StyleRef(), *this,
- DashScaleFactor());
-
- if (HasNonScalingStroke()) {
- // The reason is similar to the above code about HasPath().
- if (!rare_data_)
- UpdateNonScalingStrokeData();
- return NonScalingStrokePath().StrokeContains(
- NonScalingStrokeTransform().MapPoint(location.TransformedPoint()),
- stroke_data);
+ if (!stroke_path_cache_) {
+ // In case the subclass didn't create path during UpdateShapeFromElement()
+ // for optimization but still calls this method.
+ if (!HasPath())
+ CreatePath();
+
+ StrokeData stroke_data;
+ SVGLayoutSupport::ApplyStrokeStyleToStrokeData(stroke_data, StyleRef(),
+ *this, DashScaleFactor());
+
+ if (HasNonScalingStroke()) {
+ // The reason is similar to the above code about HasPath().
+ if (!rare_data_)
+ UpdateNonScalingStrokeData();
+
+ // Un-scale to get back to the root-transform (cheaper than re-computing
+ // the root transform from scratch).
+ AffineTransform root_transform;
+ root_transform.Scale(StyleRef().EffectiveZoom())
+ .Multiply(NonScalingStrokeTransform());
+
+ stroke_path_cache_ = std::make_unique<Path>(
+ NonScalingStrokePath().StrokePath(stroke_data, root_transform));
+ } else {
+ stroke_path_cache_ = std::make_unique<Path>(
+ path_->StrokePath(stroke_data, ComputeRootTransform()));
+ }
}
- return path_->StrokeContains(location.TransformedPoint(), stroke_data);
+
+ DCHECK(stroke_path_cache_);
+ auto point = location.TransformedPoint();
+ if (HasNonScalingStroke())
+ point = NonScalingStrokeTransform().MapPoint(point);
+ return stroke_path_cache_->Contains(point);
}
bool LayoutSVGShape::ShapeDependentFillContains(
@@ -217,6 +256,10 @@ void LayoutSVGShape::UpdateLayout() {
if (EverHadLayout() && SelfNeedsLayout())
SVGResourcesCache::ClientLayoutChanged(*this);
+ // The cached stroke may be affected by the ancestor transform, and so needs
+ // to be cleared regardless of whether the shape or bounds have changed.
+ stroke_path_cache_.reset();
+
bool update_parent_boundaries = false;
bool bbox_changed = false;
// UpdateShapeFromElement() also updates the object & stroke bounds - which
@@ -264,19 +307,23 @@ void LayoutSVGShape::UpdateLayout() {
ClearNeedsLayout();
}
+AffineTransform LayoutSVGShape::ComputeRootTransform() const {
+ const LayoutObject* root = this;
+ while (root && !root->IsSVGRoot())
+ root = root->Parent();
+ return LocalToAncestorTransform(ToLayoutSVGRoot(root)).ToAffineTransform();
+}
+
AffineTransform LayoutSVGShape::ComputeNonScalingStrokeTransform() const {
// Compute the CTM to the SVG root. This should probably be the CTM all the
// way to the "canvas" of the page ("host" coordinate system), but with our
// current approach of applying/painting non-scaling-stroke, that can break in
// unpleasant ways (see crbug.com/747708 for an example.) Maybe it would be
// better to apply this effect during rasterization?
- const LayoutObject* root = this;
- while (root && !root->IsSVGRoot())
- root = root->Parent();
AffineTransform host_transform;
host_transform.Scale(1 / StyleRef().EffectiveZoom())
- .Multiply(
- LocalToAncestorTransform(ToLayoutSVGRoot(root)).ToAffineTransform());
+ .Multiply(ComputeRootTransform());
+
// Width of non-scaling stroke is independent of translation, so zero it out
// here.
host_transform.SetE(0);
diff --git a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_shape.h b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_shape.h
index 803a52ec322..34f2f4ac0f3 100644
--- a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_shape.h
+++ b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_shape.h
@@ -93,6 +93,7 @@ class LayoutSVGShape : public LayoutSVGModelObject {
return rare_data_->non_scaling_stroke_transform_;
}
+ AffineTransform ComputeRootTransform() const;
AffineTransform ComputeNonScalingStrokeTransform() const;
AffineTransform LocalSVGTransform() const final { return local_transform_; }
@@ -131,7 +132,7 @@ class LayoutSVGShape : public LayoutSVGModelObject {
float VisualRectOutsetForRasterEffects() const override;
- void ClearPath() { path_.reset(); }
+ void ClearPath();
void CreatePath();
// Update (cached) shape data and the (object) bounding box.
@@ -189,6 +190,7 @@ class LayoutSVGShape : public LayoutSVGModelObject {
// into removing it.
std::unique_ptr<Path> path_;
mutable std::unique_ptr<LayoutSVGShapeRareData> rare_data_;
+ std::unique_ptr<Path> stroke_path_cache_;
StrokeGeometryClass geometry_class_;
bool needs_boundaries_update_ : 1;
diff --git a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_transformable_container.cc b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_transformable_container.cc
index 1e83a75dfbc..5569cbfe4bd 100644
--- a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_transformable_container.cc
+++ b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_transformable_container.cc
@@ -30,7 +30,9 @@ namespace blink {
LayoutSVGTransformableContainer::LayoutSVGTransformableContainer(
SVGGraphicsElement* node)
- : LayoutSVGContainer(node), needs_transform_update_(true) {}
+ : LayoutSVGContainer(node),
+ needs_transform_update_(true),
+ transform_uses_reference_box_(false) {}
static bool HasValidPredecessor(const Node* node) {
DCHECK(node);
@@ -85,7 +87,8 @@ bool LayoutSVGTransformableContainer::IsUseElement() const {
return false;
}
-SVGTransformChange LayoutSVGTransformableContainer::CalculateLocalTransform() {
+SVGTransformChange LayoutSVGTransformableContainer::CalculateLocalTransform(
+ bool bounds_changed) {
SVGElement* element = GetElement();
DCHECK(element);
@@ -105,6 +108,11 @@ SVGTransformChange LayoutSVGTransformableContainer::CalculateLocalTransform() {
additional_translation_ = translation;
}
+ if (!needs_transform_update_ && transform_uses_reference_box_) {
+ if (CheckForImplicitTransformChange(bounds_changed))
+ SetNeedsTransformUpdate();
+ }
+
if (!needs_transform_update_)
return SVGTransformChange::kNone;
@@ -117,4 +125,12 @@ SVGTransformChange LayoutSVGTransformableContainer::CalculateLocalTransform() {
return change_detector.ComputeChange(local_transform_);
}
+void LayoutSVGTransformableContainer::StyleDidChange(
+ StyleDifference diff,
+ const ComputedStyle* old_style) {
+ transform_uses_reference_box_ =
+ TransformHelper::DependsOnReferenceBox(StyleRef());
+ LayoutSVGContainer::StyleDidChange(diff, old_style);
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_transformable_container.h b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_transformable_container.h
index 1513a48c4b8..347cf8b385c 100644
--- a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_transformable_container.h
+++ b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_transformable_container.h
@@ -44,13 +44,15 @@ class LayoutSVGTransformableContainer final : public LayoutSVGContainer {
void SetNeedsTransformUpdate() override;
private:
- SVGTransformChange CalculateLocalTransform() override;
+ void StyleDidChange(StyleDifference, const ComputedStyle* old_style) override;
+ SVGTransformChange CalculateLocalTransform(bool bounds_changed) override;
AffineTransform LocalSVGTransform() const override {
return local_transform_;
}
bool IsUseElement() const;
bool needs_transform_update_ : 1;
+ bool transform_uses_reference_box_ : 1;
AffineTransform local_transform_;
FloatSize additional_translation_;
};
diff --git a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_viewport_container.cc b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_viewport_container.cc
index a5b2cd54337..5edcbbaa50b 100644
--- a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_viewport_container.cc
+++ b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_viewport_container.cc
@@ -63,7 +63,8 @@ void LayoutSVGViewportContainer::SetNeedsTransformUpdate() {
needs_transform_update_ = true;
}
-SVGTransformChange LayoutSVGViewportContainer::CalculateLocalTransform() {
+SVGTransformChange LayoutSVGViewportContainer::CalculateLocalTransform(
+ bool bounds_changed) {
if (!needs_transform_update_)
return SVGTransformChange::kNone;
diff --git a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_viewport_container.h b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_viewport_container.h
index c7a32b46865..9835f9be113 100644
--- a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_viewport_container.h
+++ b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_viewport_container.h
@@ -54,7 +54,7 @@ class LayoutSVGViewportContainer final : public LayoutSVGContainer {
void UpdateLayout() override;
- SVGTransformChange CalculateLocalTransform() override;
+ SVGTransformChange CalculateLocalTransform(bool bounds_changed) override;
bool NodeAtPoint(HitTestResult&,
const HitTestLocation&,
diff --git a/chromium/third_party/blink/renderer/core/layout/svg/svg_resources.cc b/chromium/third_party/blink/renderer/core/layout/svg/svg_resources.cc
index 4d1cc23961b..fd553642211 100644
--- a/chromium/third_party/blink/renderer/core/layout/svg/svg_resources.cc
+++ b/chromium/third_party/blink/renderer/core/layout/svg/svg_resources.cc
@@ -29,6 +29,7 @@
#include "third_party/blink/renderer/core/layout/svg/layout_svg_resource_paint_server.h"
#include "third_party/blink/renderer/core/layout/svg/layout_svg_text.h"
#include "third_party/blink/renderer/core/layout/svg/svg_resources_cache.h"
+#include "third_party/blink/renderer/core/paint/filter_effect_builder.h"
#include "third_party/blink/renderer/core/style/computed_style.h"
#include "third_party/blink/renderer/core/style/reference_clip_path_operation.h"
#include "third_party/blink/renderer/core/style/style_svg_resource.h"
@@ -598,14 +599,20 @@ void SVGResources::ClearClipPathFilterMask(SVGElement& element,
const ComputedStyle* style) {
if (!style)
return;
- SVGResourceClient* client = element.GetSVGResourceClient();
+ SVGElementResourceClient* client = element.GetSVGResourceClient();
if (!client)
return;
if (auto* old_reference_clip =
DynamicTo<ReferenceClipPathOperation>(style->ClipPath()))
old_reference_clip->RemoveClient(*client);
- if (style->HasFilter())
+ if (style->HasFilter()) {
style->Filter().RemoveClient(*client);
+ if (client->ClearFilterData()) {
+ LayoutObject* layout_object = element.GetLayoutObject();
+ LayoutSVGResourceContainer::MarkClientForInvalidation(
+ *layout_object, SVGResourceClient::kPaintInvalidation);
+ }
+ }
if (StyleSVGResource* masker_resource = style->SvgStyle().MaskerResource())
masker_resource->RemoveClient(*client);
}
@@ -799,8 +806,33 @@ void SVGElementResourceClient::FilterPrimitiveChanged(
*layout_object, SVGResourceClient::kPaintInvalidation);
}
-void SVGElementResourceClient::SetFilterData(FilterData* filter_data) {
- filter_data_ = filter_data;
+FilterData* SVGElementResourceClient::UpdateFilterData() {
+ DCHECK(element_->GetLayoutObject());
+ if (filter_data_) {
+ // If the filterData already exists we do not need to record the
+ // content to be filtered. This can occur if the content was
+ // previously recorded or we are in a cycle.
+ filter_data_->UpdateStateOnPrepare();
+ return filter_data_;
+ }
+ const LayoutObject& object = *element_->GetLayoutObject();
+ const ComputedStyle& style = object.StyleRef();
+ // Caller should make sure this holds.
+ DCHECK(GetFilterResourceForSVG(style));
+
+ auto* node_map = MakeGarbageCollected<SVGFilterGraphNodeMap>();
+ FilterEffectBuilder builder(SVGResources::ReferenceBoxForEffects(object), 1);
+ Filter* filter = builder.BuildReferenceFilter(
+ To<ReferenceFilterOperation>(*style.Filter().at(0)), nullptr, node_map);
+ if (!filter || !filter->LastEffect())
+ return nullptr;
+
+ IntRect source_region = EnclosingIntRect(object.StrokeBoundingBox());
+ filter->GetSourceGraphic()->SetSourceRect(source_region);
+
+ filter_data_ =
+ MakeGarbageCollected<FilterData>(filter->LastEffect(), node_map);
+ return filter_data_;
}
bool SVGElementResourceClient::ClearFilterData() {
diff --git a/chromium/third_party/blink/renderer/core/layout/svg/svg_resources.h b/chromium/third_party/blink/renderer/core/layout/svg/svg_resources.h
index 96db2ccc575..7507e78f3fe 100644
--- a/chromium/third_party/blink/renderer/core/layout/svg/svg_resources.h
+++ b/chromium/third_party/blink/renderer/core/layout/svg/svg_resources.h
@@ -253,9 +253,8 @@ class SVGElementResourceClient final
void FilterPrimitiveChanged(SVGFilterPrimitiveStandardAttributes& primitive,
const QualifiedName& attribute) override;
- void SetFilterData(FilterData*);
+ FilterData* UpdateFilterData();
bool ClearFilterData();
- FilterData* GetFilterData() const { return filter_data_; }
void Trace(Visitor*) override;
diff --git a/chromium/third_party/blink/renderer/core/layout/text_decoration_offset_base.cc b/chromium/third_party/blink/renderer/core/layout/text_decoration_offset_base.cc
index 8d7a67a4f97..ae99892548b 100644
--- a/chromium/third_party/blink/renderer/core/layout/text_decoration_offset_base.cc
+++ b/chromium/third_party/blink/renderer/core/layout/text_decoration_offset_base.cc
@@ -5,34 +5,43 @@
#include "third_party/blink/renderer/core/layout/text_decoration_offset_base.h"
#include <algorithm>
+
+#include <base/optional.h>
+
#include "third_party/blink/renderer/core/paint/decoration_info.h"
#include "third_party/blink/renderer/platform/fonts/font_metrics.h"
#include "third_party/blink/renderer/platform/fonts/font_vertical_position_type.h"
+#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
-namespace blink {
+namespace {
-int TextDecorationOffsetBase::ComputeUnderlineOffsetForRoman(
- const FontMetrics& font_metrics,
- float text_decoration_thickness) const {
+int ComputeUnderlineOffsetAuto(const blink::FontMetrics& font_metrics,
+ float text_decoration_thickness) {
// Compute the gap between the font and the underline. Use at least one
// pixel gap, if underline is thick then use a bigger gap.
- int gap = 0;
-
// Underline position of zero means draw underline on Baseline Position,
// in Blink we need at least 1-pixel gap to adding following check.
// Positive underline Position means underline should be drawn above baseline
// and negative value means drawing below baseline, negating the value as in
// Blink downward Y-increases.
-
- if (font_metrics.UnderlinePosition())
- gap = -font_metrics.UnderlinePosition();
- else
- gap = std::max<int>(1, ceilf(text_decoration_thickness / 2.f));
+ int gap = std::max<int>(1, ceilf(text_decoration_thickness / 2.f));
// Position underline near the alphabetic baseline.
return font_metrics.Ascent() + gap;
}
+base::Optional<int> ComputeUnderlineOffsetFromFont(
+ const blink::FontMetrics& font_metrics) {
+ if (!font_metrics.UnderlinePosition())
+ return base::nullopt;
+
+ return roundf(font_metrics.FloatAscent() + *font_metrics.UnderlinePosition());
+}
+
+} // namespace
+
+namespace blink {
+
int TextDecorationOffsetBase::ComputeUnderlineOffset(
ResolvedUnderlinePosition underline_position,
const FontMetrics& font_metrics,
@@ -41,9 +50,14 @@ int TextDecorationOffsetBase::ComputeUnderlineOffset(
default:
NOTREACHED();
FALLTHROUGH;
- case ResolvedUnderlinePosition::kRoman:
- return ComputeUnderlineOffsetForRoman(font_metrics,
- text_decoration_thickness);
+ case ResolvedUnderlinePosition::kNearAlphabeticBaselineFromFont:
+ DCHECK(RuntimeEnabledFeatures::UnderlineOffsetThicknessEnabled());
+ return ComputeUnderlineOffsetFromFont(font_metrics)
+ .value_or(ComputeUnderlineOffsetAuto(font_metrics,
+ text_decoration_thickness));
+ case ResolvedUnderlinePosition::kNearAlphabeticBaselineAuto:
+ return ComputeUnderlineOffsetAuto(font_metrics,
+ text_decoration_thickness);
case ResolvedUnderlinePosition::kUnder:
// Position underline at the under edge of the lowest element's
// content box.
diff --git a/chromium/third_party/blink/renderer/core/layout/text_decoration_offset_base.h b/chromium/third_party/blink/renderer/core/layout/text_decoration_offset_base.h
index 3d6f46530c5..05f3528f75c 100644
--- a/chromium/third_party/blink/renderer/core/layout/text_decoration_offset_base.h
+++ b/chromium/third_party/blink/renderer/core/layout/text_decoration_offset_base.h
@@ -27,9 +27,6 @@ class CORE_EXPORT TextDecorationOffsetBase {
float text_decoration_thickness,
FontVerticalPositionType) const = 0;
- int ComputeUnderlineOffsetForRoman(const FontMetrics&,
- float text_decoration_thickness) const;
-
int ComputeUnderlineOffset(ResolvedUnderlinePosition,
const FontMetrics&,
float text_decoration_thickness) const;
diff --git a/chromium/third_party/blink/renderer/core/loader/BUILD.gn b/chromium/third_party/blink/renderer/core/loader/BUILD.gn
index 286d10f505c..4e0a703b636 100644
--- a/chromium/third_party/blink/renderer/core/loader/BUILD.gn
+++ b/chromium/third_party/blink/renderer/core/loader/BUILD.gn
@@ -41,8 +41,6 @@ blink_core_sources("loader") {
"frame_loader_state_machine.cc",
"frame_loader_state_machine.h",
"frame_loader_types.h",
- "frame_or_imported_document.cc",
- "frame_or_imported_document.h",
"frame_resource_fetcher_properties.cc",
"frame_resource_fetcher_properties.h",
"history_item.cc",
@@ -116,8 +114,6 @@ blink_core_sources("loader") {
"progress_tracker.h",
"resource/css_style_sheet_resource.cc",
"resource/css_style_sheet_resource.h",
- "resource/document_resource.cc",
- "resource/document_resource.h",
"resource/font_resource.cc",
"resource/font_resource.h",
"resource/image_resource.cc",
diff --git a/chromium/third_party/blink/renderer/core/loader/DEPS b/chromium/third_party/blink/renderer/core/loader/DEPS
index 528c6cb134d..39227699fb8 100644
--- a/chromium/third_party/blink/renderer/core/loader/DEPS
+++ b/chromium/third_party/blink/renderer/core/loader/DEPS
@@ -1,5 +1,6 @@
specific_include_rules = {
"alternate_signed_exchange_resource_info.cc" : [
+ "+media/media_buildflags.h",
"+net/http/http_request_headers.h"
],
"progress_tracker_test.cc" : [
diff --git a/chromium/third_party/blink/renderer/core/loader/alternate_signed_exchange_resource_info.cc b/chromium/third_party/blink/renderer/core/loader/alternate_signed_exchange_resource_info.cc
index 35ae1b9c22f..071132490ac 100644
--- a/chromium/third_party/blink/renderer/core/loader/alternate_signed_exchange_resource_info.cc
+++ b/chromium/third_party/blink/renderer/core/loader/alternate_signed_exchange_resource_info.cc
@@ -4,7 +4,9 @@
#include "third_party/blink/renderer/core/loader/alternate_signed_exchange_resource_info.h"
+#include "media/media_buildflags.h"
#include "net/http/http_request_headers.h"
+#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/common/web_package/signed_exchange_consts.h"
#include "third_party/blink/public/common/web_package/web_package_request_matcher.h"
#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h"
@@ -28,7 +30,20 @@ constexpr char kAllowedAltSxg[] = "allowed-alt-sxg";
// TODO(horo): Move somewhere and use shared constant value.
const char kDefaultAcceptHeader[] = "*/*";
const char kStylesheetAcceptHeader[] = "text/css,*/*;q=0.1";
-const char kImageAcceptHeader[] = "image/webp,image/apng,image/*,*/*;q=0.8";
+
+const char* ImageAcceptHeader() {
+ static constexpr char kImageAcceptHeaderWithAvif[] =
+ "image/avif,image/webp,image/apng,image/*,*/*;q=0.8";
+ static constexpr size_t kOffset = sizeof("image/avif,") - 1;
+#if BUILDFLAG(ENABLE_AV1_DECODER)
+ static const char* header = base::FeatureList::IsEnabled(features::kAVIF)
+ ? kImageAcceptHeaderWithAvif
+ : kImageAcceptHeaderWithAvif + kOffset;
+#else
+ static const char* header = kImageAcceptHeaderWithAvif + kOffset;
+#endif
+ return header;
+}
using AlternateSignedExchangeMachingKey =
std::pair<String /* anchor */,
@@ -133,7 +148,7 @@ AlternateSignedExchangeResourceInfo::FindMatchingEntry(
if (resource_type == ResourceType::kCSSStyleSheet) {
accept_header = kStylesheetAcceptHeader;
} else if (resource_type == ResourceType::kImage) {
- accept_header = kImageAcceptHeader;
+ accept_header = ImageAcceptHeader();
}
return FindMatchingEntry(url, accept_header, languages);
}
@@ -147,7 +162,7 @@ AlternateSignedExchangeResourceInfo::FindMatchingEntry(
if (request_context == mojom::RequestContextType::STYLE) {
accept_header = kStylesheetAcceptHeader;
} else if (request_context == mojom::RequestContextType::IMAGE) {
- accept_header = kImageAcceptHeader;
+ accept_header = ImageAcceptHeader();
}
return FindMatchingEntry(url, accept_header, languages);
}
diff --git a/chromium/third_party/blink/renderer/core/loader/appcache/application_cache.cc b/chromium/third_party/blink/renderer/core/loader/appcache/application_cache.cc
index f554a26f1f6..0e6a546ccbd 100644
--- a/chromium/third_party/blink/renderer/core/loader/appcache/application_cache.cc
+++ b/chromium/third_party/blink/renderer/core/loader/appcache/application_cache.cc
@@ -30,6 +30,7 @@
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/events/event_listener.h"
#include "third_party/blink/renderer/core/frame/deprecation.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/loader/appcache/application_cache_host_for_frame.h"
#include "third_party/blink/renderer/core/loader/document_loader.h"
@@ -39,9 +40,9 @@
namespace blink {
-ApplicationCache::ApplicationCache(LocalFrame* frame) : DOMWindowClient(frame) {
- DCHECK(RuntimeEnabledFeatures::AppCacheEnabled(
- frame->GetDocument()->ToExecutionContext()));
+ApplicationCache::ApplicationCache(LocalFrame* frame)
+ : ExecutionContextClient(frame) {
+ DCHECK(RuntimeEnabledFeatures::AppCacheEnabled(frame->DomWindow()));
ApplicationCacheHostForFrame* cache_host = GetApplicationCacheHost();
if (cache_host)
cache_host->SetApplicationCache(this);
@@ -49,7 +50,7 @@ ApplicationCache::ApplicationCache(LocalFrame* frame) : DOMWindowClient(frame) {
void ApplicationCache::Trace(Visitor* visitor) {
EventTargetWithInlineData::Trace(visitor);
- DOMWindowClient::Trace(visitor);
+ ExecutionContextClient::Trace(visitor);
}
ApplicationCacheHostForFrame* ApplicationCache::GetApplicationCacheHost()
@@ -120,7 +121,7 @@ const AtomicString& ApplicationCache::InterfaceName() const {
}
ExecutionContext* ApplicationCache::GetExecutionContext() const {
- return GetFrame() ? GetFrame()->GetDocument()->ToExecutionContext() : nullptr;
+ return GetFrame() ? GetFrame()->DomWindow() : nullptr;
}
const AtomicString& ApplicationCache::ToEventType(mojom::AppCacheEventID id) {
diff --git a/chromium/third_party/blink/renderer/core/loader/appcache/application_cache.h b/chromium/third_party/blink/renderer/core/loader/appcache/application_cache.h
index 002ab6c55ec..65d4777c458 100644
--- a/chromium/third_party/blink/renderer/core/loader/appcache/application_cache.h
+++ b/chromium/third_party/blink/renderer/core/loader/appcache/application_cache.h
@@ -39,7 +39,7 @@ class ExceptionState;
class LocalFrame;
class ApplicationCache final : public EventTargetWithInlineData,
- public DOMWindowClient {
+ public ExecutionContextClient {
DEFINE_WRAPPERTYPEINFO();
USING_GARBAGE_COLLECTED_MIXIN(ApplicationCache);
diff --git a/chromium/third_party/blink/renderer/core/loader/appcache/application_cache_host.cc b/chromium/third_party/blink/renderer/core/loader/appcache/application_cache_host.cc
index 69bc7f24209..5cd4936c13d 100644
--- a/chromium/third_party/blink/renderer/core/loader/appcache/application_cache_host.cc
+++ b/chromium/third_party/blink/renderer/core/loader/appcache/application_cache_host.cc
@@ -63,8 +63,12 @@ const char* const kEventNames[] = {"Checking", "Error", "NoUpdate",
ApplicationCacheHost::ApplicationCacheHost(
const BrowserInterfaceBrokerProxy& interface_broker_proxy,
- scoped_refptr<base::SingleThreadTaskRunner> task_runner)
- : task_runner_(std::move(task_runner)),
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ ContextLifecycleNotifier* notifier)
+ : backend_host_(notifier),
+ receiver_(this, notifier),
+ backend_remote_(notifier),
+ task_runner_(std::move(task_runner)),
interface_broker_proxy_(interface_broker_proxy) {}
ApplicationCacheHost::~ApplicationCacheHost() = default;
@@ -230,6 +234,12 @@ void ApplicationCacheHost::ErrorEventRaised(
}
}
+void ApplicationCacheHost::Trace(Visitor* visitor) {
+ visitor->Trace(backend_host_);
+ visitor->Trace(receiver_);
+ visitor->Trace(backend_remote_);
+}
+
void ApplicationCacheHost::GetAssociatedCacheInfo(
ApplicationCacheHost::CacheInfo* info) {
if (!backend_host_.is_bound())
diff --git a/chromium/third_party/blink/renderer/core/loader/appcache/application_cache_host.h b/chromium/third_party/blink/renderer/core/loader/appcache/application_cache_host.h
index 78e37fc991c..fc578e6c407 100644
--- a/chromium/third_party/blink/renderer/core/loader/appcache/application_cache_host.h
+++ b/chromium/third_party/blink/renderer/core/loader/appcache/application_cache_host.h
@@ -36,15 +36,17 @@
#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
-#include "mojo/public/cpp/bindings/receiver.h"
-#include "mojo/public/cpp/bindings/remote.h"
#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
#include "third_party/blink/public/mojom/appcache/appcache.mojom-blink.h"
#include "third_party/blink/public/mojom/appcache/appcache_info.mojom-blink-forward.h"
#include "third_party/blink/public/mojom/devtools/console_message.mojom-blink-forward.h"
#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/platform/context_lifecycle_notifier.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_response.h"
+#include "third_party/blink/renderer/platform/mojo/heap_mojo_receiver.h"
+#include "third_party/blink/renderer/platform/mojo/heap_mojo_remote.h"
+#include "third_party/blink/renderer/platform/mojo/heap_mojo_wrapper_mode.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
@@ -57,7 +59,8 @@ class CORE_EXPORT ApplicationCacheHost
public:
ApplicationCacheHost(
const BrowserInterfaceBrokerProxy& interface_broker_proxy,
- scoped_refptr<base::SingleThreadTaskRunner> task_runner);
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ ContextLifecycleNotifier* notifier);
~ApplicationCacheHost() override;
virtual void Detach();
@@ -108,10 +111,12 @@ class CORE_EXPORT ApplicationCacheHost
mojo::PendingRemote<network::mojom::blink::URLLoaderFactory>
url_loader_factory) override {}
- virtual void Trace(Visitor*) {}
+ virtual void Trace(Visitor*);
protected:
- mojo::Remote<mojom::blink::AppCacheHost> backend_host_;
+ HeapMojoRemote<mojom::blink::AppCacheHost,
+ HeapMojoWrapperMode::kWithoutContextObserver>
+ backend_host_;
mojom::blink::AppCacheStatus status_ =
mojom::blink::AppCacheStatus::APPCACHE_STATUS_UNCACHED;
@@ -129,8 +134,13 @@ class CORE_EXPORT ApplicationCacheHost
void GetAssociatedCacheInfo(CacheInfo* info);
- mojo::Receiver<mojom::blink::AppCacheFrontend> receiver_{this};
- mojo::Remote<mojom::blink::AppCacheBackend> backend_remote_;
+ HeapMojoReceiver<mojom::blink::AppCacheFrontend,
+ ApplicationCacheHost,
+ HeapMojoWrapperMode::kWithoutContextObserver>
+ receiver_;
+ HeapMojoRemote<mojom::blink::AppCacheBackend,
+ HeapMojoWrapperMode::kWithoutContextObserver>
+ backend_remote_;
base::UnguessableToken host_id_;
mojom::blink::AppCacheInfo cache_info_;
diff --git a/chromium/third_party/blink/renderer/core/loader/appcache/application_cache_host_for_frame.cc b/chromium/third_party/blink/renderer/core/loader/appcache/application_cache_host_for_frame.cc
index 551b8d5f573..c65efa31353 100644
--- a/chromium/third_party/blink/renderer/core/loader/appcache/application_cache_host_for_frame.cc
+++ b/chromium/third_party/blink/renderer/core/loader/appcache/application_cache_host_for_frame.cc
@@ -9,6 +9,7 @@
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/events/application_cache_error_event.h"
#include "third_party/blink/renderer/core/events/progress_event.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame_client.h"
#include "third_party/blink/renderer/core/frame/settings.h"
#include "third_party/blink/renderer/core/inspector/console_message.h"
@@ -47,7 +48,9 @@ ApplicationCacheHostForFrame::ApplicationCacheHostForFrame(
const BrowserInterfaceBrokerProxy& interface_broker_proxy,
scoped_refptr<base::SingleThreadTaskRunner> task_runner,
const base::UnguessableToken& appcache_host_id)
- : ApplicationCacheHost(interface_broker_proxy, std::move(task_runner)),
+ : ApplicationCacheHost(interface_broker_proxy,
+ std::move(task_runner),
+ document_loader->GetFrame()->DomWindow()),
local_frame_(document_loader->GetFrame()),
document_loader_(document_loader) {
// PlzNavigate: The browser passes the ID to be used.
@@ -208,7 +211,7 @@ void ApplicationCacheHostForFrame::SelectCacheWithManifest(
const KURL& manifest_url) {
LocalFrame* frame = document_loader_->GetFrame();
Document* document = frame->GetDocument();
- if (document->IsSandboxed(mojom::blink::WebSandboxFlags::kOrigin)) {
+ if (document->IsSandboxed(network::mojom::blink::WebSandboxFlags::kOrigin)) {
// Prevent sandboxes from establishing application caches.
SelectCacheWithoutManifest();
return;
diff --git a/chromium/third_party/blink/renderer/core/loader/appcache/application_cache_host_for_worker.cc b/chromium/third_party/blink/renderer/core/loader/appcache/application_cache_host_for_worker.cc
index 9cb4e9fea3b..f046a63cf23 100644
--- a/chromium/third_party/blink/renderer/core/loader/appcache/application_cache_host_for_worker.cc
+++ b/chromium/third_party/blink/renderer/core/loader/appcache/application_cache_host_for_worker.cc
@@ -9,8 +9,11 @@ namespace blink {
ApplicationCacheHostForWorker::ApplicationCacheHostForWorker(
const base::UnguessableToken& appcache_host_id,
const BrowserInterfaceBrokerProxy& interface_broker_proxy,
- scoped_refptr<base::SingleThreadTaskRunner> task_runner)
- : ApplicationCacheHost(interface_broker_proxy, std::move(task_runner)) {
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ ContextLifecycleNotifier* notifier)
+ : ApplicationCacheHost(interface_broker_proxy,
+ std::move(task_runner),
+ notifier) {
SetHostID(appcache_host_id ? appcache_host_id
: base::UnguessableToken::Create());
BindBackend();
diff --git a/chromium/third_party/blink/renderer/core/loader/appcache/application_cache_host_for_worker.h b/chromium/third_party/blink/renderer/core/loader/appcache/application_cache_host_for_worker.h
index 5a51ec72a97..ff6327933f2 100644
--- a/chromium/third_party/blink/renderer/core/loader/appcache/application_cache_host_for_worker.h
+++ b/chromium/third_party/blink/renderer/core/loader/appcache/application_cache_host_for_worker.h
@@ -14,7 +14,8 @@ class ApplicationCacheHostForWorker final : public ApplicationCacheHost {
ApplicationCacheHostForWorker(
const base::UnguessableToken& appcache_host_id,
const BrowserInterfaceBrokerProxy& interface_broker_proxy,
- scoped_refptr<base::SingleThreadTaskRunner> task_runner);
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ ContextLifecycleNotifier* notifier);
~ApplicationCacheHostForWorker() override;
};
diff --git a/chromium/third_party/blink/renderer/core/loader/base_fetch_context.cc b/chromium/third_party/blink/renderer/core/loader/base_fetch_context.cc
index 566cf11eab0..1214294c826 100644
--- a/chromium/third_party/blink/renderer/core/loader/base_fetch_context.cc
+++ b/chromium/third_party/blink/renderer/core/loader/base_fetch_context.cc
@@ -45,8 +45,10 @@ base::Optional<ResourceRequestBlockedReason> BaseFetchContext::CanRequest(
return blocked_reason;
}
-bool BaseFetchContext::CalculateIfAdSubresource(const ResourceRequest& request,
- ResourceType type) {
+bool BaseFetchContext::CalculateIfAdSubresource(
+ const ResourceRequest& request,
+ ResourceType type,
+ const FetchInitiatorInfo& initiator_info) {
// A base class should override this is they have more signals than just the
// SubresourceFilter.
SubresourceFilter* filter = GetSubresourceFilter();
@@ -88,18 +90,21 @@ void BaseFetchContext::PrintAccessDeniedMessage(const KURL& url) const {
base::Optional<ResourceRequestBlockedReason>
BaseFetchContext::CheckCSPForRequest(
mojom::RequestContextType request_context,
+ network::mojom::RequestDestination request_destination,
const KURL& url,
const ResourceLoaderOptions& options,
ReportingDisposition reporting_disposition,
ResourceRequest::RedirectStatus redirect_status) const {
return CheckCSPForRequestInternal(
- request_context, url, options, reporting_disposition, redirect_status,
+ request_context, request_destination, url, options, reporting_disposition,
+ redirect_status,
ContentSecurityPolicy::CheckHeaderType::kCheckReportOnly);
}
base::Optional<ResourceRequestBlockedReason>
BaseFetchContext::CheckCSPForRequestInternal(
mojom::RequestContextType request_context,
+ network::mojom::RequestDestination request_destination,
const KURL& url,
const ResourceLoaderOptions& options,
ReportingDisposition reporting_disposition,
@@ -112,10 +117,11 @@ BaseFetchContext::CheckCSPForRequestInternal(
}
const ContentSecurityPolicy* csp = GetContentSecurityPolicy();
- if (csp && !csp->AllowRequest(
- request_context, url, options.content_security_policy_nonce,
- options.integrity_metadata, options.parser_disposition,
- redirect_status, reporting_disposition, check_header_type)) {
+ if (csp && !csp->AllowRequest(request_context, request_destination, url,
+ options.content_security_policy_nonce,
+ options.integrity_metadata,
+ options.parser_disposition, redirect_status,
+ reporting_disposition, check_header_type)) {
return ResourceRequestBlockedReason::kCSP;
}
return base::nullopt;
@@ -179,12 +185,15 @@ BaseFetchContext::CanRequestInternal(
mojom::RequestContextType request_context =
resource_request.GetRequestContext();
+ network::mojom::RequestDestination request_destination =
+ resource_request.GetRequestDestination();
// We check the 'report-only' headers before upgrading the request (in
// populateResourceRequest). We check the enforced headers here to ensure we
// block things we ought to block.
if (CheckCSPForRequestInternal(
- request_context, url, options, reporting_disposition, redirect_status,
+ request_context, request_destination, url, options,
+ reporting_disposition, redirect_status,
ContentSecurityPolicy::CheckHeaderType::kCheckEnforce) ==
ResourceRequestBlockedReason::kCSP) {
return ResourceRequestBlockedReason::kCSP;
@@ -225,10 +234,11 @@ BaseFetchContext::CanRequestInternal(
// Check for mixed content. We do this second-to-last so that when folks block
// mixed content via CSP, they don't get a mixed content warning, but a CSP
// warning instead.
- if (ShouldBlockFetchByMixedContentCheck(request_context,
- resource_request.GetRedirectStatus(),
- url, reporting_disposition))
+ if (ShouldBlockFetchByMixedContentCheck(
+ request_context, resource_request.GetRedirectStatus(), url,
+ reporting_disposition, resource_request.GetDevToolsId())) {
return ResourceRequestBlockedReason::kMixedContent;
+ }
if (url.PotentiallyDanglingMarkup() && url.ProtocolIsInHTTPFamily()) {
CountDeprecation(WebFeature::kCanRequestURLHTTPContainingNewline);
diff --git a/chromium/third_party/blink/renderer/core/loader/base_fetch_context.h b/chromium/third_party/blink/renderer/core/loader/base_fetch_context.h
index 7f6c4db5584..fa5bc0b3ba5 100644
--- a/chromium/third_party/blink/renderer/core/loader/base_fetch_context.h
+++ b/chromium/third_party/blink/renderer/core/loader/base_fetch_context.h
@@ -40,6 +40,7 @@ class CORE_EXPORT BaseFetchContext : public FetchContext {
ResourceRequest::RedirectStatus) const override;
base::Optional<ResourceRequestBlockedReason> CheckCSPForRequest(
mojom::RequestContextType,
+ network::mojom::RequestDestination request_destination,
const KURL&,
const ResourceLoaderOptions&,
ReportingDisposition,
@@ -66,8 +67,10 @@ class CORE_EXPORT BaseFetchContext : public FetchContext {
virtual std::unique_ptr<WebSocketHandshakeThrottle>
CreateWebSocketHandshakeThrottle() = 0;
- bool CalculateIfAdSubresource(const ResourceRequest& resource_request,
- ResourceType type) override;
+ bool CalculateIfAdSubresource(
+ const ResourceRequest& resource_request,
+ ResourceType type,
+ const FetchInitiatorInfo& initiator_info) override;
// Returns whether a request to |url| is a conversion registration request.
// Conversion registration requests are redirects to a well-known conversion
@@ -98,10 +101,11 @@ class CORE_EXPORT BaseFetchContext : public FetchContext {
virtual bool ShouldBypassMainWorldCSP() const = 0;
virtual bool IsSVGImageChromeClient() const = 0;
virtual bool ShouldBlockFetchByMixedContentCheck(
- mojom::RequestContextType,
- ResourceRequest::RedirectStatus,
- const KURL&,
- ReportingDisposition) const = 0;
+ mojom::blink::RequestContextType request_context,
+ ResourceRequest::RedirectStatus redirect_status,
+ const KURL& url,
+ ReportingDisposition reporting_disposition,
+ const base::Optional<String>& devtools_id) const = 0;
virtual bool ShouldBlockFetchAsCredentialedSubresource(const ResourceRequest&,
const KURL&) const = 0;
virtual const KURL& Url() const = 0;
@@ -127,6 +131,7 @@ class CORE_EXPORT BaseFetchContext : public FetchContext {
base::Optional<ResourceRequestBlockedReason> CheckCSPForRequestInternal(
mojom::RequestContextType,
+ network::mojom::RequestDestination request_destination,
const KURL&,
const ResourceLoaderOptions&,
ReportingDisposition,
diff --git a/chromium/third_party/blink/renderer/core/loader/base_fetch_context_test.cc b/chromium/third_party/blink/renderer/core/loader/base_fetch_context_test.cc
index 0a9908bb7f9..84dde4e10b7 100644
--- a/chromium/third_party/blink/renderer/core/loader/base_fetch_context_test.cc
+++ b/chromium/third_party/blink/renderer/core/loader/base_fetch_context_test.cc
@@ -88,7 +88,8 @@ class MockBaseFetchContext final : public BaseFetchContext {
mojom::RequestContextType,
ResourceRequest::RedirectStatus,
const KURL&,
- ReportingDisposition) const override {
+ ReportingDisposition,
+ const base::Optional<String>&) const override {
return false;
}
bool ShouldBlockFetchAsCredentialedSubresource(const ResourceRequest&,
@@ -191,7 +192,8 @@ TEST_F(BaseFetchContextTest, CheckCSPForRequest) {
EXPECT_EQ(base::nullopt,
fetch_context_->CheckCSPForRequest(
- mojom::RequestContextType::SCRIPT, url, options,
+ mojom::RequestContextType::SCRIPT,
+ network::mojom::RequestDestination::kScript, url, options,
ReportingDisposition::kReport,
ResourceRequest::RedirectStatus::kFollowedRedirect));
EXPECT_EQ(1u, policy->violation_reports_sent_.size());
diff --git a/chromium/third_party/blink/renderer/core/loader/cookie_jar.cc b/chromium/third_party/blink/renderer/core/loader/cookie_jar.cc
index ca6b5e62eb1..4593b594587 100644
--- a/chromium/third_party/blink/renderer/core/loader/cookie_jar.cc
+++ b/chromium/third_party/blink/renderer/core/loader/cookie_jar.cc
@@ -11,7 +11,7 @@
namespace blink {
CookieJar::CookieJar(blink::Document* document)
- : backend_(document->ToExecutionContext()), document_(document) {}
+ : backend_(document->GetExecutionContext()), document_(document) {}
CookieJar::~CookieJar() = default;
diff --git a/chromium/third_party/blink/renderer/core/loader/document_loader.cc b/chromium/third_party/blink/renderer/core/loader/document_loader.cc
index 94d7026e591..7faf30225b4 100644
--- a/chromium/third_party/blink/renderer/core/loader/document_loader.cc
+++ b/chromium/third_party/blink/renderer/core/loader/document_loader.cc
@@ -36,7 +36,7 @@
#include "base/metrics/histogram_macros.h"
#include "base/time/default_tick_clock.h"
#include "services/network/public/cpp/features.h"
-#include "third_party/blink/public/common/origin_policy/origin_policy.h"
+#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/mojom/commit_result/commit_result.mojom-blink.h"
#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_network_provider.h"
#include "third_party/blink/public/platform/web_url_request.h"
@@ -80,6 +80,7 @@
#include "third_party/blink/renderer/core/probe/core_probes.h"
#include "third_party/blink/renderer/core/timing/dom_window_performance.h"
#include "third_party/blink/renderer/core/timing/window_performance.h"
+#include "third_party/blink/renderer/core/xml/document_xslt.h"
#include "third_party/blink/renderer/platform/bindings/microtask.h"
#include "third_party/blink/renderer/platform/bindings/script_forbidden_scope.h"
#include "third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h"
@@ -129,7 +130,9 @@ DocumentLoader::DocumentLoader(
service_worker_network_provider_(
std::move(params_->service_worker_network_provider)),
was_blocked_by_document_policy_(false),
- was_blocked_by_csp_(false),
+ content_security_policy_(content_security_policy),
+ // The CSP is null when the CSP check done in the FrameLoader failed.
+ was_blocked_by_csp_(!content_security_policy),
state_(kNotStarted),
in_commit_data_(false),
data_buffer_(SharedBuffer::Create()),
@@ -183,21 +186,6 @@ DocumentLoader::DocumentLoader(
document_policy_ = CreateDocumentPolicy();
- // If the document is blocked by document policy, there won't be content
- // in the sub-frametree, thus no need to initialize required_policy for
- // subtree.
- if (!was_blocked_by_document_policy_) {
- // Require-Document-Policy header only affects subtree of current document,
- // but not the current document.
- const DocumentPolicy::FeatureState header_required_policy =
- DocumentPolicyParser::Parse(
- response_.HttpHeaderField(http_names::kRequireDocumentPolicy))
- .value_or(DocumentPolicy::ParsedDocumentPolicy{})
- .feature_state;
- frame_->SetRequiredDocumentPolicy(DocumentPolicy::MergeFeatureState(
- frame_policy_.required_document_policy, header_required_policy));
- }
-
WebNavigationTimings& timings = params_->navigation_timings;
if (!timings.input_start.is_null())
document_load_timing_.SetInputStart(timings.input_start);
@@ -239,27 +227,20 @@ DocumentLoader::DocumentLoader(
loading_url_as_empty_document_ =
!params_->is_static_data && WillLoadUrlAsEmpty(url_);
- if (!loading_url_as_empty_document_) {
- content_security_policy_ = content_security_policy;
-
- // The CSP are null when the CSP check done in the FrameLoader failed.
- if (!content_security_policy_) {
- // Loading the document was blocked by the CSP check. Pretend that
- // this was an empty document instead and don't reuse the
- // original URL (https://crbug.com/622385).
- // TODO(mkwst): Remove this once XFO moves to the browser.
- // https://crbug.com/555418.
-
- // Update |origin_to_commit_| to contain an opaque origin with precursor
- // information that is consistent with the final request URL.
- // Note: We can't use |url_| for the origin calculation because
- // we need to take into account any redirects that may have occurred.
- const auto request_url_origin =
- blink::SecurityOrigin::Create(response_.CurrentRequestUrl());
- origin_to_commit_ = request_url_origin->DeriveNewOpaqueOrigin();
-
- was_blocked_by_csp_ = true;
- }
+ if (was_blocked_by_csp_) {
+ // Loading the document was blocked by the CSP check. Pretend that this was
+ // an empty document instead and don't reuse the original URL. More details
+ // in: https://crbug.com/622385.
+ // TODO(https://crbug.com/555418) Remove this once XFO moves to the browser.
+
+ // Update |origin_to_commit_| to contain an opaque origin with precursor
+ // information that is consistent with the final request URL.
+ // Note: this doesn't use |url_| for the origin calculation, because
+ // redirects are not yet accounted for (this happens later in
+ // StartLoadingInternal).
+ const auto request_url_origin =
+ blink::SecurityOrigin::Create(response_.CurrentRequestUrl());
+ origin_to_commit_ = request_url_origin->DeriveNewOpaqueOrigin();
}
if (was_blocked_by_csp_ || was_blocked_by_document_policy_)
@@ -652,6 +633,9 @@ void DocumentLoader::BodyLoadingFinished(
completion_time, total_encoded_data_length, total_decoded_body_length,
should_report_corb_blocking);
if (response_.IsHTTP()) {
+ // The response is being copied here to pass the Encoded and Decoded
+ // sizes.
+ // TODO(yoav): copy the sizes info directly.
navigation_timing_info_->SetFinalResponse(response_);
navigation_timing_info_->AddFinalTransferSize(
total_encoded_data_length == -1 ? 0 : total_encoded_data_length);
@@ -714,7 +698,7 @@ void DocumentLoader::FinishedLoading(base::TimeTicks finish_time) {
body_loader_.reset();
virtual_time_pauser_.UnpauseVirtualTime();
- DCHECK(frame_->Loader().StateMachine()->CreatingInitialEmptyDocument() ||
+ DCHECK(commit_reason_ == CommitReason::kInitialization ||
!frame_->GetPage()->Paused() ||
MainThreadDebugger::Instance()->IsPaused());
@@ -842,22 +826,53 @@ DocumentPolicy::ParsedDocumentPolicy DocumentLoader::CreateDocumentPolicy() {
url_.ProtocolIs("blob") || url_.ProtocolIs("filesystem"))
return {frame_policy_.required_document_policy, {} /* endpoint_map */};
- // Assume Document policy feature is enabled so we can check the
- // Required- headers. Will re-validate when we install the new Document.
- const auto parsed_policy =
+ PolicyParserMessageBuffer header_logger("Document-Policy HTTP header: ");
+ PolicyParserMessageBuffer require_header_logger(
+ "Require-Document-Policy HTTP header: ");
+
+ // Filtering out features that are disabled by origin trial is done
+ // in SecurityContextInit when origin trial context is available.
+ auto parsed_policy =
DocumentPolicyParser::Parse(
- response_.HttpHeaderField(http_names::kDocumentPolicy))
+ response_.HttpHeaderField(http_names::kDocumentPolicy), header_logger)
.value_or(DocumentPolicy::ParsedDocumentPolicy{});
+ // |parsed_policy| can have policies that are disabled by origin trial,
+ // but |frame_policy_.required_document_policy| cannot.
+ // It is safe to call |IsPolicyCompatible| as long as required policy is
+ // checked against origin trial.
if (!DocumentPolicy::IsPolicyCompatible(
frame_policy_.required_document_policy,
parsed_policy.feature_state)) {
was_blocked_by_document_policy_ = true;
// When header policy is less strict than required policy, use required
// policy to initialize document policy for the document.
- return {frame_policy_.required_document_policy, {} /* endpoint_map */};
+ parsed_policy = {frame_policy_.required_document_policy,
+ {} /* endpoint_map */};
}
+ // Initialize required document policy for subtree.
+ //
+ // If the document is blocked by document policy, there won't be content
+ // in the sub-frametree, thus no need to initialize required_policy for
+ // subtree.
+ if (!was_blocked_by_document_policy_) {
+ // Require-Document-Policy header only affects subtree of current document,
+ // but not the current document.
+ const DocumentPolicy::FeatureState header_required_policy =
+ DocumentPolicyParser::Parse(
+ response_.HttpHeaderField(http_names::kRequireDocumentPolicy),
+ require_header_logger)
+ .value_or(DocumentPolicy::ParsedDocumentPolicy{})
+ .feature_state;
+ frame_->SetRequiredDocumentPolicy(DocumentPolicy::MergeFeatureState(
+ frame_policy_.required_document_policy, header_required_policy));
+ }
+
+ document_policy_parsing_messages_.AppendVector(header_logger.GetMessages());
+ document_policy_parsing_messages_.AppendVector(
+ require_header_logger.GetMessages());
+
return parsed_policy;
}
@@ -897,7 +912,7 @@ void DocumentLoader::CommitNavigation() {
// TODO(dcheng): This differs from the behavior of both IE and Firefox: the
// origin is inherited from the document that loaded the URL.
- if (loading_url_as_javascript_) {
+ if (IsJavaScriptURLOrXSLTCommit()) {
owner_document = frame_->GetDocument();
} else if (Document::ShouldInheritSecurityOriginFromOwner(Url())) {
Frame* owner_frame = frame_->Tree().Parent();
@@ -911,6 +926,12 @@ void DocumentLoader::CommitNavigation() {
DCHECK(frame_->GetPage());
InstallNewDocument(Url(), initiator_origin, owner_document, MimeType());
+
+ if (response_.IsHTTP() && navigation_timing_info_) {
+ // The response is being copied here to pass the ServerTiming info.
+ // TODO(yoav): copy the ServerTiming info directly.
+ navigation_timing_info_->SetFinalResponse(response_);
+ }
}
void DocumentLoader::CommitData(const char* bytes, size_t length) {
@@ -1161,10 +1182,8 @@ void DocumentLoader::StartLoadingInternal() {
GetFrame()->GetTaskRunner(TaskType::kNetworking),
params_->appcache_host_id);
- if (url_.IsEmpty() &&
- !GetFrameLoader().StateMachine()->CreatingInitialEmptyDocument()) {
+ if (url_.IsEmpty() && commit_reason_ != CommitReason::kInitialization)
url_ = BlankURL();
- }
if (loading_url_as_empty_document_) {
InitializeEmptyResponse();
@@ -1290,6 +1309,17 @@ void DocumentLoader::StartLoadingResponse() {
return;
CHECK_GE(state_, kCommitted);
+
+ // Let the browser process know about all the CSP applied to the document.
+ // The browser process is enforcing several directives. It needs to know about
+ // 'frame-src', 'child-src', 'navigate-to', 'upgrade-insecure-request', etc.
+ //
+ // It is important to forward all the CSP data before loading the response
+ // body, otherwise some loaded content might not be blocked.
+ frame_->GetSecurityContext()
+ ->GetContentSecurityPolicy()
+ ->ReportAccumulatedHeaders(frame_);
+
CreateParserPostCommit();
// Finish load of MHTML archives and empty documents.
@@ -1378,8 +1408,7 @@ void DocumentLoader::DidInstallNewDocument(Document* document) {
response_.HttpHeaderField(http_names::kReferrerPolicy);
if (!referrer_policy_header.IsNull()) {
UseCounter::Count(*document, WebFeature::kReferrerPolicyHeader);
- document->ToExecutionContext()->ParseAndSetReferrerPolicy(
- referrer_policy_header);
+ document->domWindow()->ParseAndSetReferrerPolicy(referrer_policy_header);
}
if (response_.IsSignedExchangeInnerResponse()) {
@@ -1389,17 +1418,35 @@ void DocumentLoader::DidInstallNewDocument(Document* document) {
? WebFeature::kSignedExchangeInnerResponseInMainFrame
: WebFeature::kSignedExchangeInnerResponseInSubFrame);
}
+
+ if (!response_.HttpHeaderField(http_names::kRequireDocumentPolicy).IsNull())
+ UseCounter::Count(*document, WebFeature::kRequireDocumentPolicyHeader);
+
+ if (was_blocked_by_document_policy_)
+ UseCounter::Count(*document, WebFeature::kDocumentPolicyCausedPageUnload);
+
+ // Required document policy can either come from iframe attribute or HTTP
+ // header 'Require-Document-Policy'.
+ if (!frame_policy_.required_document_policy.empty())
+ UseCounter::Count(*document, WebFeature::kRequiredDocumentPolicy);
+
+ for (const auto& message : document_policy_parsing_messages_) {
+ document->AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>(
+ mojom::blink::ConsoleMessageSource::kOther, message.level,
+ message.content));
+ }
+ document_policy_parsing_messages_.clear();
}
void DocumentLoader::WillCommitNavigation() {
- if (GetFrameLoader().StateMachine()->CreatingInitialEmptyDocument())
+ if (commit_reason_ != CommitReason::kRegular)
return;
probe::WillCommitLoad(frame_, this);
frame_->GetIdlenessDetector()->WillCommitLoad();
}
void DocumentLoader::DidCommitNavigation() {
- if (GetFrameLoader().StateMachine()->CreatingInitialEmptyDocument())
+ if (commit_reason_ != CommitReason::kRegular)
return;
if (!frame_->Loader().StateMachine()->CommittedMultipleRealLoads() &&
@@ -1532,10 +1579,13 @@ void DocumentLoader::InstallNewDocument(
.WithContentSecurityPolicy(content_security_policy_.Get())
.WithWebBundleClaimedUrl(web_bundle_claimed_url_);
- // A javascript: url inherits CSP from the document in which it was
+ if (commit_reason_ == CommitReason::kXSLT)
+ init = init.WithSandboxFlags(owner_document->GetSandboxFlags());
+
+ // A javascript: url or XSLT inherits CSP from the document in which it was
// executed.
ContentSecurityPolicy* csp =
- loading_url_as_javascript_
+ IsJavaScriptURLOrXSLTCommit()
? frame_->GetDocument()->GetContentSecurityPolicy()
: content_security_policy_.Get();
global_object_reuse_policy_ =
@@ -1579,10 +1629,9 @@ void DocumentLoader::InstallNewDocument(
}
}
- if (!loading_url_as_javascript_)
- WillCommitNavigation();
+ WillCommitNavigation();
- Document* document = frame_->DomWindow()->InstallNewDocument(init, false);
+ Document* document = frame_->DomWindow()->InstallNewDocument(init);
// Clear the user activation state.
// TODO(crbug.com/736415): Clear this bit unconditionally for all frames.
@@ -1618,12 +1667,14 @@ void DocumentLoader::InstallNewDocument(
document->SetBaseURLOverride(archive_->MainResource()->Url());
}
+ if (commit_reason_ == CommitReason::kXSLT)
+ DocumentXSLT::From(*document).SetTransformSourceDocument(owner_document);
+
DidInstallNewDocument(document);
// This must be called before the document is opened, otherwise HTML parser
// will use stale values from HTMLParserOption.
- if (!loading_url_as_javascript_)
- DidCommitNavigation();
+ DidCommitNavigation();
if (was_cross_origin_to_parent_frame !=
frame_->IsCrossOriginToParentFrame()) {
@@ -1698,17 +1749,6 @@ void DocumentLoader::CreateParserPostCommit() {
DispatchLinkHeaderPreloads(nullptr /* viewport */,
PreloadHelper::kOnlyLoadNonMedia);
- if (!loading_url_as_javascript_ &&
- !GetFrameLoader().StateMachine()->CreatingInitialEmptyDocument()) {
- // When the embedder gets notified (above) that the new navigation has
- // committed, the embedder will drop the old Content Security Policy and
- // therefore now is a good time to report to the embedder the Content
- // Security Policies that have accumulated so far for the new navigation.
- frame_->GetSecurityContext()
- ->GetContentSecurityPolicy()
- ->ReportAccumulatedHeaders(frame_);
- }
-
// Initializing origin trials might force window proxy initialization,
// which later triggers CHECK when swapping in via WebFrame::Swap().
// We can safely omit installing original trials on initial empty document
@@ -1737,16 +1777,28 @@ void DocumentLoader::CreateParserPostCommit() {
#endif
OriginTrialContext::ActivateNavigationFeaturesFromInitiator(
- document->ToExecutionContext(), &initiator_origin_trial_features_);
+ frame_->DomWindow(), &initiator_origin_trial_features_);
}
ParserSynchronizationPolicy parsing_policy = kAllowAsynchronousParsing;
- if (loading_url_as_javascript_ ||
+ if (IsJavaScriptURLOrXSLTCommit() ||
!Document::ThreadedParsingEnabledForTesting()) {
parsing_policy = kForceSynchronousParsing;
}
- parser_ = document->OpenForNavigation(parsing_policy, MimeType(),
- response_.TextEncodingName());
+ const AtomicString& encoding = commit_reason_ == CommitReason::kXSLT
+ ? "UTF-8"
+ : response_.TextEncodingName();
+
+ parser_ = document->OpenForNavigation(parsing_policy, MimeType(), encoding);
+
+ // XSLT processing converts the response into UTF-8 before sending it through
+ // the DocumentParser, but we should still report the original encoding when
+ // script queries it via document.characterSet.
+ if (commit_reason_ == CommitReason::kXSLT) {
+ DocumentEncodingData data;
+ data.SetEncoding(WTF::TextEncoding(response_.TextEncodingName()));
+ document->SetEncodingData(data);
+ }
// If this is a scriptable parser and there is a resource, register the
// resource's cache handler with the parser.
@@ -1814,7 +1866,6 @@ void DocumentLoader::ReportPreviewsIntervention() const {
// Verify that certain types are not on main frame requests.
DCHECK_NE(WebURLRequest::kClientLoFiAutoReload, previews_state_);
- DCHECK_NE(WebURLRequest::kLazyImageLoadDeferred, previews_state_);
DCHECK_NE(WebURLRequest::kSubresourceRedirectOn, previews_state_);
static_assert(WebURLRequest::kPreviewsStateLast ==
@@ -1842,17 +1893,9 @@ void DocumentLoader::ParseAndPersistClientHints(
const KURL& url = response.CurrentRequestUrl();
// The accept-ch header is honored only on the navigation responses from a top
- // level frame or with an origin matching the origin of the to level frame.
- if (!frame_->IsMainFrame()) {
- bool is_first_party_origin =
- frame_->Tree()
- .Top()
- .GetSecurityContext()
- ->GetSecurityOrigin()
- ->IsSameOriginWith(SecurityOrigin::Create(url).get());
- if (!is_first_party_origin)
- return;
- }
+ // level frame.
+ if (!frame_->IsMainFrame())
+ return;
if (!response.HttpHeaderFields().Contains(http_names::kAcceptCH))
return;
@@ -1863,7 +1906,8 @@ void DocumentLoader::ParseAndPersistClientHints(
response.HttpHeaderField(http_names::kAcceptCHLifetime), url,
&hints_context);
client_hints_preferences_.UpdateFromAcceptClientHintsHeader(
- response.HttpHeaderField(http_names::kAcceptCH), url, &hints_context);
+ response.HttpHeaderField(http_names::kAcceptCH), url,
+ ClientHintsPreferences::UpdateMode::kReplace, &hints_context);
base::TimeDelta persist_duration;
@@ -1890,6 +1934,8 @@ void DocumentLoader::ParseAndPersistClientHints(
return;
// Do not persist client hint preferences if the JavaScript is disabled.
+ // TODO(yoav): this seems buggy, and settings doesn't seem notified in
+ // ClientHintBrowserTest.ClientHintsNoLifetimeScriptNotAllowed.
bool allow_script = frame_->GetSettings()->GetScriptEnabled();
if (!settings_client->AllowScriptFromSource(allow_script, url))
return;
@@ -1922,6 +1968,19 @@ DocumentLoader::GetPrefetchedSignedExchangeManager() const {
return prefetched_signed_exchange_manager_;
}
+base::TimeDelta DocumentLoader::RemainingTimeToLCPLimit() const {
+ // We shouldn't call this function before navigation start
+ DCHECK(!document_load_timing_.NavigationStart().is_null());
+ base::TimeTicks lcp_limit =
+ document_load_timing_.NavigationStart() +
+ base::TimeDelta::FromMilliseconds(
+ features::kAlignFontDisplayAutoTimeoutWithLCPGoalTimeoutParam.Get());
+ base::TimeTicks now = clock_->NowTicks();
+ if (now < lcp_limit)
+ return lcp_limit - now;
+ return base::TimeDelta();
+}
+
DEFINE_WEAK_IDENTIFIER_MAP(DocumentLoader)
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/loader/document_loader.h b/chromium/third_party/blink/renderer/core/loader/document_loader.h
index 31fc5754a02..073760ce6f2 100644
--- a/chromium/third_party/blink/renderer/core/loader/document_loader.h
+++ b/chromium/third_party/blink/renderer/core/loader/document_loader.h
@@ -50,6 +50,7 @@
#include "third_party/blink/renderer/bindings/core/v8/source_location.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/dom/weak_identifier_map.h"
+#include "third_party/blink/renderer/core/feature_policy/policy_helper.h"
#include "third_party/blink/renderer/core/frame/dactyloscoper.h"
#include "third_party/blink/renderer/core/frame/frame_types.h"
#include "third_party/blink/renderer/core/frame/use_counter_helper.h"
@@ -70,7 +71,6 @@
#include "third_party/blink/renderer/platform/weborigin/referrer.h"
#include "third_party/blink/renderer/platform/wtf/hash_set.h"
#include "third_party/blink/renderer/platform/wtf/shared_buffer.h"
-
namespace base {
class TickClock;
}
@@ -290,10 +290,13 @@ class CORE_EXPORT DocumentLoader : public GarbageCollected<DocumentLoader>,
application_cache_host_ = host;
}
- void SetLoadingJavaScriptUrl() { loading_url_as_javascript_ = true; }
+ void SetCommitReason(CommitReason reason) { commit_reason_ = reason; }
bool HadTransientActivation() const { return had_transient_activation_; }
+ // Whether the navigation originated from the browser process. Note: history
+ // navigation is always considered to be browser initiated, even if the
+ // navigation was started using the history API in the renderer.
bool IsBrowserInitiated() const { return is_browser_initiated_; }
bool IsSameOriginNavigation() const { return is_same_origin_navigation_; }
@@ -324,6 +327,11 @@ class CORE_EXPORT DocumentLoader : public GarbageCollected<DocumentLoader>,
bool NavigationScrollAllowed() const { return navigation_scroll_allowed_; }
+ // We want to make sure that the largest content is painted before the "LCP
+ // limit", so that we get a good LCP value. This returns the remaining time to
+ // the LCP limit. See crbug.com/1065508 for details.
+ base::TimeDelta RemainingTimeToLCPLimit() const;
+
protected:
Vector<KURL> redirect_chain_;
@@ -419,6 +427,11 @@ class CORE_EXPORT DocumentLoader : public GarbageCollected<DocumentLoader>,
// prefetched signed exchanges for matching requests.
void InitializePrefetchedSignedExchangeManager();
+ bool IsJavaScriptURLOrXSLTCommit() const {
+ return commit_reason_ == CommitReason::kJavascriptUrl ||
+ commit_reason_ == CommitReason::kXSLT;
+ }
+
// These fields are copied from WebNavigationParams, see there for definition.
KURL url_;
AtomicString http_method_;
@@ -481,15 +494,16 @@ class CORE_EXPORT DocumentLoader : public GarbageCollected<DocumentLoader>,
std::unique_ptr<WebServiceWorkerNetworkProvider>
service_worker_network_provider_;
- bool was_blocked_by_document_policy_;
DocumentPolicy::ParsedDocumentPolicy document_policy_;
+ bool was_blocked_by_document_policy_;
+ Vector<PolicyParserMessageBuffer::Message> document_policy_parsing_messages_;
+
+ const Member<ContentSecurityPolicy> content_security_policy_;
+ const bool was_blocked_by_csp_;
- Member<ContentSecurityPolicy> content_security_policy_;
ClientHintsPreferences client_hints_preferences_;
InitialScrollState initial_scroll_state_;
- bool was_blocked_by_csp_;
-
enum State { kNotStarted, kProvisional, kCommitted, kSentDidFinishLoad };
State state_;
@@ -522,7 +536,7 @@ class CORE_EXPORT DocumentLoader : public GarbageCollected<DocumentLoader>,
bool loading_mhtml_archive_ = false;
bool loading_srcdoc_ = false;
bool loading_url_as_empty_document_ = false;
- bool loading_url_as_javascript_ = false;
+ CommitReason commit_reason_ = CommitReason::kRegular;
uint64_t main_resource_identifier_ = 0;
scoped_refptr<ResourceTimingInfo> navigation_timing_info_;
bool report_timing_info_to_parent_ = false;
diff --git a/chromium/third_party/blink/renderer/core/loader/document_loader_test.cc b/chromium/third_party/blink/renderer/core/loader/document_loader_test.cc
index f3673fe84eb..c680b907120 100644
--- a/chromium/third_party/blink/renderer/core/loader/document_loader_test.cc
+++ b/chromium/third_party/blink/renderer/core/loader/document_loader_test.cc
@@ -5,14 +5,17 @@
#include "third_party/blink/renderer/core/loader/document_loader.h"
#include <utility>
+
#include "base/auto_reset.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/common/frame/frame_owner_element_type.h"
#include "third_party/blink/public/mojom/feature_policy/feature_policy.mojom-shared.h"
+#include "third_party/blink/public/mojom/feature_policy/policy_disposition.mojom-blink.h"
+#include "third_party/blink/public/mojom/frame/frame_owner_element_type.mojom-blink.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/web_url_loader_client.h"
#include "third_party/blink/public/platform/web_url_loader_mock_factory.h"
#include "third_party/blink/renderer/core/frame/frame_test_helpers.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
#include "third_party/blink/renderer/core/inspector/console_message.h"
#include "third_party/blink/renderer/core/page/page.h"
@@ -20,6 +23,7 @@
#include "third_party/blink/renderer/core/testing/sim/sim_request.h"
#include "third_party/blink/renderer/core/testing/sim/sim_test.h"
#include "third_party/blink/renderer/platform/loader/static_data_navigation_body_loader.h"
+#include "third_party/blink/renderer/platform/testing/histogram_tester.h"
#include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
#include "third_party/blink/renderer/platform/testing/url_test_helpers.h"
#include "third_party/blink/renderer/platform/wtf/deque.h"
@@ -256,6 +260,89 @@ TEST_F(DocumentLoaderSimTest, FramePolicyIntegrityOnNavigationCommit) {
EXPECT_TRUE(child_document->IsFeatureEnabled(
blink::mojom::blink::FeaturePolicyFeature::kPayment));
}
+// When runtime feature DocumentPolicy is not enabled, specifying
+// Document-Policy and Require-Document-Policy should have no effect, i.e.
+// document load should not be blocked even if the required policy and incoming
+// policy are incompatible and calling
+// |Document::IsFeatureEnabled(DocumentPolicyFeature...)| should always return
+// true.
+TEST_F(DocumentLoaderSimTest, DocumentPolicyNoEffectWhenFlagNotSet) {
+ blink::ScopedDocumentPolicyForTest sdp(false);
+ SimRequest::Params params;
+ params.response_http_headers = {
+ {"Document-Policy", "unoptimized-lossless-images;bpp=1.1"}};
+
+ SimRequest main_resource("https://example.com", "text/html");
+ SimRequest iframe_resource("https://example.com/foo.html", "text/html",
+ params);
+
+ LoadURL("https://example.com");
+ main_resource.Complete(R"(
+ <iframe
+ src="https://example.com/foo.html"
+ policy="unoptimized-lossless-images;bpp=1.0">
+ </iframe>
+ )");
+
+ iframe_resource.Finish();
+ auto* child_frame = To<WebLocalFrameImpl>(MainFrame().FirstChild());
+ auto* child_document = child_frame->GetFrame()->GetDocument();
+ auto& console_messages = static_cast<frame_test_helpers::TestWebFrameClient*>(
+ child_frame->Client())
+ ->ConsoleMessages();
+
+ // Should not receive a console error message caused by document policy
+ // violation blocking document load.
+ EXPECT_TRUE(console_messages.IsEmpty());
+
+ EXPECT_EQ(child_document->Url(), KURL("https://example.com/foo.html"));
+
+ EXPECT_FALSE(child_document->IsUseCounted(
+ mojom::WebFeature::kDocumentPolicyCausedPageUnload));
+
+ // Unoptimized-lossless-images should still be allowed in main document.
+ EXPECT_TRUE(GetDocument().IsFeatureEnabled(
+ mojom::blink::DocumentPolicyFeature::kUnoptimizedLosslessImages,
+ PolicyValue(2.0)));
+ EXPECT_TRUE(GetDocument().IsFeatureEnabled(
+ mojom::blink::DocumentPolicyFeature::kUnoptimizedLosslessImages,
+ PolicyValue(1.0)));
+
+ // Unoptimized-lossless-images should still be allowed in child document.
+ EXPECT_TRUE(child_document->IsFeatureEnabled(
+ mojom::blink::DocumentPolicyFeature::kUnoptimizedLosslessImages,
+ PolicyValue(2.0)));
+ EXPECT_TRUE(child_document->IsFeatureEnabled(
+ mojom::blink::DocumentPolicyFeature::kUnoptimizedLosslessImages,
+ PolicyValue(1.0)));
+}
+
+TEST_F(DocumentLoaderSimTest, ReportDocumentPolicyHeaderParsingError) {
+ blink::ScopedDocumentPolicyForTest sdp(true);
+ SimRequest::Params params;
+ params.response_http_headers = {{"Document-Policy", "bad-feature-name"}};
+ SimRequest main_resource("https://example.com", "text/html", params);
+ LoadURL("https://example.com");
+ main_resource.Finish();
+
+ EXPECT_EQ(ConsoleMessages().size(), 1u);
+ EXPECT_TRUE(
+ ConsoleMessages().front().StartsWith("Document-Policy HTTP header:"));
+}
+
+TEST_F(DocumentLoaderSimTest, ReportRequireDocumentPolicyHeaderParsingError) {
+ blink::ScopedDocumentPolicyForTest sdp(true);
+ SimRequest::Params params;
+ params.response_http_headers = {
+ {"Require-Document-Policy", "bad-feature-name"}};
+ SimRequest main_resource("https://example.com", "text/html", params);
+ LoadURL("https://example.com");
+ main_resource.Finish();
+
+ EXPECT_EQ(ConsoleMessages().size(), 1u);
+ EXPECT_TRUE(ConsoleMessages().front().StartsWith(
+ "Require-Document-Policy HTTP header:"));
+}
TEST_F(DocumentLoaderSimTest, ReportErrorWhenDocumentPolicyIncompatible) {
blink::ScopedDocumentPolicyForTest sdp(true);
@@ -294,6 +381,9 @@ TEST_F(DocumentLoaderSimTest, ReportErrorWhenDocumentPolicyIncompatible) {
// Should replace the document's origin with an opaque origin.
EXPECT_EQ(child_document->Url(), SecurityOrigin::UrlWithUniqueOpaqueOrigin());
+
+ EXPECT_TRUE(child_document->IsUseCounted(
+ mojom::WebFeature::kDocumentPolicyCausedPageUnload));
}
// HTTP header Require-Document-Policy should only take effect on subtree of
@@ -313,6 +403,226 @@ TEST_F(DocumentLoaderSimTest,
main_resource.Finish();
}
+TEST_F(DocumentLoaderSimTest, DocumentPolicyHeaderHistogramTest) {
+ blink::ScopedDocumentPolicyForTest sdp(true);
+ HistogramTester histogram_tester;
+
+ SimRequest::Params params;
+ params.response_http_headers = {
+ {"Document-Policy",
+ "font-display-late-swap, unoptimized-lossless-images;bpp=1.1"}};
+
+ SimRequest main_resource("https://example.com", "text/html", params);
+ LoadURL("https://example.com");
+ main_resource.Finish();
+
+ histogram_tester.ExpectTotalCount("Blink.UseCounter.DocumentPolicy.Header",
+ 2);
+ histogram_tester.ExpectBucketCount("Blink.UseCounter.DocumentPolicy.Header",
+ 1 /* kFontDisplay */, 1);
+ histogram_tester.ExpectBucketCount("Blink.UseCounter.DocumentPolicy.Header",
+ 2 /* kUnoptimizedLosslessImages */, 1);
+}
+
+TEST_F(DocumentLoaderSimTest, DocumentPolicyPolicyAttributeHistogramTest) {
+ blink::ScopedDocumentPolicyForTest sdp(true);
+ HistogramTester histogram_tester;
+
+ SimRequest main_resource("https://example.com", "text/html");
+ LoadURL("https://example.com");
+
+ // Same feature should only be reported once in a document despite its
+ // occurrence.
+ main_resource.Complete(R"(
+ <iframe policy="font-display-late-swap"></iframe>
+ <iframe policy="no-font-display-late-swap"></iframe>
+ <iframe
+ policy="font-display-late-swap, unoptimized-lossless-images;bpp=1.1">
+ </iframe>
+ )");
+
+ histogram_tester.ExpectTotalCount(
+ "Blink.UseCounter.DocumentPolicy.PolicyAttribute", 2);
+ histogram_tester.ExpectBucketCount(
+ "Blink.UseCounter.DocumentPolicy.PolicyAttribute", 1 /* kFontDisplay */,
+ 1);
+ histogram_tester.ExpectBucketCount(
+ "Blink.UseCounter.DocumentPolicy.PolicyAttribute",
+ 2 /* kUnoptimizedLosslessImages */, 1);
+}
+
+TEST_F(DocumentLoaderSimTest, DocumentPolicyEnforcedReportHistogramTest) {
+ blink::ScopedDocumentPolicyForTest sdp(true);
+ HistogramTester histogram_tester;
+
+ SimRequest main_resource("https://example.com", "text/html");
+ LoadURL("https://example.com");
+ main_resource.Finish();
+
+ Window().ReportDocumentPolicyViolation(
+ mojom::blink::DocumentPolicyFeature::kFontDisplay,
+ mojom::blink::PolicyDisposition::kEnforce);
+
+ histogram_tester.ExpectTotalCount("Blink.UseCounter.DocumentPolicy.Enforced",
+ 1);
+ histogram_tester.ExpectBucketCount("Blink.UseCounter.DocumentPolicy.Enforced",
+ 1 /* kFontDisplay */, 1);
+
+ // Multiple reports should be recorded multiple times.
+ Window().ReportDocumentPolicyViolation(
+ mojom::blink::DocumentPolicyFeature::kFontDisplay,
+ mojom::blink::PolicyDisposition::kEnforce);
+
+ histogram_tester.ExpectTotalCount("Blink.UseCounter.DocumentPolicy.Enforced",
+ 2);
+ histogram_tester.ExpectBucketCount("Blink.UseCounter.DocumentPolicy.Enforced",
+ 1 /* kFontDisplay */, 2);
+}
+
+TEST_F(DocumentLoaderSimTest, DocumentPolicyReportOnlyReportHistogramTest) {
+ blink::ScopedDocumentPolicyForTest sdp(true);
+ HistogramTester histogram_tester;
+
+ SimRequest::Params params;
+ params.response_http_headers = {
+ {"Document-Policy-Report-Only", "font-display-late-swap"}};
+ SimRequest main_resource("https://example.com", "text/html", params);
+
+ LoadURL("https://example.com");
+ main_resource.Finish();
+
+ Window().ReportDocumentPolicyViolation(
+ mojom::blink::DocumentPolicyFeature::kFontDisplay,
+ mojom::blink::PolicyDisposition::kReport);
+
+ histogram_tester.ExpectTotalCount(
+ "Blink.UseCounter.DocumentPolicy.ReportOnly", 1);
+ histogram_tester.ExpectBucketCount(
+ "Blink.UseCounter.DocumentPolicy.ReportOnly", 1 /* kFontDisplay */, 1);
+
+ // Multiple reports should be recorded multiple times.
+ Window().ReportDocumentPolicyViolation(
+ mojom::blink::DocumentPolicyFeature::kFontDisplay,
+ mojom::blink::PolicyDisposition::kReport);
+
+ histogram_tester.ExpectTotalCount(
+ "Blink.UseCounter.DocumentPolicy.ReportOnly", 2);
+ histogram_tester.ExpectBucketCount(
+ "Blink.UseCounter.DocumentPolicy.ReportOnly", 1 /* kFontDisplay */, 2);
+}
+
+class DocumentPolicyHeaderUseCounterTest
+ : public DocumentLoaderSimTest,
+ public testing::WithParamInterface<std::tuple<bool, bool, bool>> {};
+
+TEST_P(DocumentPolicyHeaderUseCounterTest, ShouldObserveUseCounterUpdate) {
+ blink::ScopedDocumentPolicyForTest sdp(true);
+
+ bool has_document_policy_header, has_report_only_header, has_require_header;
+ std::tie(has_document_policy_header, has_report_only_header,
+ has_require_header) = GetParam();
+
+ SimRequest::Params params;
+ if (has_document_policy_header) {
+ params.response_http_headers.insert("Document-Policy",
+ "unoptimized-lossless-images;bpp=1.0");
+ }
+ if (has_report_only_header) {
+ params.response_http_headers.insert("Document-Policy-Report-Only",
+ "unoptimized-lossless-images;bpp=1.0");
+ }
+ if (has_require_header) {
+ params.response_http_headers.insert("Require-Document-Policy",
+ "unoptimized-lossless-images;bpp=1.0");
+ }
+ SimRequest main_resource("https://example.com", "text/html", params);
+ LoadURL("https://example.com");
+ main_resource.Complete();
+
+ EXPECT_EQ(
+ GetDocument().IsUseCounted(mojom::WebFeature::kDocumentPolicyHeader),
+ has_document_policy_header);
+ EXPECT_EQ(GetDocument().IsUseCounted(
+ mojom::WebFeature::kDocumentPolicyReportOnlyHeader),
+ has_report_only_header);
+ EXPECT_EQ(GetDocument().IsUseCounted(
+ mojom::WebFeature::kRequireDocumentPolicyHeader),
+ has_require_header);
+}
+
+INSTANTIATE_TEST_SUITE_P(DocumentPolicyHeaderValues,
+ DocumentPolicyHeaderUseCounterTest,
+ ::testing::Combine(::testing::Bool(),
+ ::testing::Bool(),
+ ::testing::Bool()));
+
+TEST_F(DocumentLoaderSimTest,
+ DocumentPolicyIframePolicyAttributeUseCounterTest) {
+ blink::ScopedDocumentPolicyForTest sdp(true);
+ SimRequest main_resource("https://example.com", "text/html");
+ SimRequest::Params iframe_params;
+ iframe_params.response_http_headers = {
+ {"Document-Policy", "unoptimized-lossless-images;bpp=1.0"}};
+ SimRequest iframe_resource("https://example.com/foo.html", "text/html",
+ iframe_params);
+ LoadURL("https://example.com");
+ main_resource.Complete(R"(
+ <iframe
+ src="https://example.com/foo.html"
+ policy="unoptimized-lossless-images;bpp=1.0"
+ ></iframe>
+ )");
+ iframe_resource.Finish();
+
+ EXPECT_TRUE(GetDocument().IsUseCounted(
+ mojom::WebFeature::kDocumentPolicyIframePolicyAttribute));
+ EXPECT_FALSE(
+ GetDocument().IsUseCounted(mojom::WebFeature::kRequiredDocumentPolicy));
+
+ auto* child_frame = To<WebLocalFrameImpl>(MainFrame().FirstChild());
+ auto* child_document = child_frame->GetFrame()->GetDocument();
+
+ EXPECT_FALSE(child_document->IsUseCounted(
+ mojom::WebFeature::kDocumentPolicyIframePolicyAttribute));
+ EXPECT_TRUE(
+ child_document->IsUseCounted(mojom::WebFeature::kRequiredDocumentPolicy));
+}
+
+TEST_F(DocumentLoaderSimTest, RequiredDocumentPolicyUseCounterTest) {
+ blink::ScopedDocumentPolicyForTest sdp(true);
+
+ SimRequest::Params main_frame_params;
+ main_frame_params.response_http_headers = {
+ {"Require-Document-Policy", "unoptimized-lossless-images;bpp=1.0"}};
+ SimRequest main_resource("https://example.com", "text/html",
+ main_frame_params);
+
+ SimRequest::Params iframe_params;
+ iframe_params.response_http_headers = {
+ {"Document-Policy", "unoptimized-lossless-images;bpp=1.0"}};
+ SimRequest iframe_resource("https://example.com/foo.html", "text/html",
+ iframe_params);
+
+ LoadURL("https://example.com");
+ main_resource.Complete(R"(
+ <iframe src="https://example.com/foo.html"></iframe>
+ )");
+ iframe_resource.Finish();
+
+ EXPECT_FALSE(GetDocument().IsUseCounted(
+ mojom::WebFeature::kDocumentPolicyIframePolicyAttribute));
+ EXPECT_FALSE(
+ GetDocument().IsUseCounted(mojom::WebFeature::kRequiredDocumentPolicy));
+
+ auto* child_frame = To<WebLocalFrameImpl>(MainFrame().FirstChild());
+ auto* child_document = child_frame->GetFrame()->GetDocument();
+
+ EXPECT_FALSE(child_document->IsUseCounted(
+ mojom::WebFeature::kDocumentPolicyIframePolicyAttribute));
+ EXPECT_TRUE(
+ child_document->IsUseCounted(mojom::WebFeature::kRequiredDocumentPolicy));
+}
+
TEST_F(DocumentLoaderTest, CommitsDeferredOnSameOriginNavigation) {
const KURL& requestor_url =
KURL(NullURL(), "https://www.example.com/foo.html");
diff --git a/chromium/third_party/blink/renderer/core/loader/empty_clients.cc b/chromium/third_party/blink/renderer/core/loader/empty_clients.cc
index 31d1f0a93bf..c20b0b6b215 100644
--- a/chromium/third_party/blink/renderer/core/loader/empty_clients.cc
+++ b/chromium/third_party/blink/renderer/core/loader/empty_clients.cc
@@ -95,7 +95,6 @@ void EmptyLocalFrameClient::BeginNavigation(
DocumentLoader*,
WebNavigationType,
NavigationPolicy,
- bool,
WebFrameLoadType,
bool,
TriggeringEventInfo,
@@ -104,6 +103,7 @@ void EmptyLocalFrameClient::BeginNavigation(
mojo::PendingRemote<mojom::blink::BlobURLToken>,
base::TimeTicks,
const String&,
+ const base::Optional<WebImpression>&,
WTF::Vector<network::mojom::blink::ContentSecurityPolicyPtr> initiator_csp,
network::mojom::blink::CSPSourcePtr initiator_csp_self,
network::mojom::IPAddressSpace,
diff --git a/chromium/third_party/blink/renderer/core/loader/empty_clients.h b/chromium/third_party/blink/renderer/core/loader/empty_clients.h
index bbfe2870e68..3379260227c 100644
--- a/chromium/third_party/blink/renderer/core/loader/empty_clients.h
+++ b/chromium/third_party/blink/renderer/core/loader/empty_clients.h
@@ -134,7 +134,7 @@ class CORE_EXPORT EmptyChromeClient : public ChromeClient {
const FrameLoadRequest&,
const AtomicString&,
const WebWindowFeatures&,
- mojom::blink::WebSandboxFlags,
+ network::mojom::blink::WebSandboxFlags,
const FeaturePolicy::FeatureState&,
const SessionStorageNamespaceId&) override {
return nullptr;
@@ -210,13 +210,7 @@ class CORE_EXPORT EmptyChromeClient : public ChromeClient {
void RegisterPopupOpeningObserver(PopupOpeningObserver*) override {}
void UnregisterPopupOpeningObserver(PopupOpeningObserver*) override {}
void NotifyPopupOpeningObservers() const override {}
- void FallbackCursorModeLockCursor(LocalFrame* frame,
- bool left,
- bool right,
- bool up,
- bool down) override {}
- void FallbackCursorModeSetCursorVisibility(LocalFrame* frame,
- bool visible) override {}
+
void RequestBeginMainFrameNotExpected(LocalFrame& frame,
bool request) override {}
int GetLayerTreeId(LocalFrame& frame) override { return 0; }
@@ -266,7 +260,6 @@ class CORE_EXPORT EmptyLocalFrameClient : public LocalFrameClient {
DocumentLoader*,
WebNavigationType,
NavigationPolicy,
- bool,
WebFrameLoadType,
bool,
TriggeringEventInfo,
@@ -275,6 +268,7 @@ class CORE_EXPORT EmptyLocalFrameClient : public LocalFrameClient {
mojo::PendingRemote<mojom::blink::BlobURLToken>,
base::TimeTicks,
const String&,
+ const base::Optional<WebImpression>&,
WTF::Vector<network::mojom::blink::ContentSecurityPolicyPtr>
initiator_csp,
network::mojom::blink::CSPSourcePtr initiator_self_source,
@@ -332,7 +326,7 @@ class CORE_EXPORT EmptyLocalFrameClient : public LocalFrameClient {
HTMLMediaElement&) override;
void DidCreateInitialEmptyDocument() override {}
- void DidCommitJavascriptUrlNavigation(DocumentLoader*) override {}
+ void DidCommitDocumentReplacementNavigation(DocumentLoader*) override {}
void DispatchDidClearWindowObjectInMainWorld() override {}
void DocumentElementAvailable() override {}
void RunScriptsAtDocumentElementAvailable() override {}
@@ -411,11 +405,13 @@ class CORE_EXPORT EmptyRemoteFrameClient : public RemoteFrameClient {
// RemoteFrameClient implementation.
void Navigate(const ResourceRequest&,
+ blink::WebLocalFrame* initiator_frame,
bool should_replace_current_entry,
bool is_opener_navigation,
bool initiator_frame_has_download_sandbox_flag,
bool initiator_frame_is_ad,
- mojo::PendingRemote<mojom::blink::BlobURLToken>) override {}
+ mojo::PendingRemote<mojom::blink::BlobURLToken>,
+ const base::Optional<WebImpression>&) override {}
unsigned BackForwardLength() override { return 0; }
void ForwardPostMessage(
MessageEvent*,
diff --git a/chromium/third_party/blink/renderer/core/loader/font_preload_manager_test.cc b/chromium/third_party/blink/renderer/core/loader/font_preload_manager_test.cc
index 8a254066e90..a3ce32c60d9 100644
--- a/chromium/third_party/blink/renderer/core/loader/font_preload_manager_test.cc
+++ b/chromium/third_party/blink/renderer/core/loader/font_preload_manager_test.cc
@@ -483,4 +483,103 @@ TEST_F(FontPreloadManagerTest, OptionalFontFastImperativeLoad) {
EXPECT_FALSE(GetTargetFont().ShouldSkipDrawing());
}
+class FontPreloadBehaviorObservationTest
+ : public testing::WithParamInterface<bool>,
+ public SimTest {
+ public:
+ class LoadingBehaviorObserver
+ : public frame_test_helpers::TestWebFrameClient {
+ public:
+ void DidObserveLoadingBehavior(LoadingBehaviorFlag flag) override {
+ observed_behaviors_ =
+ static_cast<LoadingBehaviorFlag>(observed_behaviors_ | flag);
+ }
+
+ LoadingBehaviorFlag ObservedBehaviors() const {
+ return observed_behaviors_;
+ }
+
+ private:
+ LoadingBehaviorFlag observed_behaviors_ = kLoadingBehaviorNone;
+ };
+
+ void SetUp() override {
+ SimTest::SetUp();
+ original_web_local_frame_client_ = MainFrame().Client();
+ MainFrame().SetClient(&loading_behavior_observer_);
+ }
+
+ void TearDown() override {
+ MainFrame().SetClient(original_web_local_frame_client_);
+ SimTest::TearDown();
+ }
+
+ LoadingBehaviorFlag ObservedBehaviors() const {
+ return loading_behavior_observer_.ObservedBehaviors();
+ }
+
+ private:
+ WebLocalFrameClient* original_web_local_frame_client_;
+ LoadingBehaviorObserver loading_behavior_observer_;
+};
+
+INSTANTIATE_TEST_SUITE_P(All,
+ FontPreloadBehaviorObservationTest,
+ testing::Bool());
+
+TEST_P(FontPreloadBehaviorObservationTest, ObserveBehaviorWithLinkPreload) {
+ // kLoadingBehaviorFontPreloadStartedBeforeRendering should be observed as
+ // long as there's font preloading, regardless of the enabled status of the
+ // feature FontPreloadingDelaysRendering.
+ base::test::ScopedFeatureList scoped_feature_list;
+ if (GetParam()) {
+ scoped_feature_list.InitAndEnableFeature(
+ features::kFontPreloadingDelaysRendering);
+ }
+
+ SimRequest main_resource("https://example.com", "text/html");
+ SimRequest font_resource("https://example.com/font.woff", "font/woff2");
+
+ LoadURL("https://example.com");
+ main_resource.Complete(R"HTML(
+ <!doctype html>
+ <link rel="preload" as="font" type="font/woff2"
+ href="https://example.com/font.woff" crossorigin>
+ )HTML");
+
+ EXPECT_TRUE(ObservedBehaviors() |
+ kLoadingBehaviorFontPreloadStartedBeforeRendering);
+
+ font_resource.Finish();
+ test::RunPendingTasks();
+}
+
+TEST_P(FontPreloadBehaviorObservationTest, ObserveBehaviorWithImperativeLoad) {
+ // kLoadingBehaviorFontPreloadStartedBeforeRendering should be observed as
+ // long as there's an imperative font load, regardless of the enabled status
+ // of the feature FontPreloadingDelaysRendering.
+ base::test::ScopedFeatureList scoped_feature_list;
+ if (GetParam()) {
+ scoped_feature_list.InitAndEnableFeature(
+ features::kFontPreloadingDelaysRendering);
+ }
+
+ SimRequest main_resource("https://example.com", "text/html");
+ SimRequest font_resource("https://example.com/font.woff", "font/woff2");
+
+ LoadURL("https://example.com");
+ main_resource.Complete(R"HTML(
+ <!doctype html>
+ <script>
+ new FontFace('custom-font', 'url(https://example.com/font.woff)').load();
+ </script>
+ )HTML");
+
+ EXPECT_TRUE(ObservedBehaviors() |
+ kLoadingBehaviorFontPreloadStartedBeforeRendering);
+
+ font_resource.Finish();
+ test::RunPendingTasks();
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/loader/frame_fetch_context.cc b/chromium/third_party/blink/renderer/core/loader/frame_fetch_context.cc
index 4da8cf1c591..51f3241349b 100644
--- a/chromium/third_party/blink/renderer/core/loader/frame_fetch_context.cc
+++ b/chromium/third_party/blink/renderer/core/loader/frame_fetch_context.cc
@@ -37,14 +37,16 @@
#include "base/optional.h"
#include "build/build_config.h"
#include "mojo/public/cpp/bindings/associated_remote.h"
+#include "net/http/structured_headers.h"
+#include "services/network/public/mojom/web_client_hints_types.mojom-blink.h"
#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
#include "third_party/blink/public/common/client_hints/client_hints.h"
#include "third_party/blink/public/common/device_memory/approximated_device_memory.h"
+#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/mojom/conversions/conversions.mojom-blink.h"
#include "third_party/blink/public/mojom/feature_policy/feature_policy.mojom-blink.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/web_client_hints/web_client_hints_types.mojom-blink.h"
#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_network_provider.h"
#include "third_party/blink/public/platform/scheduler/web_scoped_virtual_time_pauser.h"
#include "third_party/blink/public/platform/web_content_settings_client.h"
@@ -75,7 +77,6 @@
#include "third_party/blink/renderer/core/loader/appcache/application_cache_host.h"
#include "third_party/blink/renderer/core/loader/document_loader.h"
#include "third_party/blink/renderer/core/loader/frame_loader.h"
-#include "third_party/blink/renderer/core/loader/frame_or_imported_document.h"
#include "third_party/blink/renderer/core/loader/frame_resource_fetcher_properties.h"
#include "third_party/blink/renderer/core/loader/idleness_detector.h"
#include "third_party/blink/renderer/core/loader/interactive_detector.h"
@@ -121,26 +122,15 @@ namespace {
// If that flag is disabled (the default), then all hints are always sent for
// first-party subresources, and the kAllowClientHintsToThirdParty feature
// controls whether some specific hints are sent to third parties. (Only
-// device-memory, resource-width, viewport-width and the limited UA hints are
-// sent under this model). This feature is enabled by default on Android, and
-// disabled by default on all other platforms.
+// device-memory, resource-width, viewport-width and DPR are sent under this
+// model). This feature is enabled by default on Android, and disabled by
+// default on all other platforms.
//
// When the runtime flag is enabled, all client hints except UA are controlled
// entirely by feature policy on all platforms. In that case, hints will
// generally be sent for first-party resources, and not for third-party
// resources, unless specifically enabled by policy.
-// If kAllowClientHintsToThirdParty is enabled, then device-memory,
-// resource-width and viewport-width client hints can be sent to third-party
-// origins if the first-party has opted in to receiving client hints.
-#if defined(OS_ANDROID)
-const base::Feature kAllowClientHintsToThirdParty{
- "AllowClientHintsToThirdParty", base::FEATURE_ENABLED_BY_DEFAULT};
-#else
-const base::Feature kAllowClientHintsToThirdParty{
- "AllowClientHintsToThirdParty", base::FEATURE_DISABLED_BY_DEFAULT};
-#endif
-
// Determines FetchCacheMode for |frame|. This FetchCacheMode should be a base
// policy to consider one of each resource belonging to the frame, and should
// not count resource specific conditions in.
@@ -188,33 +178,15 @@ mojom::FetchCacheMode DetermineFrameCacheMode(Frame* frame) {
}
// Simple function to add quotes to make headers strings.
-const AtomicString AddBrandVersionQuotes(const std::string& brand,
- const std::string& version) {
- if (brand.empty())
- return AtomicString("");
-
- StringBuilder quoted_string;
- quoted_string.Append("\"");
- quoted_string.Append(brand.data());
- quoted_string.Append("\"");
- if (!version.empty()) {
- quoted_string.Append(";v=\"");
- quoted_string.Append(version.data());
- quoted_string.Append("\"");
+const AtomicString SerializeHeaderString(std::string str) {
+ std::string output;
+ if (!str.empty()) {
+ output = net::structured_headers::SerializeItem(
+ net::structured_headers::Item(str))
+ .value_or(std::string());
}
- return quoted_string.ToAtomicString();
-}
-// Simple function to add quotes to make headers strings.
-const AtomicString AddQuotes(std::string str) {
- if (str.empty())
- return AtomicString("");
-
- StringBuilder quoted_string;
- quoted_string.Append("\"");
- quoted_string.Append(str.data());
- quoted_string.Append("\"");
- return quoted_string.ToAtomicString();
+ return AtomicString(output.c_str());
}
} // namespace
@@ -258,18 +230,15 @@ struct FrameFetchContext::FrozenState final : GarbageCollected<FrozenState> {
ResourceFetcher* FrameFetchContext::CreateFetcherForCommittedDocument(
DocumentLoader& loader,
Document& document) {
- auto& frame_or_imported_document =
- *MakeGarbageCollected<FrameOrImportedDocument>(loader, document);
auto& properties = *MakeGarbageCollected<DetachableResourceFetcherProperties>(
- *MakeGarbageCollected<FrameResourceFetcherProperties>(
- frame_or_imported_document));
- LocalFrame& frame = frame_or_imported_document.GetFrame();
+ *MakeGarbageCollected<FrameResourceFetcherProperties>(loader, document));
+ LocalFrame* frame = document.GetFrame();
+ DCHECK(frame);
ResourceFetcherInit init(
properties,
- MakeGarbageCollected<FrameFetchContext>(frame_or_imported_document,
- properties),
- frame.GetTaskRunner(TaskType::kNetworking),
- MakeGarbageCollected<LoaderFactoryForFrame>(frame_or_imported_document));
+ MakeGarbageCollected<FrameFetchContext>(loader, document, properties),
+ frame->GetTaskRunner(TaskType::kNetworking),
+ MakeGarbageCollected<LoaderFactoryForFrame>(loader, document));
init.use_counter = MakeGarbageCollected<DetachableUseCounter>(&document);
init.console_logger = MakeGarbageCollected<DetachableConsoleLogger>(
document.GetExecutionContext());
@@ -277,51 +246,25 @@ ResourceFetcher* FrameFetchContext::CreateFetcherForCommittedDocument(
// frame will be in layout-blocking state until the <body> tag is inserted
init.initial_throttling_policy =
ResourceLoadScheduler::ThrottlingPolicy::kTight;
- init.frame_scheduler = frame.GetFrameScheduler();
+ init.frame_or_worker_scheduler = frame->GetFrameScheduler();
init.archive = loader.Archive();
ResourceFetcher* fetcher = MakeGarbageCollected<ResourceFetcher>(init);
fetcher->SetResourceLoadObserver(
MakeGarbageCollected<ResourceLoadObserverForFrame>(
- frame_or_imported_document, fetcher->GetProperties()));
- fetcher->SetImagesEnabled(frame.GetSettings()->GetImagesEnabled());
+ loader, document, fetcher->GetProperties()));
+ fetcher->SetImagesEnabled(frame->GetSettings()->GetImagesEnabled());
fetcher->SetAutoLoadImages(
- frame.GetSettings()->GetLoadsImagesAutomatically());
- return fetcher;
-}
-
-ResourceFetcher* FrameFetchContext::CreateFetcherForImportedDocument(
- Document* document) {
- DCHECK(document);
- // |document| is detached.
- DCHECK(!document->GetFrame());
- auto& frame_or_imported_document =
- *MakeGarbageCollected<FrameOrImportedDocument>(*document);
- auto& properties = *MakeGarbageCollected<DetachableResourceFetcherProperties>(
- *MakeGarbageCollected<FrameResourceFetcherProperties>(
- frame_or_imported_document));
- LocalFrame& frame = frame_or_imported_document.GetFrame();
- ResourceFetcherInit init(
- properties,
- MakeGarbageCollected<FrameFetchContext>(frame_or_imported_document,
- properties),
- document->GetTaskRunner(blink::TaskType::kNetworking),
- MakeGarbageCollected<LoaderFactoryForFrame>(frame_or_imported_document));
- init.use_counter = MakeGarbageCollected<DetachableUseCounter>(document);
- init.console_logger = MakeGarbageCollected<DetachableConsoleLogger>(
- document->GetExecutionContext());
- init.frame_scheduler = frame.GetFrameScheduler();
- auto* fetcher = MakeGarbageCollected<ResourceFetcher>(init);
- fetcher->SetResourceLoadObserver(
- MakeGarbageCollected<ResourceLoadObserverForFrame>(
- frame_or_imported_document, fetcher->GetProperties()));
+ frame->GetSettings()->GetLoadsImagesAutomatically());
return fetcher;
}
FrameFetchContext::FrameFetchContext(
- const FrameOrImportedDocument& frame_or_imported_document,
+ DocumentLoader& document_loader,
+ Document& document,
const DetachableResourceFetcherProperties& properties)
: BaseFetchContext(properties),
- frame_or_imported_document_(frame_or_imported_document),
+ document_loader_(document_loader),
+ document_(document),
save_data_enabled_(
GetNetworkStateNotifier().SaveDataEnabled() &&
!GetFrame()->GetSettings()->GetDataSaverHoldbackWebApi()) {}
@@ -329,14 +272,14 @@ FrameFetchContext::FrameFetchContext(
net::SiteForCookies FrameFetchContext::GetSiteForCookies() const {
if (GetResourceFetcherProperties().IsDetached())
return frozen_state_->site_for_cookies;
- return frame_or_imported_document_->GetDocument().SiteForCookies();
+ return document_->SiteForCookies();
}
scoped_refptr<const SecurityOrigin> FrameFetchContext::GetTopFrameOrigin()
const {
if (GetResourceFetcherProperties().IsDetached())
return frozen_state_->top_frame_origin;
- return frame_or_imported_document_->GetDocument().TopFrameOrigin();
+ return document_->TopFrameOrigin();
}
SubresourceFilter* FrameFetchContext::GetSubresourceFilter() const {
@@ -363,7 +306,7 @@ WebURLRequest::PreviewsState FrameFetchContext::previews_state() const {
}
LocalFrame* FrameFetchContext::GetFrame() const {
- return &frame_or_imported_document_->GetFrame();
+ return document_->GetFrame();
}
LocalFrameClient* FrameFetchContext::GetLocalFrameClient() const {
@@ -411,7 +354,7 @@ mojom::FetchCacheMode FrameFetchContext::ResourceRequestCachePolicy(
inline DocumentLoader* FrameFetchContext::MasterDocumentLoader() const {
DCHECK(!GetResourceFetcherProperties().IsDetached());
- return &frame_or_imported_document_->GetMasterDocumentLoader();
+ return document_loader_;
}
void FrameFetchContext::PrepareRequest(
@@ -448,10 +391,6 @@ void FrameFetchContext::PrepareRequest(
if (request.GetPreviewsState() == WebURLRequest::kPreviewsUnspecified) {
WebURLRequest::PreviewsState request_previews_state =
document_loader->GetPreviewsState();
- // The decision of whether or not to enable Client Lo-Fi is made earlier
- // in the request lifetime, in LocalFrame::MaybeAllowImagePlaceholder(),
- // so don't add the Client Lo-Fi bit to the request here.
- request_previews_state &= ~(WebURLRequest::kLazyImageLoadDeferred);
if (request_previews_state == WebURLRequest::kPreviewsUnspecified)
request_previews_state = WebURLRequest::kPreviewsOff;
request.SetPreviewsState(request_previews_state);
@@ -481,14 +420,10 @@ void FrameFetchContext::AddResourceTiming(const ResourceTimingInfo& info) {
// early return, as there is nothing to report the resource timing to.
if (GetResourceFetcherProperties().IsDetached())
return;
- LocalFrame* frame = frame_or_imported_document_->GetDocument().GetFrame();
- if (!frame)
- return;
// Timing for main resource is handled in DocumentLoader.
// All other resources are reported to the corresponding Document.
- DOMWindowPerformance::performance(
- *frame_or_imported_document_->GetDocument().domWindow())
+ DOMWindowPerformance::performance(*document_->domWindow())
->GenerateAndAddResourceTiming(info);
}
@@ -509,8 +444,7 @@ void FrameFetchContext::ModifyRequestForCSP(ResourceRequest& resource_request) {
GetFrame()->Loader().RecordLatestRequiredCSP();
GetFrame()->Loader().ModifyRequestForCSP(
resource_request,
- &GetResourceFetcherProperties().GetFetchClientSettingsObject(),
- &frame_or_imported_document_->GetDocument(),
+ &GetResourceFetcherProperties().GetFetchClientSettingsObject(), document_,
mojom::RequestContextFrameType::kNone);
}
@@ -533,12 +467,12 @@ void FrameFetchContext::AddClientHintsIfNecessary(
// When the runtime flag "FeaturePolicyForClientHints" is enabled, feature
// policy is used to enable hints for all subresources, based on the policy of
// the requesting document, and the origin of the resource.
- const FeaturePolicy* policy = nullptr;
- if (frame_or_imported_document_) {
- policy = frame_or_imported_document_->GetDocument()
- .GetSecurityContext()
- .GetFeaturePolicy();
- }
+ const FeaturePolicy* policy =
+ document_ ? document_->GetSecurityContext().GetFeaturePolicy() : nullptr;
+
+ url::Origin resource_origin =
+ SecurityOrigin::Create(request.Url())->ToUrlOrigin();
+ bool is_1p_origin = IsFirstPartyOrigin(request.Url());
// Sec-CH-UA is special: we always send the header to all origins that are
// eligible for client hints (e.g. secure transport, JavaScript enabled).
@@ -549,49 +483,64 @@ void FrameFetchContext::AddClientHintsIfNecessary(
// specifying accomponying client hints, in which case we disable sending
// them.
base::Optional<UserAgentMetadata> ua = GetUserAgentMetadata();
- if (RuntimeEnabledFeatures::UserAgentClientHintEnabled() && ua.has_value()) {
- request.SetHttpHeaderField(
- blink::kClientHintsHeaderMapping[static_cast<size_t>(
- mojom::blink::WebClientHintsType::kUA)],
- AddBrandVersionQuotes(ua->brand, ua->major_version));
+ if (ClientHintsPreferences::UserAgentClientHintEnabled() && ua.has_value()) {
+ // ShouldSendClientHint is called to make sure UA is controlled by
+ // FeaturePolicy.
+ if (ShouldSendClientHint(ClientHintsMode::kStandard, policy,
+ resource_origin, is_1p_origin,
+ network::mojom::blink::WebClientHintsType::kUA,
+ hints_preferences, enabled_hints)) {
+ request.SetHttpHeaderField(
+ blink::kClientHintsHeaderMapping[static_cast<size_t>(
+ network::mojom::blink::WebClientHintsType::kUA)],
+ ua->SerializeBrandVersionList().c_str());
+ }
// We also send Sec-CH-UA-Mobile to all hints. It is a one-bit header
// identifying if the browser has opted for a "mobile" experience
// Formatted using the "sh-boolean" format from:
// https://httpwg.org/http-extensions/draft-ietf-httpbis-header-structure.html#boolean
- request.SetHttpHeaderField(
- blink::kClientHintsHeaderMapping[static_cast<size_t>(
- mojom::blink::WebClientHintsType::kUAMobile)],
- ua->mobile ? "?1" : "?0");
+ // ShouldSendClientHint is called to make sure it's controlled by
+ // FeaturePolicy.
+ if (ShouldSendClientHint(
+ ClientHintsMode::kStandard, policy, resource_origin, is_1p_origin,
+ network::mojom::blink::WebClientHintsType::kUAMobile,
+ hints_preferences, enabled_hints)) {
+ request.SetHttpHeaderField(
+ blink::kClientHintsHeaderMapping[static_cast<size_t>(
+ network::mojom::blink::WebClientHintsType::kUAMobile)],
+ ua->mobile ? "?1" : "?0");
+ }
}
// If the frame is detached, then don't send any hints other than UA.
if (!policy)
return;
- url::Origin resource_origin =
- SecurityOrigin::Create(request.Url())->ToUrlOrigin();
- bool is_1p_origin = IsFirstPartyOrigin(request.Url());
if (!RuntimeEnabledFeatures::FeaturePolicyForClientHintsEnabled() &&
- !base::FeatureList::IsEnabled(kAllowClientHintsToThirdParty) &&
+ !base::FeatureList::IsEnabled(features::kAllowClientHintsToThirdParty) &&
!is_1p_origin) {
// No client hints for 3p origins.
return;
}
- // Persisted client hints preferences should be read for only the first
- // party origins.
- if (is_1p_origin && GetContentSettingsClient()) {
- GetContentSettingsClient()->GetAllowedClientHintsFromSource(request.Url(),
- &enabled_hints);
+ // Persisted client hints preferences should be read for the top-frame's
+ // origin.
+ if (GetContentSettingsClient() &&
+ !GetResourceFetcherProperties().IsDetached()) {
+ const SecurityOrigin* top_security_origin =
+ GetFrame()->Tree().Top().GetSecurityContext()->GetSecurityOrigin();
+ if (!top_security_origin->IsOpaque()) {
+ GetContentSettingsClient()->GetAllowedClientHintsFromSource(
+ KURL(top_security_origin->ToString()), &enabled_hints);
+ }
}
// The next 4 hints should be enabled if we're allowing legacy hints to third
// parties, or if FeaturePolicy delegation says they are allowed.
if (ShouldSendClientHint(
ClientHintsMode::kLegacy, policy, resource_origin, is_1p_origin,
- mojom::blink::WebClientHintsType::kDeviceMemory,
- mojom::blink::FeaturePolicyFeature::kClientHintDeviceMemory,
+ network::mojom::blink::WebClientHintsType::kDeviceMemory,
hints_preferences, enabled_hints)) {
request.SetHttpHeaderField(
"Device-Memory",
@@ -601,16 +550,15 @@ void FrameFetchContext::AddClientHintsIfNecessary(
float dpr = GetDevicePixelRatio();
if (ShouldSendClientHint(ClientHintsMode::kLegacy, policy, resource_origin,
- is_1p_origin, mojom::blink::WebClientHintsType::kDpr,
- mojom::blink::FeaturePolicyFeature::kClientHintDPR,
+ is_1p_origin,
+ network::mojom::blink::WebClientHintsType::kDpr,
hints_preferences, enabled_hints)) {
request.SetHttpHeaderField("DPR", AtomicString(String::Number(dpr)));
}
if (ShouldSendClientHint(
ClientHintsMode::kLegacy, policy, resource_origin, is_1p_origin,
- mojom::blink::WebClientHintsType::kViewportWidth,
- mojom::blink::FeaturePolicyFeature::kClientHintViewportWidth,
+ network::mojom::blink::WebClientHintsType::kViewportWidth,
hints_preferences, enabled_hints) &&
!GetResourceFetcherProperties().IsDetached() && GetFrame()->View()) {
request.SetHttpHeaderField(
@@ -618,11 +566,10 @@ void FrameFetchContext::AddClientHintsIfNecessary(
AtomicString(String::Number(GetFrame()->View()->ViewportWidth())));
}
- if (ShouldSendClientHint(ClientHintsMode::kLegacy, policy, resource_origin,
- is_1p_origin,
- mojom::blink::WebClientHintsType::kResourceWidth,
- mojom::blink::FeaturePolicyFeature::kClientHintWidth,
- hints_preferences, enabled_hints)) {
+ if (ShouldSendClientHint(
+ ClientHintsMode::kLegacy, policy, resource_origin, is_1p_origin,
+ network::mojom::blink::WebClientHintsType::kResourceWidth,
+ hints_preferences, enabled_hints)) {
if (resource_width.is_set) {
float physical_width = resource_width.width * dpr;
request.SetHttpHeaderField(
@@ -631,8 +578,8 @@ void FrameFetchContext::AddClientHintsIfNecessary(
}
if (ShouldSendClientHint(ClientHintsMode::kStandard, policy, resource_origin,
- is_1p_origin, mojom::blink::WebClientHintsType::kRtt,
- mojom::blink::FeaturePolicyFeature::kClientHintRTT,
+ is_1p_origin,
+ network::mojom::blink::WebClientHintsType::kRtt,
hints_preferences, enabled_hints)) {
base::Optional<base::TimeDelta> http_rtt =
GetNetworkStateNotifier().GetWebHoldbackHttpRtt();
@@ -644,14 +591,13 @@ void FrameFetchContext::AddClientHintsIfNecessary(
GetNetworkStateNotifier().RoundRtt(request.Url().Host(), http_rtt);
request.SetHttpHeaderField(
blink::kClientHintsHeaderMapping[static_cast<size_t>(
- mojom::blink::WebClientHintsType::kRtt)],
+ network::mojom::blink::WebClientHintsType::kRtt)],
AtomicString(String::Number(rtt)));
}
if (ShouldSendClientHint(
ClientHintsMode::kStandard, policy, resource_origin, is_1p_origin,
- mojom::blink::WebClientHintsType::kDownlink,
- mojom::blink::FeaturePolicyFeature::kClientHintDownlink,
+ network::mojom::blink::WebClientHintsType::kDownlink,
hints_preferences, enabled_hints)) {
base::Optional<double> throughput_mbps =
GetNetworkStateNotifier().GetWebHoldbackDownlinkThroughputMbps();
@@ -663,13 +609,13 @@ void FrameFetchContext::AddClientHintsIfNecessary(
throughput_mbps);
request.SetHttpHeaderField(
blink::kClientHintsHeaderMapping[static_cast<size_t>(
- mojom::blink::WebClientHintsType::kDownlink)],
+ network::mojom::blink::WebClientHintsType::kDownlink)],
AtomicString(String::Number(mbps)));
}
if (ShouldSendClientHint(ClientHintsMode::kStandard, policy, resource_origin,
- is_1p_origin, mojom::blink::WebClientHintsType::kEct,
- mojom::blink::FeaturePolicyFeature::kClientHintECT,
+ is_1p_origin,
+ network::mojom::blink::WebClientHintsType::kEct,
hints_preferences, enabled_hints)) {
base::Optional<WebEffectiveConnectionType> holdback_ect =
GetNetworkStateNotifier().GetWebHoldbackEffectiveType();
@@ -678,19 +624,18 @@ void FrameFetchContext::AddClientHintsIfNecessary(
request.SetHttpHeaderField(
blink::kClientHintsHeaderMapping[static_cast<size_t>(
- mojom::blink::WebClientHintsType::kEct)],
+ network::mojom::blink::WebClientHintsType::kEct)],
AtomicString(NetworkStateNotifier::EffectiveConnectionTypeToString(
holdback_ect.value())));
}
if (ShouldSendClientHint(ClientHintsMode::kStandard, policy, resource_origin,
is_1p_origin,
- mojom::blink::WebClientHintsType::kLang,
- mojom::blink::FeaturePolicyFeature::kClientHintLang,
+ network::mojom::blink::WebClientHintsType::kLang,
hints_preferences, enabled_hints)) {
request.SetHttpHeaderField(
blink::kClientHintsHeaderMapping[static_cast<size_t>(
- mojom::blink::WebClientHintsType::kLang)],
+ network::mojom::blink::WebClientHintsType::kLang)],
GetFrame()
->DomWindow()
->navigator()
@@ -700,49 +645,56 @@ void FrameFetchContext::AddClientHintsIfNecessary(
if (ua.has_value() &&
ShouldSendClientHint(
ClientHintsMode::kStandard, policy, resource_origin, is_1p_origin,
- mojom::blink::WebClientHintsType::kUAArch,
- mojom::blink::FeaturePolicyFeature::kClientHintUAArch,
+ network::mojom::blink::WebClientHintsType::kUAArch,
+ hints_preferences, enabled_hints)) {
+ request.SetHttpHeaderField(
+ blink::kClientHintsHeaderMapping[static_cast<size_t>(
+ network::mojom::blink::WebClientHintsType::kUAArch)],
+ SerializeHeaderString(ua->architecture));
+ }
+
+ if (ua.has_value() &&
+ ShouldSendClientHint(
+ ClientHintsMode::kStandard, policy, resource_origin, is_1p_origin,
+ network::mojom::blink::WebClientHintsType::kUAPlatform,
hints_preferences, enabled_hints)) {
request.SetHttpHeaderField(
blink::kClientHintsHeaderMapping[static_cast<size_t>(
- mojom::blink::WebClientHintsType::kUAArch)],
- AddQuotes(ua->architecture));
+ network::mojom::blink::WebClientHintsType::kUAPlatform)],
+ SerializeHeaderString(ua->platform));
}
if (ua.has_value() &&
ShouldSendClientHint(
ClientHintsMode::kStandard, policy, resource_origin, is_1p_origin,
- mojom::blink::WebClientHintsType::kUAPlatform,
- mojom::blink::FeaturePolicyFeature::kClientHintUAPlatform,
+ network::mojom::blink::WebClientHintsType::kUAPlatformVersion,
hints_preferences, enabled_hints)) {
request.SetHttpHeaderField(
blink::kClientHintsHeaderMapping[static_cast<size_t>(
- mojom::blink::WebClientHintsType::kUAPlatform)],
- AddBrandVersionQuotes(ua->platform, ua->platform_version));
+ network::mojom::blink::WebClientHintsType::kUAPlatformVersion)],
+ SerializeHeaderString(ua->platform_version));
}
if (ua.has_value() &&
ShouldSendClientHint(
ClientHintsMode::kStandard, policy, resource_origin, is_1p_origin,
- mojom::blink::WebClientHintsType::kUAModel,
- mojom::blink::FeaturePolicyFeature::kClientHintUAModel,
+ network::mojom::blink::WebClientHintsType::kUAModel,
hints_preferences, enabled_hints)) {
request.SetHttpHeaderField(
blink::kClientHintsHeaderMapping[static_cast<size_t>(
- mojom::blink::WebClientHintsType::kUAModel)],
- AddQuotes(ua->model));
+ network::mojom::blink::WebClientHintsType::kUAModel)],
+ SerializeHeaderString(ua->model));
}
if (ua.has_value() &&
ShouldSendClientHint(
ClientHintsMode::kStandard, policy, resource_origin, is_1p_origin,
- mojom::blink::WebClientHintsType::kUAFullVersion,
- mojom::blink::FeaturePolicyFeature::kClientHintUAFullVersion,
+ network::mojom::blink::WebClientHintsType::kUAFullVersion,
hints_preferences, enabled_hints)) {
request.SetHttpHeaderField(
blink::kClientHintsHeaderMapping[static_cast<size_t>(
- mojom::blink::WebClientHintsType::kUAFullVersion)],
- AddQuotes(ua->full_version));
+ network::mojom::blink::WebClientHintsType::kUAFullVersion)],
+ SerializeHeaderString(ua->full_version));
}
}
@@ -751,6 +703,9 @@ void FrameFetchContext::PopulateResourceRequest(
const ClientHintsPreferences& hints_preferences,
const FetchParameters::ResourceWidth& resource_width,
ResourceRequest& request) {
+ if (!GetResourceFetcherProperties().IsDetached())
+ probe::SetDevToolsIds(Probe(), request);
+
ModifyRequestForCSP(request);
AddClientHintsIfNecessary(hints_preferences, resource_width, request);
@@ -824,8 +779,7 @@ bool FrameFetchContext::ShouldBypassMainWorldCSP() const {
if (GetResourceFetcherProperties().IsDetached())
return false;
- return ContentSecurityPolicy::ShouldBypassMainWorld(
- GetFrame()->GetDocument()->ToExecutionContext());
+ return ContentSecurityPolicy::ShouldBypassMainWorld(GetFrame()->DomWindow());
}
bool FrameFetchContext::IsSVGImageChromeClient() const {
@@ -876,13 +830,15 @@ bool FrameFetchContext::ShouldBlockFetchByMixedContentCheck(
mojom::RequestContextType request_context,
ResourceRequest::RedirectStatus redirect_status,
const KURL& url,
- ReportingDisposition reporting_disposition) const {
+ ReportingDisposition reporting_disposition,
+ const base::Optional<String>& devtools_id) const {
if (GetResourceFetcherProperties().IsDetached()) {
// TODO(yhirano): Implement the detached case.
return false;
}
return MixedContentChecker::ShouldBlockFetch(
- GetFrame(), request_context, redirect_status, url, reporting_disposition);
+ GetFrame(), request_context, redirect_status, url, devtools_id,
+ reporting_disposition);
}
bool FrameFetchContext::ShouldBlockFetchAsCredentialedSubresource(
@@ -919,7 +875,7 @@ bool FrameFetchContext::ShouldBlockFetchAsCredentialedSubresource(
const KURL& FrameFetchContext::Url() const {
if (GetResourceFetcherProperties().IsDetached())
return frozen_state_->url;
- return frame_or_imported_document_->GetDocument().Url();
+ return document_->Url();
}
const SecurityOrigin* FrameFetchContext::GetParentSecurityOrigin() const {
@@ -935,20 +891,14 @@ const ContentSecurityPolicy* FrameFetchContext::GetContentSecurityPolicy()
const {
if (GetResourceFetcherProperties().IsDetached())
return frozen_state_->content_security_policy;
- return frame_or_imported_document_->GetDocument().GetContentSecurityPolicy();
+ return document_->GetContentSecurityPolicy();
}
void FrameFetchContext::AddConsoleMessage(ConsoleMessage* message) const {
if (GetResourceFetcherProperties().IsDetached())
return;
- // Route the console message through Document if it's attached, so
- // that script line numbers can be included. Otherwise, route directly to the
- // FrameConsole, to ensure we never drop a message.
- if (frame_or_imported_document_->GetDocument().GetFrame())
- frame_or_imported_document_->GetDocument().AddConsoleMessage(message);
- else
- GetFrame()->Console().AddMessage(message);
+ document_->AddConsoleMessage(message);
}
WebContentSettingsClient* FrameFetchContext::GetContentSettingsClient() const {
@@ -977,18 +927,24 @@ base::Optional<UserAgentMetadata> FrameFetchContext::GetUserAgentMetadata()
return GetLocalFrameClient()->UserAgentMetadata();
}
+const FeaturePolicy* FrameFetchContext::GetFeaturePolicy() const {
+ return document_ ? document_->GetSecurityContext().GetFeaturePolicy()
+ : nullptr;
+}
+
const ClientHintsPreferences FrameFetchContext::GetClientHintsPreferences()
const {
if (GetResourceFetcherProperties().IsDetached())
return frozen_state_->client_hints_preferences;
- LocalFrame* frame = frame_or_imported_document_->GetDocument().GetFrame();
- return frame ? frame->GetClientHintsPreferences() : ClientHintsPreferences();
+ LocalFrame* frame = document_->GetFrame();
+ DCHECK(frame);
+ return frame->GetClientHintsPreferences();
}
float FrameFetchContext::GetDevicePixelRatio() const {
if (GetResourceFetcherProperties().IsDetached())
return frozen_state_->device_pixel_ratio;
- return frame_or_imported_document_->GetDocument().DevicePixelRatio();
+ return document_->DevicePixelRatio();
}
bool FrameFetchContext::ShouldSendClientHint(
@@ -996,18 +952,19 @@ bool FrameFetchContext::ShouldSendClientHint(
const FeaturePolicy* policy,
const url::Origin& resource_origin,
bool is_1p_origin,
- mojom::blink::WebClientHintsType type,
- mojom::blink::FeaturePolicyFeature feature_policy_feature,
+ network::mojom::blink::WebClientHintsType type,
const ClientHintsPreferences& hints_preferences,
const WebEnabledClientHints& enabled_hints) const {
bool origin_ok;
if (mode == ClientHintsMode::kLegacy &&
- base::FeatureList::IsEnabled(kAllowClientHintsToThirdParty)) {
+ base::FeatureList::IsEnabled(features::kAllowClientHintsToThirdParty)) {
origin_ok = true;
} else if (RuntimeEnabledFeatures::FeaturePolicyForClientHintsEnabled()) {
- origin_ok = (policy && policy->IsFeatureEnabledForOrigin(
- feature_policy_feature, resource_origin));
+ origin_ok =
+ (policy && policy->IsFeatureEnabledForOrigin(
+ kClientHintsFeaturePolicyMapping[static_cast<int>(type)],
+ resource_origin));
} else {
origin_ok = is_1p_origin;
}
@@ -1018,8 +975,10 @@ bool FrameFetchContext::ShouldSendClientHint(
// |hints_preferences| is used only in case of the preload scanner;
// GetClientHintsPreferences() has things parsed for this document
// normally (whether via headers of http-equiv), and |enabled_hints| are
- // previously persistent settings.
- return GetClientHintsPreferences().ShouldSend(type) ||
+ // previously persistent settings (which may include those from current
+ // document if IPCs got through already).
+ return IsClientHintSentByDefault(type) ||
+ GetClientHintsPreferences().ShouldSend(type) ||
hints_preferences.ShouldSend(type) || enabled_hints.IsEnabled(type);
}
@@ -1032,22 +991,25 @@ FetchContext* FrameFetchContext::Detach() {
GetSiteForCookies(), GetTopFrameOrigin(), GetClientHintsPreferences(),
GetDevicePixelRatio(), GetUserAgent(), GetUserAgentMetadata(),
IsSVGImageChromeClient());
- frame_or_imported_document_ = nullptr;
+ document_loader_ = nullptr;
+ document_ = nullptr;
return this;
}
void FrameFetchContext::Trace(Visitor* visitor) {
- visitor->Trace(frame_or_imported_document_);
+ visitor->Trace(document_loader_);
+ visitor->Trace(document_);
visitor->Trace(frozen_state_);
BaseFetchContext::Trace(visitor);
}
bool FrameFetchContext::CalculateIfAdSubresource(
const ResourceRequest& resource_request,
- ResourceType type) {
+ ResourceType type,
+ const FetchInitiatorInfo& initiator_info) {
// Mark the resource as an Ad if the SubresourceFilter thinks it's an ad.
- bool known_ad =
- BaseFetchContext::CalculateIfAdSubresource(resource_request, type);
+ bool known_ad = BaseFetchContext::CalculateIfAdSubresource(
+ resource_request, type, initiator_info);
if (GetResourceFetcherProperties().IsDetached() ||
!GetFrame()->GetAdTracker()) {
return known_ad;
@@ -1056,8 +1018,7 @@ bool FrameFetchContext::CalculateIfAdSubresource(
// The AdTracker needs to know about the request as well, and may also mark it
// as an ad.
return GetFrame()->GetAdTracker()->CalculateIfAdSubresource(
- frame_or_imported_document_->GetDocument().ToExecutionContext(),
- resource_request, type, known_ad);
+ document_->domWindow(), resource_request, type, initiator_info, known_ad);
}
bool FrameFetchContext::SendConversionRequestInsteadOfRedirecting(
@@ -1067,12 +1028,16 @@ bool FrameFetchContext::SendConversionRequestInsteadOfRedirecting(
if (!RuntimeEnabledFeatures::ConversionMeasurementEnabled())
return false;
+ if (GetResourceFetcherProperties().IsDetached())
+ return false;
+
+ LocalFrame* frame = document_->GetFrame();
+ DCHECK(frame);
// Only register conversions pings that are redirects in the main frame.
// TODO(https://crbug.com/1042919): This should also validate that the
// redirect is same origin to ensure that the reporting domain has consented
// to the registration event.
- if (!frame_or_imported_document_ || !GetFrame() ||
- !GetFrame()->IsMainFrame() ||
+ if (!frame->IsMainFrame() ||
redirect_status != ResourceRequest::RedirectStatus::kFollowedRedirect) {
return false;
}
@@ -1082,6 +1047,17 @@ bool FrameFetchContext::SendConversionRequestInsteadOfRedirecting(
if (url.GetPath() != kWellKnownConversionRegsitrationPath)
return false;
+ if (!document_->IsFeatureEnabled(
+ mojom::blink::FeaturePolicyFeature::kConversionMeasurement)) {
+ String message =
+ "The 'conversion-measurement' feature policy must be enabled to "
+ "register a conversion.";
+ document_->AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>(
+ mojom::blink::ConsoleMessageSource::kOther,
+ mojom::blink::ConsoleMessageLevel::kError, message));
+ return false;
+ }
+
// Only allow conversion registration on secure pages with a secure conversion
// redirect.
scoped_refptr<const SecurityOrigin> redirect_origin =
@@ -1134,8 +1110,7 @@ base::Optional<ResourceRequestBlockedReason> FrameFetchContext::CanRequest(
ReportingDisposition reporting_disposition,
ResourceRequest::RedirectStatus redirect_status) const {
if (!GetResourceFetcherProperties().IsDetached() &&
- frame_or_imported_document_->GetDocument().IsFreezingInProgress() &&
- !resource_request.GetKeepalive()) {
+ document_->IsFreezingInProgress() && !resource_request.GetKeepalive()) {
AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>(
mojom::ConsoleMessageSource::kJavaScript,
mojom::ConsoleMessageLevel::kError,
diff --git a/chromium/third_party/blink/renderer/core/loader/frame_fetch_context.h b/chromium/third_party/blink/renderer/core/loader/frame_fetch_context.h
index 9c6d325bce5..caf0421f52f 100644
--- a/chromium/third_party/blink/renderer/core/loader/frame_fetch_context.h
+++ b/chromium/third_party/blink/renderer/core/loader/frame_fetch_context.h
@@ -33,9 +33,9 @@ n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
#include "base/optional.h"
#include "base/single_thread_task_runner.h"
+#include "services/network/public/mojom/web_client_hints_types.mojom-blink-forward.h"
#include "third_party/blink/public/common/user_agent/user_agent_metadata.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_object.mojom-blink-forward.h"
-#include "third_party/blink/public/mojom/web_client_hints/web_client_hints_types.mojom-blink-forward.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/loader/base_fetch_context.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
@@ -54,7 +54,6 @@ class ContentSecurityPolicy;
class CoreProbeSink;
class Document;
class DocumentLoader;
-class FrameOrImportedDocument;
class LocalFrame;
class LocalFrameClient;
class Settings;
@@ -64,11 +63,8 @@ class CORE_EXPORT FrameFetchContext final : public BaseFetchContext {
public:
static ResourceFetcher* CreateFetcherForCommittedDocument(DocumentLoader&,
Document&);
- // Used for creating a FrameFetchContext for an imported Document.
- // |document_loader_| will be set to nullptr.
- static ResourceFetcher* CreateFetcherForImportedDocument(Document* document);
-
- FrameFetchContext(const FrameOrImportedDocument&,
+ FrameFetchContext(DocumentLoader& document_loader,
+ Document& document,
const DetachableResourceFetcherProperties&);
~FrameFetchContext() override = default;
@@ -107,8 +103,10 @@ class CORE_EXPORT FrameFetchContext final : public BaseFetchContext {
void Trace(Visitor*) override;
- bool CalculateIfAdSubresource(const ResourceRequest& resource_request,
- ResourceType type) override;
+ bool CalculateIfAdSubresource(
+ const ResourceRequest& resource_request,
+ ResourceType type,
+ const FetchInitiatorInfo& initiator_info) override;
bool SendConversionRequestInsteadOfRedirecting(
const KURL& url,
@@ -151,10 +149,12 @@ class CORE_EXPORT FrameFetchContext final : public BaseFetchContext {
bool ShouldBlockWebSocketByMixedContentCheck(const KURL&) const override;
std::unique_ptr<WebSocketHandshakeThrottle> CreateWebSocketHandshakeThrottle()
override;
- bool ShouldBlockFetchByMixedContentCheck(mojom::RequestContextType,
- ResourceRequest::RedirectStatus,
- const KURL&,
- ReportingDisposition) const override;
+ bool ShouldBlockFetchByMixedContentCheck(
+ mojom::blink::RequestContextType request_context,
+ ResourceRequest::RedirectStatus redirect_status,
+ const KURL& url,
+ ReportingDisposition reporting_disposition,
+ const base::Optional<String>& devtools_id) const override;
bool ShouldBlockFetchAsCredentialedSubresource(const ResourceRequest&,
const KURL&) const override;
@@ -167,6 +167,7 @@ class CORE_EXPORT FrameFetchContext final : public BaseFetchContext {
Settings* GetSettings() const;
String GetUserAgent() const;
base::Optional<UserAgentMetadata> GetUserAgentMetadata() const;
+ const FeaturePolicy* GetFeaturePolicy() const override;
const ClientHintsPreferences GetClientHintsPreferences() const;
float GetDevicePixelRatio() const;
@@ -175,8 +176,7 @@ class CORE_EXPORT FrameFetchContext final : public BaseFetchContext {
const FeaturePolicy*,
const url::Origin& resource_origin,
bool is_1p_origin,
- mojom::blink::WebClientHintsType,
- mojom::blink::FeaturePolicyFeature,
+ network::mojom::blink::WebClientHintsType,
const ClientHintsPreferences&,
const WebEnabledClientHints&) const;
void SetFirstPartyCookie(ResourceRequest&);
@@ -195,7 +195,8 @@ class CORE_EXPORT FrameFetchContext final : public BaseFetchContext {
CoreProbeSink* Probe() const;
- Member<const FrameOrImportedDocument> frame_or_imported_document_;
+ Member<DocumentLoader> document_loader_;
+ Member<Document> document_;
// The value of |save_data_enabled_| is read once per frame from
// NetworkStateNotifier, which is guarded by a mutex lock, and cached locally
diff --git a/chromium/third_party/blink/renderer/core/loader/frame_fetch_context_test.cc b/chromium/third_party/blink/renderer/core/loader/frame_fetch_context_test.cc
index 403758d3604..6102a61dc8c 100644
--- a/chromium/third_party/blink/renderer/core/loader/frame_fetch_context_test.cc
+++ b/chromium/third_party/blink/renderer/core/loader/frame_fetch_context_test.cc
@@ -184,7 +184,7 @@ class FrameFetchContextSubresourceFilterTest : public FrameFetchContextTest {
bool is_associated_with_ad_subframe = false) {
document->Loader()->SetSubresourceFilter(
MakeGarbageCollected<SubresourceFilter>(
- document->ToExecutionContext(),
+ document->GetExecutionContext(),
std::make_unique<FixedPolicySubresourceFilter>(
policy, &filtered_load_callback_counter_,
is_associated_with_ad_subframe)));
@@ -208,19 +208,20 @@ class FrameFetchContextSubresourceFilterTest : public FrameFetchContextTest {
base::Optional<ResourceRequestBlockedReason> reason =
CanRequestInternal(ReportingDisposition::kReport);
ResourceRequest request(KURL("http://example.com/"));
+ FetchInitiatorInfo initiator_info;
EXPECT_EQ(expect_is_ad, GetFetchContext()->CalculateIfAdSubresource(
- request, ResourceType::kMock));
+ request, ResourceType::kMock, initiator_info));
return reason;
}
void AppendExecutingScriptToAdTracker(const String& url) {
AdTracker* ad_tracker = document->GetFrame()->GetAdTracker();
- ad_tracker->WillExecuteScript(document->ToExecutionContext(), url);
+ ad_tracker->WillExecuteScript(document->GetExecutionContext(), url);
}
void AppendAdScriptToAdTracker(const KURL& ad_script_url) {
AdTracker* ad_tracker = document->GetFrame()->GetAdTracker();
- ad_tracker->AppendToKnownAdScripts(*document->ToExecutionContext(),
+ ad_tracker->AppendToKnownAdScripts(*document->GetExecutionContext(),
ad_script_url.GetString());
}
@@ -236,6 +237,7 @@ class FrameFetchContextSubresourceFilterTest : public FrameFetchContextTest {
.GetFetchClientSettingsObject()
.GetSecurityOrigin());
ResourceLoaderOptions options;
+ // DJKim
return GetFetchContext()->CanRequest(
ResourceType::kImage, resource_request, input_url, options,
reporting_disposition, ResourceRequest::RedirectStatus::kNoRedirect);
@@ -642,7 +644,8 @@ class FrameFetchContextHintsTest : public FrameFetchContextTest {
TEST_F(FrameFetchContextHintsTest, MonitorDeviceMemorySecureTransport) {
ExpectHeader("https://www.example.com/1.gif", "Device-Memory", false, "");
ClientHintsPreferences preferences;
- preferences.SetShouldSendForTesting(mojom::WebClientHintsType::kDeviceMemory);
+ preferences.SetShouldSendForTesting(
+ network::mojom::WebClientHintsType::kDeviceMemory);
document->GetFrame()->GetClientHintsPreferences().UpdateFrom(preferences);
ApproximatedDeviceMemory::SetPhysicalMemoryMBForTesting(4096);
ExpectHeader("https://www.example.com/1.gif", "Device-Memory", true, "4");
@@ -669,7 +672,8 @@ TEST_F(FrameFetchContextHintsTest, MonitorDeviceMemoryHintsInsecureContext) {
// to a secure context and the persistent client hint features is enabled.
ExpectHeader("http://www.example.com/1.gif", "Device-Memory", false, "");
ClientHintsPreferences preferences;
- preferences.SetShouldSendForTesting(mojom::WebClientHintsType::kDeviceMemory);
+ preferences.SetShouldSendForTesting(
+ network::mojom::WebClientHintsType::kDeviceMemory);
document->GetFrame()->GetClientHintsPreferences().UpdateFrom(preferences);
ApproximatedDeviceMemory::SetPhysicalMemoryMBForTesting(4096);
ExpectHeader("http://www.example.com/1.gif", "Device-Memory", false, "");
@@ -685,7 +689,8 @@ TEST_F(FrameFetchContextHintsTest, MonitorDeviceMemoryHintsLocalContext) {
document->GetSettings()->SetScriptEnabled(true);
ExpectHeader("http://localhost/1.gif", "Device-Memory", false, "");
ClientHintsPreferences preferences;
- preferences.SetShouldSendForTesting(mojom::WebClientHintsType::kDeviceMemory);
+ preferences.SetShouldSendForTesting(
+ network::mojom::WebClientHintsType::kDeviceMemory);
document->GetFrame()->GetClientHintsPreferences().UpdateFrom(preferences);
ApproximatedDeviceMemory::SetPhysicalMemoryMBForTesting(4096);
ExpectHeader("http://localhost/1.gif", "Device-Memory", true, "4");
@@ -697,7 +702,8 @@ TEST_F(FrameFetchContextHintsTest, MonitorDeviceMemoryHintsLocalContext) {
TEST_F(FrameFetchContextHintsTest, MonitorDeviceMemoryHints) {
ExpectHeader("https://www.example.com/1.gif", "Device-Memory", false, "");
ClientHintsPreferences preferences;
- preferences.SetShouldSendForTesting(mojom::WebClientHintsType::kDeviceMemory);
+ preferences.SetShouldSendForTesting(
+ network::mojom::WebClientHintsType::kDeviceMemory);
document->GetFrame()->GetClientHintsPreferences().UpdateFrom(preferences);
ApproximatedDeviceMemory::SetPhysicalMemoryMBForTesting(4096);
ExpectHeader("https://www.example.com/1.gif", "Device-Memory", true, "4");
@@ -715,7 +721,7 @@ TEST_F(FrameFetchContextHintsTest, MonitorDeviceMemoryHints) {
TEST_F(FrameFetchContextHintsTest, MonitorDPRHints) {
ExpectHeader("https://www.example.com/1.gif", "DPR", false, "");
ClientHintsPreferences preferences;
- preferences.SetShouldSendForTesting(mojom::WebClientHintsType::kDpr);
+ preferences.SetShouldSendForTesting(network::mojom::WebClientHintsType::kDpr);
document->GetFrame()->GetClientHintsPreferences().UpdateFrom(preferences);
ExpectHeader("https://www.example.com/1.gif", "DPR", true, "1");
dummy_page_holder->GetPage().SetDeviceScaleFactorDeprecated(2.5);
@@ -736,7 +742,7 @@ TEST_F(FrameFetchContextHintsTest, MonitorResourceWidthHints) {
ExpectHeader("https://www.example.com/1.gif", "Width", false, "");
ClientHintsPreferences preferences;
preferences.SetShouldSendForTesting(
- mojom::WebClientHintsType::kResourceWidth);
+ network::mojom::WebClientHintsType::kResourceWidth);
document->GetFrame()->GetClientHintsPreferences().UpdateFrom(preferences);
ExpectHeader("https://www.example.com/1.gif", "Width", true, "500", 500);
ExpectHeader("https://www.example.com/1.gif", "Width", true, "667", 666.6666);
@@ -751,7 +757,7 @@ TEST_F(FrameFetchContextHintsTest, MonitorViewportWidthHints) {
ExpectHeader("https://www.example.com/1.gif", "Viewport-Width", false, "");
ClientHintsPreferences preferences;
preferences.SetShouldSendForTesting(
- mojom::WebClientHintsType::kViewportWidth);
+ network::mojom::WebClientHintsType::kViewportWidth);
document->GetFrame()->GetClientHintsPreferences().UpdateFrom(preferences);
ExpectHeader("https://www.example.com/1.gif", "Viewport-Width", true, "500");
dummy_page_holder->GetFrameView().SetLayoutSizeFixedToFrameSize(false);
@@ -767,7 +773,8 @@ TEST_F(FrameFetchContextHintsTest, MonitorLangHint) {
ExpectHeader("http://www.example.com/1.gif", "Sec-CH-Lang", false, "");
ClientHintsPreferences preferences;
- preferences.SetShouldSendForTesting(mojom::WebClientHintsType::kLang);
+ preferences.SetShouldSendForTesting(
+ network::mojom::WebClientHintsType::kLang);
document->GetFrame()->GetClientHintsPreferences().UpdateFrom(preferences);
document->domWindow()->navigator()->SetLanguagesForTesting("en-US");
@@ -798,54 +805,94 @@ TEST_F(FrameFetchContextHintsTest, MonitorUAHints) {
ExpectHeader("https://www.example.com/1.gif", "Sec-CH-UA-Platform", false,
"");
ExpectHeader("http://www.example.com/1.gif", "Sec-CH-UA-Platform", false, "");
+ ExpectHeader("https://www.example.com/1.gif", "Sec-CH-UA-Platform-Version",
+ false, "");
+ ExpectHeader("http://www.example.com/1.gif", "Sec-CH-UA-Platform-Version",
+ false, "");
ExpectHeader("https://www.example.com/1.gif", "Sec-CH-UA-Model", false, "");
ExpectHeader("http://www.example.com/1.gif", "Sec-CH-UA-Model", false, "");
{
ClientHintsPreferences preferences;
- preferences.SetShouldSendForTesting(mojom::WebClientHintsType::kUAArch);
+ preferences.SetShouldSendForTesting(
+ network::mojom::WebClientHintsType::kUAArch);
document->GetFrame()->GetClientHintsPreferences().UpdateFrom(preferences);
ExpectHeader("https://www.example.com/1.gif", "Sec-CH-UA-Arch", true, "");
ExpectHeader("https://www.example.com/1.gif", "Sec-CH-UA-Platform", false,
"");
+ ExpectHeader("https://www.example.com/1.gif", "Sec-CH-UA-Platform-Version",
+ false, "");
ExpectHeader("https://www.example.com/1.gif", "Sec-CH-UA-Model", false, "");
ExpectHeader("http://www.example.com/1.gif", "Sec-CH-UA-Arch", false, "");
ExpectHeader("http://www.example.com/1.gif", "Sec-CH-UA-Platform", false,
"");
+ ExpectHeader("http://www.example.com/1.gif", "Sec-CH-UA-Platform-Version",
+ false, "");
ExpectHeader("http://www.example.com/1.gif", "Sec-CH-UA-Model", false, "");
}
{
ClientHintsPreferences preferences;
- preferences.SetShouldSendForTesting(mojom::WebClientHintsType::kUAPlatform);
+ preferences.SetShouldSendForTesting(
+ network::mojom::WebClientHintsType::kUAPlatform);
document->GetFrame()->GetClientHintsPreferences().UpdateFrom(preferences);
ExpectHeader("https://www.example.com/1.gif", "Sec-CH-UA-Arch", false, "");
ExpectHeader("https://www.example.com/1.gif", "Sec-CH-UA-Platform", true,
"");
+ ExpectHeader("https://www.example.com/1.gif", "Sec-CH-UA-Platform-Version",
+ false, "");
+ ExpectHeader("https://www.example.com/1.gif", "Sec-CH-UA-Model", false, "");
+
+ ExpectHeader("http://www.example.com/1.gif", "Sec-CH-UA-Arch", false, "");
+ ExpectHeader("http://www.example.com/1.gif", "Sec-CH-UA-Platform", false,
+ "");
+ ExpectHeader("http://www.example.com/1.gif", "Sec-CH-UA-Platform-Version",
+ false, "");
+ ExpectHeader("http://www.example.com/1.gif", "Sec-CH-UA-Model", false, "");
+ }
+
+ {
+ ClientHintsPreferences preferences;
+ preferences.SetShouldSendForTesting(
+ network::mojom::WebClientHintsType::kUAPlatformVersion);
+ document->GetFrame()->GetClientHintsPreferences().UpdateFrom(preferences);
+
+ ExpectHeader("https://www.example.com/1.gif", "Sec-CH-UA-Arch", false, "");
+ ExpectHeader("https://www.example.com/1.gif", "Sec-CH-UA-Platform", false,
+ "");
+ ExpectHeader("https://www.example.com/1.gif", "Sec-CH-UA-Platform-Version",
+ true, "");
ExpectHeader("https://www.example.com/1.gif", "Sec-CH-UA-Model", false, "");
ExpectHeader("http://www.example.com/1.gif", "Sec-CH-UA-Arch", false, "");
ExpectHeader("http://www.example.com/1.gif", "Sec-CH-UA-Platform", false,
"");
+ ExpectHeader("http://www.example.com/1.gif", "Sec-CH-UA-Platform-Version",
+ false, "");
ExpectHeader("http://www.example.com/1.gif", "Sec-CH-UA-Model", false, "");
}
{
ClientHintsPreferences preferences;
- preferences.SetShouldSendForTesting(mojom::WebClientHintsType::kUAModel);
+ preferences.SetShouldSendForTesting(
+ network::mojom::WebClientHintsType::kUAModel);
document->GetFrame()->GetClientHintsPreferences().UpdateFrom(preferences);
ExpectHeader("https://www.example.com/1.gif", "Sec-CH-UA-Arch", false, "");
ExpectHeader("https://www.example.com/1.gif", "Sec-CH-UA-Platform", false,
"");
+ ExpectHeader("https://www.example.com/1.gif", "Sec-CH-UA-Platform-Version",
+ false, "");
ExpectHeader("https://www.example.com/1.gif", "Sec-CH-UA-Model", true, "");
ExpectHeader("http://www.example.com/1.gif", "Sec-CH-UA-Arch", false, "");
ExpectHeader("http://www.example.com/1.gif", "Sec-CH-UA-Platform", false,
"");
+ ExpectHeader("http://www.example.com/1.gif", "Sec-CH-UA-Platform-Version",
+ false, "");
ExpectHeader("http://www.example.com/1.gif", "Sec-CH-UA-Model", false, "");
}
}
@@ -862,26 +909,36 @@ TEST_F(FrameFetchContextHintsTest, MonitorAllHints) {
ExpectHeader("https://www.example.com/1.gif", "Sec-CH-UA-Arch", false, "");
ExpectHeader("https://www.example.com/1.gif", "Sec-CH-UA-Platform", false,
"");
+ ExpectHeader("https://www.example.com/1.gif", "Sec-CH-UA-Platform-Version",
+ false, "");
ExpectHeader("https://www.example.com/1.gif", "Sec-CH-UA-Model", false, "");
// `Sec-CH-UA` is special.
ExpectHeader("https://www.example.com/1.gif", "Sec-CH-UA", true, "");
ClientHintsPreferences preferences;
- preferences.SetShouldSendForTesting(mojom::WebClientHintsType::kDeviceMemory);
- preferences.SetShouldSendForTesting(mojom::WebClientHintsType::kDpr);
preferences.SetShouldSendForTesting(
- mojom::WebClientHintsType::kResourceWidth);
+ network::mojom::WebClientHintsType::kDeviceMemory);
+ preferences.SetShouldSendForTesting(network::mojom::WebClientHintsType::kDpr);
+ preferences.SetShouldSendForTesting(
+ network::mojom::WebClientHintsType::kResourceWidth);
+ preferences.SetShouldSendForTesting(
+ network::mojom::WebClientHintsType::kViewportWidth);
+ preferences.SetShouldSendForTesting(network::mojom::WebClientHintsType::kRtt);
+ preferences.SetShouldSendForTesting(
+ network::mojom::WebClientHintsType::kDownlink);
+ preferences.SetShouldSendForTesting(network::mojom::WebClientHintsType::kEct);
+ preferences.SetShouldSendForTesting(
+ network::mojom::WebClientHintsType::kLang);
+ preferences.SetShouldSendForTesting(network::mojom::WebClientHintsType::kUA);
+ preferences.SetShouldSendForTesting(
+ network::mojom::WebClientHintsType::kUAArch);
+ preferences.SetShouldSendForTesting(
+ network::mojom::WebClientHintsType::kUAPlatform);
+ preferences.SetShouldSendForTesting(
+ network::mojom::WebClientHintsType::kUAPlatformVersion);
preferences.SetShouldSendForTesting(
- mojom::WebClientHintsType::kViewportWidth);
- preferences.SetShouldSendForTesting(mojom::WebClientHintsType::kRtt);
- preferences.SetShouldSendForTesting(mojom::WebClientHintsType::kDownlink);
- preferences.SetShouldSendForTesting(mojom::WebClientHintsType::kEct);
- preferences.SetShouldSendForTesting(mojom::WebClientHintsType::kLang);
- preferences.SetShouldSendForTesting(mojom::WebClientHintsType::kUA);
- preferences.SetShouldSendForTesting(mojom::WebClientHintsType::kUAArch);
- preferences.SetShouldSendForTesting(mojom::WebClientHintsType::kUAPlatform);
- preferences.SetShouldSendForTesting(mojom::WebClientHintsType::kUAModel);
+ network::mojom::WebClientHintsType::kUAModel);
ApproximatedDeviceMemory::SetPhysicalMemoryMBForTesting(4096);
document->GetFrame()->GetClientHintsPreferences().UpdateFrom(preferences);
ExpectHeader("https://www.example.com/1.gif", "Device-Memory", true, "4");
@@ -896,6 +953,8 @@ TEST_F(FrameFetchContextHintsTest, MonitorAllHints) {
ExpectHeader("https://www.example.com/1.gif", "Sec-CH-UA", true, "");
ExpectHeader("https://www.example.com/1.gif", "Sec-CH-UA-Arch", true, "");
ExpectHeader("https://www.example.com/1.gif", "Sec-CH-UA-Platform", true, "");
+ ExpectHeader("https://www.example.com/1.gif", "Sec-CH-UA-Platform-Version",
+ true, "");
ExpectHeader("https://www.example.com/1.gif", "Sec-CH-UA-Model", true, "");
// Value of network quality client hints may vary, so only check if the
@@ -923,24 +982,33 @@ TEST_F(FrameFetchContextHintsTest, MonitorAllHintsFeaturePolicy) {
RecreateFetchContext(
KURL("https://www.example.com/"),
"ch-dpr *; ch-device-memory *; ch-downlink *; ch-ect *; ch-lang *;"
- "ch-rtt *; ch-ua *; ch-ua-arch *; ch-ua-platform *; ch-ua-model *;"
+ "ch-rtt *; ch-ua *; ch-ua-arch *; ch-ua-platform *; "
+ "ch-ua-platform-version *; ch-ua-model *;"
"ch-viewport-width *; ch-width *");
document->GetSettings()->SetScriptEnabled(true);
ClientHintsPreferences preferences;
- preferences.SetShouldSendForTesting(mojom::WebClientHintsType::kDeviceMemory);
- preferences.SetShouldSendForTesting(mojom::WebClientHintsType::kDpr);
preferences.SetShouldSendForTesting(
- mojom::WebClientHintsType::kResourceWidth);
+ network::mojom::WebClientHintsType::kDeviceMemory);
+ preferences.SetShouldSendForTesting(network::mojom::WebClientHintsType::kDpr);
preferences.SetShouldSendForTesting(
- mojom::WebClientHintsType::kViewportWidth);
- preferences.SetShouldSendForTesting(mojom::WebClientHintsType::kRtt);
- preferences.SetShouldSendForTesting(mojom::WebClientHintsType::kDownlink);
- preferences.SetShouldSendForTesting(mojom::WebClientHintsType::kEct);
- preferences.SetShouldSendForTesting(mojom::WebClientHintsType::kLang);
- preferences.SetShouldSendForTesting(mojom::WebClientHintsType::kUA);
- preferences.SetShouldSendForTesting(mojom::WebClientHintsType::kUAArch);
- preferences.SetShouldSendForTesting(mojom::WebClientHintsType::kUAPlatform);
- preferences.SetShouldSendForTesting(mojom::WebClientHintsType::kUAModel);
+ network::mojom::WebClientHintsType::kResourceWidth);
+ preferences.SetShouldSendForTesting(
+ network::mojom::WebClientHintsType::kViewportWidth);
+ preferences.SetShouldSendForTesting(network::mojom::WebClientHintsType::kRtt);
+ preferences.SetShouldSendForTesting(
+ network::mojom::WebClientHintsType::kDownlink);
+ preferences.SetShouldSendForTesting(network::mojom::WebClientHintsType::kEct);
+ preferences.SetShouldSendForTesting(
+ network::mojom::WebClientHintsType::kLang);
+ preferences.SetShouldSendForTesting(network::mojom::WebClientHintsType::kUA);
+ preferences.SetShouldSendForTesting(
+ network::mojom::WebClientHintsType::kUAArch);
+ preferences.SetShouldSendForTesting(
+ network::mojom::WebClientHintsType::kUAPlatform);
+ preferences.SetShouldSendForTesting(
+ network::mojom::WebClientHintsType::kUAPlatformVersion);
+ preferences.SetShouldSendForTesting(
+ network::mojom::WebClientHintsType::kUAModel);
ApproximatedDeviceMemory::SetPhysicalMemoryMBForTesting(4096);
document->GetFrame()->GetClientHintsPreferences().UpdateFrom(preferences);
@@ -955,6 +1023,8 @@ TEST_F(FrameFetchContextHintsTest, MonitorAllHintsFeaturePolicy) {
ExpectHeader("https://www.example.net/1.gif", "Sec-CH-UA", true, "");
ExpectHeader("https://www.example.net/1.gif", "Sec-CH-UA-Arch", true, "");
ExpectHeader("https://www.example.net/1.gif", "Sec-CH-UA-Platform", true, "");
+ ExpectHeader("https://www.example.net/1.gif", "Sec-CH-UA-Platform-Version",
+ true, "");
ExpectHeader("https://www.example.net/1.gif", "Sec-CH-UA-Model", true, "");
ExpectHeader("https://www.example.net/1.gif", "Width", true, "400", 400);
ExpectHeader("https://www.example.net/1.gif", "Viewport-Width", true, "500");
@@ -985,8 +1055,9 @@ TEST_F(FrameFetchContextHintsTest, MonitorSomeHintsFeaturePolicy) {
"ch-device-memory 'self' https://www.example.net");
document->GetSettings()->SetScriptEnabled(true);
ClientHintsPreferences preferences;
- preferences.SetShouldSendForTesting(mojom::WebClientHintsType::kDeviceMemory);
- preferences.SetShouldSendForTesting(mojom::WebClientHintsType::kDpr);
+ preferences.SetShouldSendForTesting(
+ network::mojom::WebClientHintsType::kDeviceMemory);
+ preferences.SetShouldSendForTesting(network::mojom::WebClientHintsType::kDpr);
ApproximatedDeviceMemory::SetPhysicalMemoryMBForTesting(4096);
document->GetFrame()->GetClientHintsPreferences().UpdateFrom(preferences);
// With a feature policy header, the client hints should be sent to the
@@ -1018,6 +1089,8 @@ TEST_F(FrameFetchContextHintsTest, MonitorSomeHintsFeaturePolicy) {
ExpectHeader("https://www.example.net/1.gif", "Sec-CH-UA-Arch", false, "");
ExpectHeader("https://www.example.net/1.gif", "Sec-CH-UA-Platform", false,
"");
+ ExpectHeader("https://www.example.net/1.gif", "Sec-CH-UA-Platform-Version",
+ false, "");
ExpectHeader("https://www.example.net/1.gif", "Sec-CH-UA-Model", false, "");
ExpectHeader("https://www.example.net/1.gif", "Width", false, "");
ExpectHeader("https://www.example.net/1.gif", "Viewport-Width", false, "");
@@ -1031,7 +1104,8 @@ TEST_F(FrameFetchContextHintsTest, MonitorHintsFeaturePolicyInsecureContext) {
document->GetSettings()->SetScriptEnabled(true);
ExpectHeader("https://www.example.com/1.gif", "Device-Memory", false, "");
ClientHintsPreferences preferences;
- preferences.SetShouldSendForTesting(mojom::WebClientHintsType::kDeviceMemory);
+ preferences.SetShouldSendForTesting(
+ network::mojom::WebClientHintsType::kDeviceMemory);
document->GetFrame()->GetClientHintsPreferences().UpdateFrom(preferences);
ApproximatedDeviceMemory::SetPhysicalMemoryMBForTesting(4096);
// Device-Memory hint in this case is sent to all (and only) secure origins.
@@ -1266,25 +1340,25 @@ TEST_F(FrameFetchContextTest, PopulateResourceRequestWhenDetached) {
ClientHintsPreferences client_hints_preferences;
client_hints_preferences.SetShouldSendForTesting(
- mojom::WebClientHintsType::kDeviceMemory);
+ network::mojom::WebClientHintsType::kDeviceMemory);
client_hints_preferences.SetShouldSendForTesting(
- mojom::WebClientHintsType::kDpr);
+ network::mojom::WebClientHintsType::kDpr);
client_hints_preferences.SetShouldSendForTesting(
- mojom::WebClientHintsType::kResourceWidth);
+ network::mojom::WebClientHintsType::kResourceWidth);
client_hints_preferences.SetShouldSendForTesting(
- mojom::WebClientHintsType::kViewportWidth);
+ network::mojom::WebClientHintsType::kViewportWidth);
FetchParameters::ResourceWidth resource_width;
ResourceLoaderOptions options;
document->GetFrame()->GetClientHintsPreferences().SetShouldSendForTesting(
- mojom::WebClientHintsType::kDeviceMemory);
+ network::mojom::WebClientHintsType::kDeviceMemory);
document->GetFrame()->GetClientHintsPreferences().SetShouldSendForTesting(
- mojom::WebClientHintsType::kDpr);
+ network::mojom::WebClientHintsType::kDpr);
document->GetFrame()->GetClientHintsPreferences().SetShouldSendForTesting(
- mojom::WebClientHintsType::kResourceWidth);
+ network::mojom::WebClientHintsType::kResourceWidth);
document->GetFrame()->GetClientHintsPreferences().SetShouldSendForTesting(
- mojom::WebClientHintsType::kViewportWidth);
+ network::mojom::WebClientHintsType::kViewportWidth);
dummy_page_holder = nullptr;
diff --git a/chromium/third_party/blink/renderer/core/loader/frame_load_request.cc b/chromium/third_party/blink/renderer/core/loader/frame_load_request.cc
index b4b183842f1..face9dd90dc 100644
--- a/chromium/third_party/blink/renderer/core/loader/frame_load_request.cc
+++ b/chromium/third_party/blink/renderer/core/loader/frame_load_request.cc
@@ -57,7 +57,7 @@ FrameLoadRequest::FrameLoadRequest(Document* origin_document,
should_check_main_world_content_security_policy_ =
origin_document && ContentSecurityPolicy::ShouldBypassMainWorld(
- origin_document->ToExecutionContext())
+ origin_document->GetExecutionContext())
? network::mojom::CSPDisposition::DO_NOT_CHECK
: network::mojom::CSPDisposition::CHECK;
diff --git a/chromium/third_party/blink/renderer/core/loader/frame_load_request.h b/chromium/third_party/blink/renderer/core/loader/frame_load_request.h
index 96190d87aef..9dcf81b1531 100644
--- a/chromium/third_party/blink/renderer/core/loader/frame_load_request.h
+++ b/chromium/third_party/blink/renderer/core/loader/frame_load_request.h
@@ -31,6 +31,7 @@
#include "third_party/blink/public/common/navigation/triggering_event_info.h"
#include "third_party/blink/public/mojom/blob/blob_url_store.mojom-blink.h"
#include "third_party/blink/public/mojom/loader/request_context_frame_type.mojom-blink.h"
+#include "third_party/blink/public/platform/web_impression.h"
#include "third_party/blink/public/web/web_window_features.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/frame/frame_types.h"
@@ -144,6 +145,14 @@ struct CORE_EXPORT FrameLoadRequest {
resource_request_.ClearHTTPOrigin();
}
+ // Impressions are set when a FrameLoadRequest is created for a click on an
+ // anchor tag that has conversion measurement attributes.
+ void SetImpression(const WebImpression& impression) {
+ impression_ = impression;
+ }
+
+ const base::Optional<WebImpression>& Impression() { return impression_; }
+
// Whether either OriginDocument, RequestorOrigin or IsolatedWorldOrigin can
// display the |url|,
bool CanDisplay(const KURL&) const;
@@ -168,6 +177,7 @@ struct CORE_EXPORT FrameLoadRequest {
mojom::RequestContextFrameType::kNone;
WebWindowFeatures window_features_;
bool is_window_open_ = false;
+ base::Optional<WebImpression> impression_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/loader/frame_loader.cc b/chromium/third_party/blink/renderer/core/loader/frame_loader.cc
index b8f4aa80447..44f0a5f883c 100644
--- a/chromium/third_party/blink/renderer/core/loader/frame_loader.cc
+++ b/chromium/third_party/blink/renderer/core/loader/frame_loader.cc
@@ -46,6 +46,8 @@
#include "services/metrics/public/cpp/ukm_builders.h"
#include "services/metrics/public/cpp/ukm_recorder.h"
#include "services/network/public/cpp/features.h"
+#include "services/network/public/cpp/web_sandbox_flags.h"
+#include "services/network/public/mojom/web_sandbox_flags.mojom-blink.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h"
#include "third_party/blink/public/mojom/frame/navigation_initiator.mojom-blink.h"
@@ -61,6 +63,7 @@
#include "third_party/blink/public/web/web_navigation_params.h"
#include "third_party/blink/renderer/bindings/core/v8/script_controller.h"
#include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h"
+#include "third_party/blink/renderer/core/dom/document_init.h"
#include "third_party/blink/renderer/core/dom/element.h"
#include "third_party/blink/renderer/core/dom/ignore_opens_during_unload_count_incrementer.h"
#include "third_party/blink/renderer/core/events/page_transition_event.h"
@@ -127,6 +130,40 @@
namespace blink {
+namespace {
+
+void ApplyOriginPolicy(ContentSecurityPolicy* csp,
+ const WebOriginPolicy& origin_policy) {
+ // When this function is called. The following lines of code happen
+ // consecutively:
+ // 1) A new empty set of CSP is created.
+ // 2) CSP(s) from the HTTP response are appended.
+ // 3) CSP(s) from the OriginPolicy are appended. [HERE]
+ //
+ // As a result, at the beginning of this function, the set of CSP must not
+ // contain any OriginPolicy's CSP yet.
+ //
+ // TODO(arthursonzogni): HasPolicyFromSource(...) is used only in this DCHECK,
+ // consider removing this function.
+ DCHECK(!csp->HasPolicyFromSource(
+ network::mojom::ContentSecurityPolicySource::kOriginPolicy));
+
+ for (const auto& policy : origin_policy.content_security_policies) {
+ csp->DidReceiveHeader(
+ policy, network::mojom::ContentSecurityPolicyType::kEnforce,
+ network::mojom::ContentSecurityPolicySource::kOriginPolicy);
+ }
+
+ for (const auto& policy :
+ origin_policy.content_security_policies_report_only) {
+ csp->DidReceiveHeader(
+ policy, network::mojom::ContentSecurityPolicyType::kReport,
+ network::mojom::ContentSecurityPolicySource::kOriginPolicy);
+ }
+}
+
+} // namespace
+
bool IsBackForwardLoadType(WebFrameLoadType type) {
return type == WebFrameLoadType::kBackForward;
}
@@ -178,7 +215,7 @@ ResourceRequest FrameLoader::ResourceRequestForReload(
FrameLoader::FrameLoader(LocalFrame* frame)
: frame_(frame),
progress_tracker_(MakeGarbageCollected<ProgressTracker>(frame)),
- forced_sandbox_flags_(mojom::blink::WebSandboxFlags::kNone),
+ forced_sandbox_flags_(network::mojom::blink::WebSandboxFlags::kNone),
dispatching_did_clear_window_object_in_main_world_(false),
detached_(false),
virtual_time_pauser_(
@@ -212,8 +249,7 @@ void FrameLoader::Init() {
: base::nullopt;
DocumentLoader* new_document_loader = Client()->CreateDocumentLoader(
- frame_, kWebNavigationTypeOther,
- MakeGarbageCollected<ContentSecurityPolicy>(),
+ frame_, kWebNavigationTypeOther, CreateCSPForInitialEmptyDocument(),
std::move(navigation_params), nullptr /* extra_data */);
CommitDocumentLoader(new_document_loader, base::nullopt, nullptr,
@@ -539,9 +575,10 @@ bool FrameLoader::AllowRequestForThisFrame(const FrameLoadRequest& request) {
return false;
if (frame_->Owner() && ((frame_->Owner()->GetFramePolicy().sandbox_flags &
- mojom::blink::WebSandboxFlags::kOrigin) !=
- mojom::blink::WebSandboxFlags::kNone))
+ network::mojom::blink::WebSandboxFlags::kOrigin) !=
+ network::mojom::blink::WebSandboxFlags::kNone)) {
return false;
+ }
}
if (!request.CanDisplay(url)) {
@@ -702,25 +739,33 @@ void FrameLoader::StartNavigation(FrameLoadRequest& request,
network::mojom::blink::CSPSourcePtr initiator_self_source;
if (origin_document && origin_document->GetContentSecurityPolicy()
->ExperimentalFeaturesEnabled()) {
- initiator_csp = origin_document->GetContentSecurityPolicy()
- ->ExposeForNavigationalChecks();
- initiator_self_source = origin_document->GetContentSecurityPolicy()
- ->GetSelfSource()
- ->ExposeForNavigationalChecks();
+ ContentSecurityPolicy* origin_document_csp =
+ origin_document->GetContentSecurityPolicy();
+ CSPSource* origin_document_csp_self_source =
+ origin_document_csp->GetSelfSource();
+
+ initiator_csp = origin_document_csp->ExposeForNavigationalChecks();
+ if (origin_document_csp_self_source) {
+ initiator_self_source =
+ origin_document_csp_self_source->ExposeForNavigationalChecks();
+ }
origin_document->NavigationInitiator().BindReceiver(
navigation_initiator.InitWithNewPipeAndPassReceiver());
}
+ // Record the document that has initiated this navigation. It will be used at
+ // navigation commit time for inheritance.
+ // TODO(arthursonzogni): This looks very fragile. It seems easy to confuse the
+ // FrameLoader by starting several navigations in a row. We should get rid of
+ // this.
+ last_origin_document_csp_ = MakeGarbageCollected<ContentSecurityPolicy>();
if (origin_document && origin_document->GetContentSecurityPolicy()) {
- last_origin_document_csp_ = MakeGarbageCollected<ContentSecurityPolicy>();
last_origin_document_csp_->CopyStateFrom(
origin_document->GetContentSecurityPolicy());
- last_origin_document_csp_->CopyPluginTypesFrom(
- origin_document->GetContentSecurityPolicy());
}
- // Record the latest requiredCSP value that will be used when sending this
- // request.
+ // Record the latest requiredCSP value that will be used when loading the
+ // document at navigation commit time.
RecordLatestRequiredCSP();
// TODO(arthursonzogni): 'frame-src' check is disabled on the
@@ -763,16 +808,8 @@ void FrameLoader::StartNavigation(FrameLoadRequest& request,
return;
}
- bool has_transient_activation =
- LocalFrame::HasTransientUserActivation(frame_);
- // TODO(csharrison): In M71 when UserActivation v2 should ship, we can remove
- // the check that the pages are equal, because consumption should not be
- // shared across pages. After that, we can also get rid of consumption call
- // in RenderFrameImpl::OpenURL.
- if (frame_->IsMainFrame() && origin_document &&
- frame_->GetPage() == origin_document->GetPage()) {
+ if (frame_->IsMainFrame())
LocalFrame::ConsumeTransientUserActivation(frame_);
- }
// The main resource request gets logged here, because V8DOMActivityLogger
// is looked up based on the current v8::Context. When the request actually
@@ -790,7 +827,8 @@ void FrameLoader::StartNavigation(FrameLoadRequest& request,
if (request.ClientRedirectReason() != ClientNavigationReason::kNone) {
probe::FrameRequestedNavigation(frame_, frame_, url,
- request.ClientRedirectReason());
+ request.ClientRedirectReason(),
+ request.GetNavigationPolicy());
}
const network::mojom::IPAddressSpace initiator_address_space =
@@ -800,14 +838,14 @@ void FrameLoader::StartNavigation(FrameLoadRequest& request,
Client()->BeginNavigation(
resource_request, request.GetFrameType(), origin_document,
nullptr /* document_loader */, navigation_type,
- request.GetNavigationPolicy(), has_transient_activation, frame_load_type,
+ request.GetNavigationPolicy(), frame_load_type,
request.ClientRedirect() == ClientRedirectPolicy::kClientRedirect,
request.GetTriggeringEventInfo(), request.Form(),
request.ShouldCheckMainWorldContentSecurityPolicy(),
request.GetBlobURLToken(), request.GetInputStartTime(),
- request.HrefTranslate().GetString(), std::move(initiator_csp),
- std::move(initiator_self_source), initiator_address_space,
- std::move(navigation_initiator));
+ request.HrefTranslate().GetString(), request.Impression(),
+ std::move(initiator_csp), std::move(initiator_self_source),
+ initiator_address_space, std::move(navigation_initiator));
}
static void FillStaticResponseIfNeeded(WebNavigationParams* params,
@@ -889,7 +927,7 @@ static bool ShouldNavigate(WebNavigationParams* params, LocalFrame* frame) {
void FrameLoader::CommitNavigation(
std::unique_ptr<WebNavigationParams> navigation_params,
std::unique_ptr<WebDocumentLoader::ExtraData> extra_data,
- bool is_javascript_url) {
+ CommitReason commit_reason) {
DCHECK(frame_->GetDocument());
DCHECK(Client()->HasWebView());
@@ -944,20 +982,13 @@ void FrameLoader::CommitNavigation(
DCHECK(!StateMachine()->CreatingInitialEmptyDocument());
HistoryItem* previous_history_item = GetDocumentLoader()->GetHistoryItem();
- bool loading_url_as_empty_document =
- !navigation_params->is_static_data &&
- DocumentLoader::WillLoadUrlAsEmpty(navigation_params->url);
-
- // Check if the CSP of the response allow should block the new document from
+ // Check if the CSP of the response should block the new document from
// committing before unloading the current document. This will allow to report
// violations and display console messages properly.
- ContentSecurityPolicy* content_security_policy;
- if (!loading_url_as_empty_document) {
- content_security_policy =
- CreateCSP(navigation_params->url,
- navigation_params->response.ToResourceResponse(),
- navigation_params->origin_policy);
- }
+ ContentSecurityPolicy* content_security_policy = CreateCSP(
+ navigation_params->url, navigation_params->response.ToResourceResponse(),
+ navigation_params->origin_policy, last_origin_document_csp_.Release(),
+ commit_reason);
base::Optional<Document::UnloadEventTiming> unload_timing;
FrameSwapScope frame_swap_scope(frame_owner);
@@ -991,9 +1022,7 @@ void FrameLoader::CommitNavigation(
std::move(navigation_params), std::move(extra_data));
CommitDocumentLoader(new_document_loader, unload_timing,
- previous_history_item,
- is_javascript_url ? CommitReason::kJavascriptUrl
- : CommitReason::kRegular);
+ previous_history_item, commit_reason);
RestoreScrollPositionAndViewState();
@@ -1038,6 +1067,7 @@ void FrameLoader::StopAllLoaders() {
if (document_loader_)
document_loader_->StopLoading();
CancelClientNavigation();
+ frame_->CancelFormSubmission();
DidFinishNavigation(FrameLoader::NavigationFinishState::kSuccess);
TakeObjectSnapshot();
@@ -1116,8 +1146,7 @@ void FrameLoader::CommitDocumentLoader(
document_loader_ = document_loader;
CHECK(document_loader_);
- if (commit_reason == CommitReason::kJavascriptUrl)
- document_loader_->SetLoadingJavaScriptUrl();
+ document_loader_->SetCommitReason(commit_reason);
virtual_time_pauser_.PauseVirtualTime();
document_loader_->StartLoading();
@@ -1155,8 +1184,9 @@ void FrameLoader::CommitDocumentLoader(
FrameNavigationDisabler navigation_disabler(*frame_);
if (commit_reason == CommitReason::kInitialization) {
Client()->DidCreateInitialEmptyDocument();
- } else if (commit_reason == CommitReason::kJavascriptUrl) {
- Client()->DidCommitJavascriptUrlNavigation(document_loader_);
+ } else if (commit_reason == CommitReason::kJavascriptUrl ||
+ commit_reason == CommitReason::kXSLT) {
+ Client()->DidCommitDocumentReplacementNavigation(document_loader_);
} else {
Client()->DispatchDidCommitLoad(
document_loader_->GetHistoryItem(),
@@ -1224,7 +1254,6 @@ String FrameLoader::UserAgent() const {
base::Optional<blink::UserAgentMetadata> FrameLoader::UserAgentMetadata()
const {
- // TODO(mkwst): Support overrides probes for devtools support.
return Client()->UserAgentMetadata();
}
@@ -1424,11 +1453,12 @@ bool FrameLoader::ShouldReuseDefaultView(
// be considered when deciding whether to reuse it.
// Spec:
// https://html.spec.whatwg.org/C/#initialise-the-document-object
- if ((csp &&
- (csp->GetSandboxMask() & mojom::blink::WebSandboxFlags::kOrigin) !=
- mojom::blink::WebSandboxFlags::kNone) ||
- ((EffectiveSandboxFlags() & mojom::blink::WebSandboxFlags::kOrigin) !=
- mojom::blink::WebSandboxFlags::kNone)) {
+ if ((csp && (csp->GetSandboxMask() &
+ network::mojom::blink::WebSandboxFlags::kOrigin) !=
+ network::mojom::blink::WebSandboxFlags::kNone) ||
+ ((EffectiveSandboxFlags() &
+ network::mojom::blink::WebSandboxFlags::kOrigin) !=
+ network::mojom::blink::WebSandboxFlags::kNone)) {
return false;
}
@@ -1450,6 +1480,9 @@ bool FrameLoader::CancelProvisionalLoaderForNewNavigation() {
// replacing client navigation with a DocumentLoader.
ClearClientNavigation();
+ // Cancel pending form submissions so they don't take precedence over this.
+ frame_->CancelFormSubmission();
+
return true;
}
@@ -1494,6 +1527,16 @@ void FrameLoader::RunScriptsAtDocumentElementAvailable() {
// The frame might be detached at this point.
}
+void FrameLoader::ForceSandboxFlags(
+ network::mojom::blink::WebSandboxFlags flags) {
+ forced_sandbox_flags_ |= flags;
+}
+
+void FrameLoader::SetFrameOwnerSandboxFlags(
+ network::mojom::blink::WebSandboxFlags flags) {
+ frame_owner_sandbox_flags_ = flags;
+}
+
void FrameLoader::DispatchDidClearDocumentOfWindowObject() {
DCHECK(frame_->GetDocument());
if (state_machine_.CreatingInitialEmptyDocument())
@@ -1529,8 +1572,9 @@ void FrameLoader::DispatchDidClearWindowObjectInMainWorld() {
Client()->DispatchDidClearWindowObjectInMainWorld();
}
-SandboxFlags FrameLoader::EffectiveSandboxFlags() const {
- SandboxFlags flags = forced_sandbox_flags_;
+network::mojom::blink::WebSandboxFlags FrameLoader::EffectiveSandboxFlags()
+ const {
+ network::mojom::blink::WebSandboxFlags flags = forced_sandbox_flags_;
if (frame_->Owner()) {
// Cannot use flags in frame_owner->GetFramePolicy().sandbox_flags, because
// frame_owner's frame policy is volatile and can be changed by javascript
@@ -1546,8 +1590,9 @@ SandboxFlags FrameLoader::EffectiveSandboxFlags() const {
return flags;
}
-SandboxFlags FrameLoader::PendingEffectiveSandboxFlags() const {
- SandboxFlags flags = forced_sandbox_flags_;
+network::mojom::blink::WebSandboxFlags
+FrameLoader::PendingEffectiveSandboxFlags() const {
+ network::mojom::blink::WebSandboxFlags flags = forced_sandbox_flags_;
if (FrameOwner* frame_owner = frame_->Owner())
flags |= frame_owner->GetFramePolicy().sandbox_flags;
// Frames need to inherit the sandbox flags of their parent frame.
@@ -1584,7 +1629,7 @@ void FrameLoader::ModifyRequestForCSP(
MixedContentChecker::UpgradeInsecureRequest(
resource_request, fetch_client_settings_object,
- document_for_logging ? document_for_logging->ToExecutionContext()
+ document_for_logging ? document_for_logging->GetExecutionContext()
: nullptr,
frame_type, frame_->GetContentSettingsClient());
}
@@ -1692,72 +1737,124 @@ bool FrameLoader::IsClientNavigationInitialHistoryLoad() {
client_navigation_->is_history_navigation_in_new_frame;
}
+ContentSecurityPolicy* FrameLoader::CreateCSPForInitialEmptyDocument() const {
+ ContentSecurityPolicy* csp = MakeGarbageCollected<ContentSecurityPolicy>();
+
+ Frame* owner_frame = frame_->Tree().Parent() ? frame_->Tree().Parent()
+ : frame_->Client()->Opener();
+ if (owner_frame) {
+ ContentSecurityPolicy* owner_csp =
+ owner_frame->GetSecurityContext()->GetContentSecurityPolicy();
+ csp->CopyStateFrom(owner_csp);
+ }
+
+ return csp;
+}
+
ContentSecurityPolicy* FrameLoader::CreateCSP(
const KURL& url,
const ResourceResponse& response,
- const base::Optional<WebOriginPolicy>& origin_policy) {
- auto* csp = MakeGarbageCollected<ContentSecurityPolicy>();
-
+ const base::Optional<WebOriginPolicy>& origin_policy,
+ ContentSecurityPolicy* initiator_csp,
+ CommitReason commit_reason) {
+ // about:srcdoc inherits CSP from its parent.
if (url.IsAboutSrcdocURL()) {
- // about:srcdoc always inherits CSP from its parent.
- ContentSecurityPolicy* parent_csp = frame_->Tree()
- .Parent()
- ->GetSecurityContext()
- ->GetContentSecurityPolicy();
- csp->CopyStateFrom(parent_csp);
- csp->CopyPluginTypesFrom(parent_csp);
+ ContentSecurityPolicy* csp = MakeGarbageCollected<ContentSecurityPolicy>();
+ csp->CopyStateFrom(frame_->Tree()
+ .Parent()
+ ->GetSecurityContext()
+ ->GetContentSecurityPolicy());
return csp;
}
- csp->SetOverrideURLForSelf(response.CurrentRequestUrl());
+ // Documents constructed by XSLTProcessor inherit CSP from the previous
+ // Document.
+ if (commit_reason == CommitReason::kXSLT) {
+ ContentSecurityPolicy* csp = MakeGarbageCollected<ContentSecurityPolicy>();
+ csp->CopyStateFrom(frame_->GetDocument()->GetContentSecurityPolicy());
+ return csp;
+ }
- if (!frame_->GetSettings()->BypassCSP()) {
- csp->DidReceiveHeaders(ContentSecurityPolicyResponseHeaders(response));
-
- // Handle OriginPolicy. We can skip the entire block if the OP policies have
- // already been passed down.
- if (origin_policy.has_value() &&
- !csp->HasPolicyFromSource(
- network::mojom::ContentSecurityPolicySource::kOriginPolicy)) {
- for (const auto& policy : origin_policy->content_security_policies) {
- csp->DidReceiveHeader(
- policy, network::mojom::ContentSecurityPolicyType::kEnforce,
- network::mojom::ContentSecurityPolicySource::kOriginPolicy);
- }
-
- for (const auto& policy :
- origin_policy->content_security_policies_report_only) {
- csp->DidReceiveHeader(
- policy, network::mojom::ContentSecurityPolicyType::kReport,
- network::mojom::ContentSecurityPolicySource::kOriginPolicy);
- }
- }
+ // Documents with a local-scheme inherits CSP from their navigation initiator.
+ bool is_local_scheme = url.IsEmpty() || url.ProtocolIsAbout() ||
+ url.ProtocolIsData() || url.ProtocolIs("blob") ||
+ url.ProtocolIs("filesystem");
+ if (is_local_scheme) {
+ if (initiator_csp)
+ return initiator_csp;
+ return MakeGarbageCollected<ContentSecurityPolicy>();
}
+
+ // In the main case (outside of the ones above), CSP(s) are NOT inherited.
+ // Otherwise, it would allow a malicious parent/opener to block some
+ // iframe/popup's script at a fine-grained level.
+
+ ContentSecurityPolicy* csp = MakeGarbageCollected<ContentSecurityPolicy>();
+ csp->SetOverrideURLForSelf(response.CurrentRequestUrl());
+
+ if (frame_->GetSettings()->BypassCSP())
+ return csp; // Empty CSP.
+
+ // Parse CSP from the HTTP response.
+ csp->DidReceiveHeaders(ContentSecurityPolicyResponseHeaders(response));
+
+ // Retrieve CSP stored in the OriginPolicy.
+ if (origin_policy)
+ ApplyOriginPolicy(csp, origin_policy.value());
+
+ // Check CSP frame-ancestor:
if (!base::FeatureList::IsEnabled(
network::features::kOutOfBlinkFrameAncestors)) {
- if (!csp->AllowAncestors(frame_, response.CurrentRequestUrl())) {
- return nullptr;
- }
- }
+ if (!csp->AllowAncestors(frame_, response.CurrentRequestUrl()))
+ return nullptr; // Document blocked.
+ }
+
+ // Plugin inherits plugin's CSP from their navigation initiator.
+ DocumentInit::Type document_type =
+ DocumentInit::ComputeDocumentType(frame_, url, response.MimeType());
+ if (document_type == DocumentInit::Type::kPlugin) {
+ Frame* owner_frame = frame_->Tree().Parent() ? frame_->Tree().Parent()
+ : frame_->Client()->Opener();
+ ContentSecurityPolicy* owner_csp =
+ owner_frame
+ ? owner_frame->GetSecurityContext()->GetContentSecurityPolicy()
+ : nullptr;
+ // TODO(andypaicu): This should always inherit the origin document's plugin
+ // types but because this could be a OOPIF document it might not have
+ // access. In this situation we fallback on using the parent/opener:
+ ContentSecurityPolicy* inherited_csp =
+ initiator_csp ? initiator_csp : owner_csp;
+ if (inherited_csp)
+ csp->CopyPluginTypesFrom(inherited_csp);
+ }
+
+ // When the embedder used the 'required-csp', its embeddee must either:
+ // 1) Use the 'allow-csp' header for opting in inheriting them.
+ // 2) Ensure its own CSP subsume them, or it will be blocked.
+ //
+ // See:
+ // - https://w3c.github.io/webappsec-cspee/#required-csp-header
+ // - https://w3c.github.io/webappsec-cspee/#allow-csp-from-header
+ if (RequiredCSP().IsEmpty())
+ return csp;
- if (!frame_->GetSettings()->BypassCSP() && !RequiredCSP().IsEmpty()) {
- const SecurityOrigin* parent_security_origin =
- frame_->Tree().Parent()->GetSecurityContext()->GetSecurityOrigin();
- if (parent_security_origin &&
- ContentSecurityPolicy::ShouldEnforceEmbeddersPolicy(
- response, parent_security_origin)) {
- csp->AddPolicyFromHeaderValue(
- RequiredCSP(), network::mojom::ContentSecurityPolicyType::kEnforce,
- network::mojom::ContentSecurityPolicySource::kHTTP);
- } else {
- auto* required_csp = MakeGarbageCollected<ContentSecurityPolicy>();
- required_csp->AddPolicyFromHeaderValue(
- RequiredCSP(), network::mojom::ContentSecurityPolicyType::kEnforce,
- network::mojom::ContentSecurityPolicySource::kHTTP);
- if (!required_csp->Subsumes(*csp))
- return nullptr;
- }
+ const SecurityOrigin* parent_security_origin =
+ frame_->Tree().Parent()->GetSecurityContext()->GetSecurityOrigin();
+ if (parent_security_origin &&
+ ContentSecurityPolicy::ShouldEnforceEmbeddersPolicy(
+ response, parent_security_origin)) {
+ csp->AddPolicyFromHeaderValue(
+ RequiredCSP(), network::mojom::ContentSecurityPolicyType::kEnforce,
+ network::mojom::ContentSecurityPolicySource::kHTTP);
+ } else {
+ auto* required_csp = MakeGarbageCollected<ContentSecurityPolicy>();
+ required_csp->AddPolicyFromHeaderValue(
+ RequiredCSP(), network::mojom::ContentSecurityPolicyType::kEnforce,
+ network::mojom::ContentSecurityPolicySource::kHTTP);
+ if (!required_csp->Subsumes(*csp))
+ return nullptr; // Document blocked.
}
+
return csp;
}
diff --git a/chromium/third_party/blink/renderer/core/loader/frame_loader.h b/chromium/third_party/blink/renderer/core/loader/frame_loader.h
index bda3ebc0635..17f1e061426 100644
--- a/chromium/third_party/blink/renderer/core/loader/frame_loader.h
+++ b/chromium/third_party/blink/renderer/core/loader/frame_loader.h
@@ -37,6 +37,7 @@
#include "base/bind_helpers.h"
#include "base/macros.h"
+#include "services/network/public/mojom/web_sandbox_flags.mojom-blink-forward.h"
#include "third_party/blink/public/common/user_agent/user_agent_metadata.h"
#include "third_party/blink/public/mojom/loader/request_context_frame_type.mojom-blink-forward.h"
#include "third_party/blink/public/platform/scheduler/web_scoped_virtual_time_pauser.h"
@@ -47,7 +48,6 @@
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/frame/frame_types.h"
-#include "third_party/blink/renderer/core/frame/sandbox_flags.h"
#include "third_party/blink/renderer/core/loader/frame_loader_state_machine.h"
#include "third_party/blink/renderer/core/loader/frame_loader_types.h"
#include "third_party/blink/renderer/core/loader/history_item.h"
@@ -103,7 +103,7 @@ class CORE_EXPORT FrameLoader final {
void CommitNavigation(
std::unique_ptr<WebNavigationParams> navigation_params,
std::unique_ptr<WebDocumentLoader::ExtraData> extra_data,
- bool is_javascript_url = false);
+ CommitReason = CommitReason::kRegular);
// Called before the browser process is asked to navigate this frame, to mark
// the frame as loading and save some navigation information for later use.
@@ -142,28 +142,24 @@ class CORE_EXPORT FrameLoader final {
// The following sandbox flags will be forced, regardless of changes to the
// sandbox attribute of any parent frames.
- void ForceSandboxFlags(mojom::blink::WebSandboxFlags flags) {
- forced_sandbox_flags_ |= flags;
- }
+ void ForceSandboxFlags(network::mojom::blink::WebSandboxFlags flags);
// Set frame_owner's effective sandbox flags, which are sandbox flags value
// at the beginning of navigation.
- void SetFrameOwnerSandboxFlags(mojom::blink::WebSandboxFlags flags) {
- frame_owner_sandbox_flags_ = flags;
- }
+ void SetFrameOwnerSandboxFlags(network::mojom::blink::WebSandboxFlags flags);
// Includes the collection of forced, inherited, and FrameOwner's sandbox
// flags, where the FrameOwner's flag is snapshotted from the last committed
// navigation. Note: with FeaturePolicyForSandbox the frame owner's sandbox
// flags only includes the flags which are *not* implemented as feature
// policies already present in the FrameOwner's ContainerPolicy.
- mojom::blink::WebSandboxFlags EffectiveSandboxFlags() const;
+ network::mojom::blink::WebSandboxFlags EffectiveSandboxFlags() const;
// Includes the collection of forced, inherited, and FrameOwner's sandbox
// flags. Note: with FeaturePolicyForSandbox the frame owner's sandbox flags
// only includes the flags which are *not* implemented as feature policies
// already present in the FrameOwner's ContainerPolicy.
- mojom::blink::WebSandboxFlags PendingEffectiveSandboxFlags() const;
+ network::mojom::blink::WebSandboxFlags PendingEffectiveSandboxFlags() const;
// Modifying itself is done based on |fetch_client_settings_object|.
// |document_for_logging| is used only for logging, use counters,
@@ -235,9 +231,6 @@ class CORE_EXPORT FrameLoader final {
void DidDropNavigation();
void MarkAsLoading();
- ContentSecurityPolicy* GetLastOriginDocumentCSP() {
- return last_origin_document_csp_.Get();
- }
bool ShouldReuseDefaultView(const scoped_refptr<const SecurityOrigin>&,
const ContentSecurityPolicy*);
@@ -277,31 +270,28 @@ class CORE_EXPORT FrameLoader final {
std::unique_ptr<TracedValue> ToTracedValue() const;
void TakeObjectSnapshot() const;
- enum class CommitReason {
- // Committing initial empty document.
- kInitialization,
- // Committing navigation as a result of javascript URL execution.
- kJavascriptUrl,
- // All other navigations.
- kRegular
- };
// Commits the given |document_loader|.
void CommitDocumentLoader(DocumentLoader* document_loader,
const base::Optional<Document::UnloadEventTiming>&,
HistoryItem* previous_history_item,
CommitReason);
+ // Creates CSP for the initial empty document. They are inherited from the
+ // owner document (parent or opener).
+ ContentSecurityPolicy* CreateCSPForInitialEmptyDocument() const;
+
// Creates CSP based on |response| and checks that they allow loading |url|.
// Returns nullptr if the check fails.
ContentSecurityPolicy* CreateCSP(
const KURL& url,
const ResourceResponse& response,
- const base::Optional<WebOriginPolicy>& origin_policy);
+ const base::Optional<WebOriginPolicy>& origin_policy,
+ ContentSecurityPolicy* initiator_csp,
+ CommitReason);
LocalFrameClient* Client() const;
Member<LocalFrame> frame_;
- AtomicString required_csp_;
// FIXME: These should be std::unique_ptr<T> to reduce build times and
// simplify header dependencies unless performance testing proves otherwise.
@@ -322,15 +312,15 @@ class CORE_EXPORT FrameLoader final {
};
std::unique_ptr<ClientNavigationState> client_navigation_;
- mojom::blink::WebSandboxFlags forced_sandbox_flags_;
+ network::mojom::blink::WebSandboxFlags forced_sandbox_flags_;
// A snapshot value of frame_owner's sandbox flags states at the beginning of
// navigation. For main frame which does not have a frame owner, the value is
// base::nullopt.
// The snapshot value is needed because of potential racing conditions on
// sandbox attribute on iframe element.
// crbug.com/1026627
- base::Optional<mojom::blink::WebSandboxFlags> frame_owner_sandbox_flags_ =
- base::nullopt;
+ base::Optional<network::mojom::blink::WebSandboxFlags>
+ frame_owner_sandbox_flags_ = base::nullopt;
bool dispatching_did_clear_window_object_in_main_world_;
bool detached_;
@@ -339,8 +329,13 @@ class CORE_EXPORT FrameLoader final {
WebScopedVirtualTimePauser virtual_time_pauser_;
+ // The CSP of the latest document that has initiated a navigation in this
+ // frame. TODO(arthursonzogni): This looks fragile. The FrameLoader might be
+ // confused by several navigations submitted in a row.
Member<ContentSecurityPolicy> last_origin_document_csp_;
+ AtomicString required_csp_;
+
// The origins for which a legacy TLS version warning has been printed. The
// size of this set is capped, after which no more warnings are printed.
HashSet<String> tls_version_warning_origins_;
diff --git a/chromium/third_party/blink/renderer/core/loader/frame_loader_types.h b/chromium/third_party/blink/renderer/core/loader/frame_loader_types.h
index b00161b30f8..5922922e316 100644
--- a/chromium/third_party/blink/renderer/core/loader/frame_loader_types.h
+++ b/chromium/third_party/blink/renderer/core/loader/frame_loader_types.h
@@ -82,6 +82,18 @@ enum class ClientNavigationReason {
kReload,
kNone
};
+
+enum class CommitReason {
+ // Committing initial empty document.
+ kInitialization,
+ // Committing navigation as a result of javascript URL execution.
+ kJavascriptUrl,
+ // Committing a replacement document from XSLT.
+ kXSLT,
+ // All other navigations.
+ kRegular
+};
+
} // namespace blink
#endif
diff --git a/chromium/third_party/blink/renderer/core/loader/frame_or_imported_document.cc b/chromium/third_party/blink/renderer/core/loader/frame_or_imported_document.cc
deleted file mode 100644
index b5f865760b3..00000000000
--- a/chromium/third_party/blink/renderer/core/loader/frame_or_imported_document.cc
+++ /dev/null
@@ -1,65 +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/core/loader/frame_or_imported_document.h"
-
-#include "third_party/blink/renderer/core/dom/document.h"
-#include "third_party/blink/renderer/core/frame/local_frame.h"
-#include "third_party/blink/renderer/core/html/imports/html_imports_controller.h"
-#include "third_party/blink/renderer/core/loader/document_loader.h"
-#include "third_party/blink/renderer/core/loader/frame_loader.h"
-
-namespace blink {
-
-LocalFrame& FrameOrImportedDocument::GetFrame() const {
- DCHECK(document_);
- if (document_loader_) {
- LocalFrame* frame = document_->GetFrame();
- DCHECK(frame);
- return *frame;
- }
-
- // HTML imports case
- // It's guaranteed that imports_controller is not nullptr since:
- // - only ClearImportsController() clears it
- // - ClearImportsController() also calls ResourceFethcer::ClearContext().
- HTMLImportsController* imports_controller = document_->ImportsController();
- DCHECK(imports_controller);
-
- // It's guaranteed that Master() is not yet Shutdown()-ed since when Master()
- // is Shutdown()-ed:
- // - Master()'s HTMLImportsController is disposed.
- // - All the HTMLImportLoader instances of the HTMLImportsController are
- // disposed.
- // - ClearImportsController() is called on the Document.
- // HTMLImportsController is created only when the master Document's
- // GetFrame() doesn't return nullptr, this is guaranteed to be not nullptr
- // here.
- LocalFrame* frame = imports_controller->Master()->GetFrame();
- DCHECK(frame);
- return *frame;
-}
-
-DocumentLoader& FrameOrImportedDocument::GetMasterDocumentLoader() const {
- if (document_loader_)
- return *document_loader_;
-
- // HTML imports case
- // GetDocumentLoader() here always returns a non-nullptr value that is the
- // DocumentLoader for |document_| because:
- // - A Document is created with a LocalFrame only after the
- // DocumentLoader is committed
- // - When another DocumentLoader is committed, the FrameLoader
- // Shutdown()-s |document_|.
- auto* loader = GetFrame().Loader().GetDocumentLoader();
- DCHECK(loader);
- return *loader;
-}
-
-void FrameOrImportedDocument::Trace(Visitor* visitor) {
- visitor->Trace(document_loader_);
- visitor->Trace(document_);
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/loader/frame_or_imported_document.h b/chromium/third_party/blink/renderer/core/loader/frame_or_imported_document.h
deleted file mode 100644
index 81d61588fc8..00000000000
--- a/chromium/third_party/blink/renderer/core/loader/frame_or_imported_document.h
+++ /dev/null
@@ -1,73 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_FRAME_OR_IMPORTED_DOCUMENT_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_FRAME_OR_IMPORTED_DOCUMENT_H_
-
-#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/platform/heap/handle.h"
-
-namespace blink {
-
-class Document;
-class DocumentLoader;
-class LocalFrame;
-
-// FrameOrImportedDocument is a thin wrapper that represents and absorbs
-// the differences between Document-ish things behind FrameFetchContext:
-// - An imported Document
-// (document_loader_ is null, document_ is non-null),
-// - A DocumentLoader that has committed its navigation
-// (document_loader_ is non-null, document_ is non-null).
-//
-// A FrameOrImportedDocument is indirectly used with a ResourceFetcher, and
-// works until ResourceFetcher::ClearContext is called. Do not use this class
-// outside of core/loader.
-class CORE_EXPORT FrameOrImportedDocument final
- : public GarbageCollected<FrameOrImportedDocument> {
- public:
- // Creates a FrameOrImportedDocument associated with a LocalFrame (which is,
- // loader.GetFrame() which cannot be null). This object works until the
- // associated frame is detached.
- FrameOrImportedDocument(DocumentLoader& loader, Document& committed_document)
- : document_loader_(loader), document_(committed_document) {}
-
- // Creates a FrameOrImportedDocument associated with an imported document.
- // This object works until |document| is shut-down.
- explicit FrameOrImportedDocument(Document& imported_document)
- : document_(imported_document) {}
-
- // When this object is associated with a frame, returns it.
- // When this object is associated with an imported document, returns the
- // frame associated with the imports controller.
- LocalFrame& GetFrame() const;
-
- // When this object is associated with a frame, returns the document loader
- // given to the constructor (note that there may be multiple document loaders
- // in a LocalFrame).
- // When this object is associated with an imported document, returns the
- // document loader associated with the frame associated with the imports
- // controller.
- DocumentLoader& GetMasterDocumentLoader() const;
-
- // When this object is associated with a frame, returns the document loader
- // given to the constructor (note that there may be multiple document loaders
- // in a LocalFrame). Otherwise, returns null.
- DocumentLoader* GetDocumentLoader() const { return document_loader_; }
-
- // When this object is associated with a frame with a committed document,
- // returns it.
- // When this object is associated with an imported document, returns it.
- Document& GetDocument() const { return *document_; }
-
- void Trace(Visitor* visitor);
-
- private:
- const Member<DocumentLoader> document_loader_;
- const Member<Document> document_;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_FRAME_OR_IMPORTED_DOCUMENT_H_
diff --git a/chromium/third_party/blink/renderer/core/loader/frame_resource_fetcher_properties.cc b/chromium/third_party/blink/renderer/core/loader/frame_resource_fetcher_properties.cc
index 12c1fb1da2b..75dca1637b0 100644
--- a/chromium/third_party/blink/renderer/core/loader/frame_resource_fetcher_properties.cc
+++ b/chromium/third_party/blink/renderer/core/loader/frame_resource_fetcher_properties.cc
@@ -4,13 +4,14 @@
#include "third_party/blink/renderer/core/loader/frame_resource_fetcher_properties.h"
+#include "base/metrics/field_trial_params.h"
#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_network_provider.h"
#include "third_party/blink/public/platform/web_effective_connection_type.h"
#include "third_party/blink/renderer/core/dom/document.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/settings.h"
#include "third_party/blink/renderer/core/loader/document_loader.h"
-#include "third_party/blink/renderer/core/loader/frame_or_imported_document.h"
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/core/script/fetch_client_settings_object_impl.h"
#include "third_party/blink/renderer/platform/loader/fetch/fetch_client_settings_object.h"
@@ -19,31 +20,50 @@
namespace blink {
+namespace {
+
+// Feature for throttling field trial.
+const base::Feature kResourceLoadThrottlingTrial{
+ "ResourceLoadScheduler", base::FEATURE_DISABLED_BY_DEFAULT};
+
+// Field trial parameters.
+// Note: bg_limit is supported on m61+, but bg_sub_limit is only on m63+.
+// If bg_sub_limit param is not found, we should use bg_limit to make the
+// study result statistically correct.
+constexpr base::FeatureParam<int> kOutstandingLimitForBackgroundMainFrame{
+ &kResourceLoadThrottlingTrial, "bg_limit", 3};
+constexpr base::FeatureParam<int> kOutstandingLimitForBackgroundSubFrame{
+ &kResourceLoadThrottlingTrial, "bg_sub_limit", 2};
+
+} // namespace
+
FrameResourceFetcherProperties::FrameResourceFetcherProperties(
- FrameOrImportedDocument& frame_or_imported_document)
- : frame_or_imported_document_(frame_or_imported_document),
+ DocumentLoader& document_loader,
+ Document& document)
+ : document_loader_(document_loader),
+ document_(document),
fetch_client_settings_object_(
MakeGarbageCollected<FetchClientSettingsObjectImpl>(
- *frame_or_imported_document.GetDocument().ToExecutionContext())),
- web_bundle_physical_url_(
- frame_or_imported_document_->GetMasterDocumentLoader()
- .WebBundlePhysicalUrl()) {}
+ *document.domWindow())),
+ web_bundle_physical_url_(document_loader.WebBundlePhysicalUrl()) {}
void FrameResourceFetcherProperties::Trace(Visitor* visitor) {
- visitor->Trace(frame_or_imported_document_);
+ visitor->Trace(document_loader_);
+ visitor->Trace(document_);
visitor->Trace(fetch_client_settings_object_);
ResourceFetcherProperties::Trace(visitor);
}
bool FrameResourceFetcherProperties::IsMainFrame() const {
- return frame_or_imported_document_->GetFrame().IsMainFrame();
+ LocalFrame* frame = document_->GetFrame();
+ DCHECK(frame);
+ return frame->IsMainFrame();
}
mojom::ControllerServiceWorkerMode
FrameResourceFetcherProperties::GetControllerServiceWorkerMode() const {
auto* service_worker_network_provider =
- frame_or_imported_document_->GetMasterDocumentLoader()
- .GetServiceWorkerNetworkProvider();
+ document_loader_->GetServiceWorkerNetworkProvider();
if (!service_worker_network_provider)
return blink::mojom::ControllerServiceWorkerMode::kNoController;
return service_worker_network_provider->GetControllerServiceWorkerMode();
@@ -53,32 +73,31 @@ int64_t FrameResourceFetcherProperties::ServiceWorkerId() const {
DCHECK_NE(GetControllerServiceWorkerMode(),
blink::mojom::ControllerServiceWorkerMode::kNoController);
auto* service_worker_network_provider =
- frame_or_imported_document_->GetMasterDocumentLoader()
- .GetServiceWorkerNetworkProvider();
+ document_loader_->GetServiceWorkerNetworkProvider();
DCHECK(service_worker_network_provider);
return service_worker_network_provider->ControllerServiceWorkerID();
}
bool FrameResourceFetcherProperties::IsPaused() const {
- return frame_or_imported_document_->GetFrame().GetPage()->Paused();
+ LocalFrame* frame = document_->GetFrame();
+ DCHECK(frame);
+ return frame->GetPage()->Paused();
}
bool FrameResourceFetcherProperties::IsLoadComplete() const {
- return frame_or_imported_document_->GetDocument().LoadEventFinished();
+ return document_->LoadEventFinished();
}
bool FrameResourceFetcherProperties::ShouldBlockLoadingSubResource() const {
- DocumentLoader* document_loader =
- frame_or_imported_document_->GetDocumentLoader();
- if (!document_loader)
- return false;
-
- FrameLoader& loader = frame_or_imported_document_->GetFrame().Loader();
- return document_loader != loader.GetDocumentLoader();
+ LocalFrame* frame = document_->GetFrame();
+ DCHECK(frame);
+ return document_loader_ != frame->Loader().GetDocumentLoader();
}
bool FrameResourceFetcherProperties::IsSubframeDeprioritizationEnabled() const {
- Settings* settings = frame_or_imported_document_->GetFrame().GetSettings();
+ LocalFrame* frame = document_->GetFrame();
+ DCHECK(frame);
+ Settings* settings = frame->GetSettings();
if (!settings) {
return false;
}
@@ -105,12 +124,22 @@ bool FrameResourceFetcherProperties::IsSubframeDeprioritizationEnabled() const {
}
scheduler::FrameStatus FrameResourceFetcherProperties::GetFrameStatus() const {
- return scheduler::GetFrameStatus(
- frame_or_imported_document_->GetFrame().GetFrameScheduler());
+ LocalFrame* frame = document_->GetFrame();
+ DCHECK(frame);
+ return scheduler::GetFrameStatus(frame->GetFrameScheduler());
}
const KURL& FrameResourceFetcherProperties::WebBundlePhysicalUrl() const {
return web_bundle_physical_url_;
}
+int FrameResourceFetcherProperties::GetOutstandingThrottledLimit() const {
+ static const int main_frame_limit =
+ kOutstandingLimitForBackgroundMainFrame.Get();
+ static const int sub_frame_limit =
+ kOutstandingLimitForBackgroundSubFrame.Get();
+
+ return IsMainFrame() ? main_frame_limit : sub_frame_limit;
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/loader/frame_resource_fetcher_properties.h b/chromium/third_party/blink/renderer/core/loader/frame_resource_fetcher_properties.h
index e07906c5ff1..25519cc9a76 100644
--- a/chromium/third_party/blink/renderer/core/loader/frame_resource_fetcher_properties.h
+++ b/chromium/third_party/blink/renderer/core/loader/frame_resource_fetcher_properties.h
@@ -12,22 +12,20 @@
namespace blink {
-class FrameOrImportedDocument;
+class Document;
+class DocumentLoader;
// FrameResourceFetcherProperties is a ResourceFetcherProperties implementation
// for Frame.
class CORE_EXPORT FrameResourceFetcherProperties final
: public ResourceFetcherProperties {
public:
- explicit FrameResourceFetcherProperties(FrameOrImportedDocument&);
+ FrameResourceFetcherProperties(DocumentLoader& document_loader,
+ Document& document);
~FrameResourceFetcherProperties() override = default;
void Trace(Visitor*) override;
- const FrameOrImportedDocument& GetFrameOrImportedDocument() const {
- return *frame_or_imported_document_;
- }
-
// ResourceFetcherProperties implementation
const FetchClientSettingsObject& GetFetchClientSettingsObject()
const override {
@@ -43,9 +41,11 @@ class CORE_EXPORT FrameResourceFetcherProperties final
bool IsSubframeDeprioritizationEnabled() const override;
scheduler::FrameStatus GetFrameStatus() const override;
const KURL& WebBundlePhysicalUrl() const override;
+ int GetOutstandingThrottledLimit() const override;
private:
- const Member<FrameOrImportedDocument> frame_or_imported_document_;
+ const Member<DocumentLoader> document_loader_;
+ const Member<Document> document_;
Member<const FetchClientSettingsObject> fetch_client_settings_object_;
const KURL web_bundle_physical_url_;
};
diff --git a/chromium/third_party/blink/renderer/core/loader/frame_resource_fetcher_properties_test.cc b/chromium/third_party/blink/renderer/core/loader/frame_resource_fetcher_properties_test.cc
index 815a39e03b0..968851a1b28 100644
--- a/chromium/third_party/blink/renderer/core/loader/frame_resource_fetcher_properties_test.cc
+++ b/chromium/third_party/blink/renderer/core/loader/frame_resource_fetcher_properties_test.cc
@@ -7,7 +7,6 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/frame/settings.h"
-#include "third_party/blink/renderer/core/loader/frame_or_imported_document.h"
#include "third_party/blink/renderer/core/testing/dummy_page_holder.h"
#include "third_party/blink/renderer/platform/network/network_state_notifier.h"
@@ -18,9 +17,8 @@ class FrameResourceFetcherPropertiesTest : public testing::Test {
FrameResourceFetcherPropertiesTest()
: dummy_page_holder_(std::make_unique<DummyPageHolder>(IntSize(1, 1))),
properties_(MakeGarbageCollected<FrameResourceFetcherProperties>(
- *MakeGarbageCollected<FrameOrImportedDocument>(
- *dummy_page_holder_->GetDocument().Loader(),
- dummy_page_holder_->GetDocument()))) {}
+ *dummy_page_holder_->GetDocument().Loader(),
+ dummy_page_holder_->GetDocument())) {}
protected:
const std::unique_ptr<DummyPageHolder> dummy_page_holder_;
diff --git a/chromium/third_party/blink/renderer/core/loader/http_equiv.cc b/chromium/third_party/blink/renderer/core/loader/http_equiv.cc
index 9e8ed4ee4f1..171d9b1f632 100644
--- a/chromium/third_party/blink/renderer/core/loader/http_equiv.cc
+++ b/chromium/third_party/blink/renderer/core/loader/http_equiv.cc
@@ -28,18 +28,6 @@ namespace blink {
namespace {
-// Returns true if the origin of |url| is same as the origin of the top level
-// frame's main resource.
-bool IsFirstPartyOrigin(Frame* frame, const KURL& url) {
- if (!frame)
- return false;
- return frame->Tree()
- .Top()
- .GetSecurityContext()
- ->GetSecurityOrigin()
- ->IsSameOriginWith(SecurityOrigin::Create(url).get());
-}
-
// Returns true if execution of scripts from the url are allowed. Compared to
// AllowScriptFromSource(), this method does not generate any
// notification to the |ContentSettingsClient| that the execution of the
@@ -56,40 +44,6 @@ bool AllowScriptFromSourceWithoutNotifying(
return allow_script;
}
-// Notifies content settings client of persistent client hint headers.
-void NotifyPersistentClientHintsToContentSettingsClient(Document& document) {
- base::TimeDelta persist_duration;
- if (RuntimeEnabledFeatures::FeaturePolicyForClientHintsEnabled()) {
- persist_duration = base::TimeDelta::Max();
- } else {
- persist_duration =
- document.GetFrame()->GetClientHintsPreferences().GetPersistDuration();
- }
-
- if (persist_duration.InSeconds() <= 0)
- return;
-
- WebEnabledClientHints enabled_client_hints = document.GetFrame()
- ->GetClientHintsPreferences()
- .GetWebEnabledClientHints();
- if (!AllowScriptFromSourceWithoutNotifying(
- document.Url(), document.GetFrame()->GetContentSettingsClient(),
- document.GetFrame()->GetSettings())) {
- // Do not persist client hint preferences if the JavaScript is disabled.
- return;
- }
-
- if (!document.GetFrame()->IsMainFrame() &&
- !IsFirstPartyOrigin(document.GetFrame(), document.Url())) {
- return;
- }
-
- if (auto* settings_client = document.GetFrame()->GetContentSettingsClient()) {
- settings_client->PersistClientHints(enabled_client_hints, persist_duration,
- document.Url());
- }
-}
-
} // namespace
void HttpEquiv::Process(Document& document,
@@ -118,8 +72,6 @@ void HttpEquiv::Process(Document& document,
"document. It may not be set inside <meta>."));
} else if (EqualIgnoringASCIICase(equiv, http_names::kAcceptCH)) {
ProcessHttpEquivAcceptCH(document, content);
- } else if (EqualIgnoringASCIICase(equiv, http_names::kAcceptCHLifetime)) {
- ProcessHttpEquivAcceptCHLifetime(document, content);
} else if (EqualIgnoringASCIICase(equiv, "content-security-policy") ||
EqualIgnoringASCIICase(equiv,
"content-security-policy-report-only")) {
@@ -161,27 +113,22 @@ void HttpEquiv::ProcessHttpEquivAcceptCH(Document& document,
if (!frame)
return;
- UseCounter::Count(document, WebFeature::kClientHintsMetaAcceptCH);
- FrameClientHintsPreferencesContext hints_context(frame);
- frame->GetClientHintsPreferences().UpdateFromAcceptClientHintsHeader(
- content, document.Url(), &hints_context);
- NotifyPersistentClientHintsToContentSettingsClient(document);
-}
-
-void HttpEquiv::ProcessHttpEquivAcceptCHLifetime(Document& document,
- const AtomicString& content) {
- LocalFrame* frame = document.GetFrame();
- if (!frame)
+ if (!document.GetFrame()->IsMainFrame()) {
return;
+ }
- if (RuntimeEnabledFeatures::FeaturePolicyForClientHintsEnabled())
+ if (!AllowScriptFromSourceWithoutNotifying(
+ document.Url(), document.GetFrame()->GetContentSettingsClient(),
+ document.GetFrame()->GetSettings())) {
+ // Do not allow configuring client hints if JavaScript is disabled.
return;
+ }
- UseCounter::Count(document, WebFeature::kClientHintsMetaAcceptCHLifetime);
+ UseCounter::Count(document, WebFeature::kClientHintsMetaAcceptCH);
FrameClientHintsPreferencesContext hints_context(frame);
- frame->GetClientHintsPreferences().UpdateFromAcceptClientHintsLifetimeHeader(
- content, document.Url(), &hints_context);
- NotifyPersistentClientHintsToContentSettingsClient(document);
+ frame->GetClientHintsPreferences().UpdateFromAcceptClientHintsHeader(
+ content, document.Url(), ClientHintsPreferences::UpdateMode::kMerge,
+ &hints_context);
}
void HttpEquiv::ProcessHttpEquivDefaultStyle(Document& document,
diff --git a/chromium/third_party/blink/renderer/core/loader/http_equiv.h b/chromium/third_party/blink/renderer/core/loader/http_equiv.h
index 5074adc1901..d6a2ca432fb 100644
--- a/chromium/third_party/blink/renderer/core/loader/http_equiv.h
+++ b/chromium/third_party/blink/renderer/core/loader/http_equiv.h
@@ -45,8 +45,6 @@ class HttpEquiv {
const AtomicString& equiv,
const AtomicString& content);
static void ProcessHttpEquivAcceptCH(Document&, const AtomicString& content);
- static void ProcessHttpEquivAcceptCHLifetime(Document&,
- const AtomicString& content);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/loader/idleness_detector.cc b/chromium/third_party/blink/renderer/core/loader/idleness_detector.cc
index 5b910a0a934..402f57cc5f9 100644
--- a/chromium/third_party/blink/renderer/core/loader/idleness_detector.cc
+++ b/chromium/third_party/blink/renderer/core/loader/idleness_detector.cc
@@ -4,7 +4,7 @@
#include "third_party/blink/renderer/core/loader/idleness_detector.h"
-#include "base/logging.h"
+#include "base/check.h"
#include "base/time/default_tick_clock.h"
#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_network_provider.h"
#include "third_party/blink/public/platform/platform.h"
diff --git a/chromium/third_party/blink/renderer/core/loader/image_loader.cc b/chromium/third_party/blink/renderer/core/loader/image_loader.cc
index a5f02639f9b..8553ebd9e40 100644
--- a/chromium/third_party/blink/renderer/core/loader/image_loader.cc
+++ b/chromium/third_party/blink/renderer/core/loader/image_loader.cc
@@ -45,6 +45,7 @@
#include "third_party/blink/renderer/core/frame/settings.h"
#include "third_party/blink/renderer/core/html/cross_origin_attribute.h"
#include "third_party/blink/renderer/core/html/html_image_element.h"
+#include "third_party/blink/renderer/core/html/loading_attribute.h"
#include "third_party/blink/renderer/core/html/parser/html_parser_idioms.h"
#include "third_party/blink/renderer/core/html_names.h"
#include "third_party/blink/renderer/core/layout/layout_image.h"
@@ -86,7 +87,7 @@ bool CheckForUnoptimizedImagePolicy(Document& document,
// and are planned to be removed.
if (RuntimeEnabledFeatures::DocumentPolicyEnabled(&document) &&
!new_image->IsAcceptableCompressionRatio(
- *document.ToExecutionContext())) {
+ *document.GetExecutionContext())) {
return true;
}
@@ -100,7 +101,7 @@ static ImageLoader::BypassMainWorldBehavior ShouldBypassMainWorldCSP(
DCHECK(loader);
DCHECK(loader->GetElement());
if (ContentSecurityPolicy::ShouldBypassMainWorld(
- loader->GetElement()->GetDocument().ToExecutionContext())) {
+ loader->GetElement()->GetExecutionContext())) {
return ImageLoader::kBypassMainWorldCSP;
}
return ImageLoader::kDoNotBypassMainWorldCSP;
@@ -109,16 +110,13 @@ static ImageLoader::BypassMainWorldBehavior ShouldBypassMainWorldCSP(
class ImageLoader::Task {
public:
Task(ImageLoader* loader,
- const KURL& request_url,
UpdateFromElementBehavior update_behavior,
network::mojom::ReferrerPolicy referrer_policy)
: loader_(loader),
should_bypass_main_world_csp_(ShouldBypassMainWorldCSP(loader)),
update_behavior_(update_behavior),
- referrer_policy_(referrer_policy),
- request_url_(request_url) {
- ExecutionContext* context =
- loader_->GetElement()->GetDocument().ToExecutionContext();
+ referrer_policy_(referrer_policy) {
+ ExecutionContext* context = loader_->GetElement()->GetExecutionContext();
probe::AsyncTaskScheduled(context, "Image", &async_task_id_);
v8::Isolate* isolate = V8PerIsolateData::MainThreadIsolate();
v8::HandleScope scope(isolate);
@@ -136,19 +134,16 @@ class ImageLoader::Task {
void Run() {
if (!loader_)
return;
- ExecutionContext* context =
- loader_->GetElement()->GetDocument().ToExecutionContext();
+ ExecutionContext* context = loader_->GetElement()->GetExecutionContext();
probe::AsyncTask async_task(context, &async_task_id_);
if (script_state_ && script_state_->ContextIsValid()) {
ScriptState::Scope scope(script_state_);
loader_->DoUpdateFromElement(should_bypass_main_world_csp_,
- update_behavior_, request_url_,
- referrer_policy_);
+ update_behavior_, referrer_policy_);
} else {
// This call does not access v8::Context internally.
loader_->DoUpdateFromElement(should_bypass_main_world_csp_,
- update_behavior_, request_url_,
- referrer_policy_);
+ update_behavior_, referrer_policy_);
}
}
@@ -165,7 +160,7 @@ class ImageLoader::Task {
UpdateFromElementBehavior update_behavior_;
WeakPersistent<ScriptState> script_state_;
network::mojom::ReferrerPolicy referrer_policy_;
- KURL request_url_;
+
probe::AsyncTaskId async_task_id_;
base::WeakPtrFactory<Task> weak_factory_{this};
};
@@ -174,7 +169,7 @@ ImageLoader::ImageLoader(Element* element)
: element_(element),
image_complete_(true),
suppress_error_events_(false),
- was_fully_deferred_(false),
+ was_deferred_explicitly_(false),
lazy_image_load_state_(LazyImageLoadState::kNone) {
RESOURCE_LOADING_DVLOG(1) << "new ImageLoader " << this;
}
@@ -195,6 +190,15 @@ void ImageLoader::Dispose() {
}
}
+static bool ImageTypeNeedsDecode(const Image& image) {
+ // SVG images are context sensitive, and decoding them without the proper
+ // context will just end up wasting memory (and CPU).
+ // TODO(vmpstr): Generalize this to be all non-lazy decoded images.
+ if (IsA<SVGImage>(image))
+ return false;
+ return true;
+}
+
void ImageLoader::DispatchDecodeRequestsIfComplete() {
// If the current image isn't complete, then we can't dispatch any decodes.
// This function will be called again when the current image completes.
@@ -211,14 +215,24 @@ void ImageLoader::DispatchDecodeRequestsIfComplete() {
}
LocalFrame* frame = GetElement()->GetDocument().GetFrame();
- for (auto& request : decode_requests_) {
- // If the image already in kDispatched state or still in kPEndingMicrotask
+ auto* it = decode_requests_.begin();
+ while (it != decode_requests_.end()) {
+ // If the image already in kDispatched state or still in kPendingMicrotask
// state, then we don't dispatch decodes for it. So, the only case to handle
// is if we're in kPendingLoad state.
- if (request->state() != DecodeRequest::kPendingLoad)
+ auto& request = *it;
+ if (request->state() != DecodeRequest::kPendingLoad) {
+ ++it;
continue;
+ }
Image* image = GetContent()->GetImage();
-
+ if (!ImageTypeNeedsDecode(*image)) {
+ // If the image is of a type that doesn't need decode, resolve the
+ // promise.
+ request->Resolve();
+ it = decode_requests_.erase(it);
+ continue;
+ }
// ImageLoader should be kept alive when decode is still pending. JS may
// invoke 'decode' without capturing the Image object. If GC kicks in,
// ImageLoader will be destroyed, leading to unresolved/unrejected Promise.
@@ -227,6 +241,7 @@ void ImageLoader::DispatchDecodeRequestsIfComplete() {
WTF::Bind(&ImageLoader::DecodeRequestFinished,
WrapCrossThreadPersistent(this), request->request_id()));
request->NotifyDecodeDispatched();
+ ++it;
}
}
@@ -307,8 +322,7 @@ bool ImageLoader::ShouldUpdateOnInsertedInto(
}
bool ImageLoader::ImageIsPotentiallyAvailable() const {
- bool is_lazyload = lazy_image_load_state_ == LazyImageLoadState::kDeferred &&
- was_fully_deferred_;
+ bool is_lazyload = lazy_image_load_state_ == LazyImageLoadState::kDeferred;
bool image_has_loaded = image_content_ && !image_content_->IsLoading() &&
!image_content_->ErrorOccurred();
@@ -387,7 +401,7 @@ static void ConfigureRequest(
auto* html_image_element = DynamicTo<HTMLImageElement>(element);
if (client_hints_preferences.ShouldSend(
- mojom::WebClientHintsType::kResourceWidth) &&
+ network::mojom::WebClientHintsType::kResourceWidth) &&
html_image_element)
params.SetResourceWidth(html_image_element->GetResourceWidth());
}
@@ -416,11 +430,9 @@ inline void ImageLoader::ClearFailedLoadURL() {
}
inline void ImageLoader::EnqueueImageLoadingMicroTask(
- const KURL& request_url,
UpdateFromElementBehavior update_behavior,
network::mojom::ReferrerPolicy referrer_policy) {
- auto task = std::make_unique<Task>(this, request_url, update_behavior,
- referrer_policy);
+ auto task = std::make_unique<Task>(this, update_behavior, referrer_policy);
pending_task_ = task->GetWeakPtr();
Microtask::EnqueueMicrotask(
WTF::Bind(&Task::Run, WTF::Passed(std::move(task))));
@@ -435,7 +447,7 @@ void ImageLoader::UpdateImageState(ImageResourceContent* new_image_content) {
image_complete_ = true;
if (lazy_image_load_state_ == LazyImageLoadState::kDeferred) {
LazyImageHelper::StopMonitoring(GetElement());
- lazy_image_load_state_ = LazyImageLoadState::kFullImage;
+ lazy_image_load_state_ = LazyImageLoadState::kNone;
}
} else {
image_complete_ = false;
@@ -448,7 +460,6 @@ void ImageLoader::UpdateImageState(ImageResourceContent* new_image_content) {
void ImageLoader::DoUpdateFromElement(
BypassMainWorldBehavior bypass_behavior,
UpdateFromElementBehavior update_behavior,
- const KURL& url,
network::mojom::ReferrerPolicy referrer_policy,
UpdateType update_type) {
// FIXME: According to
@@ -469,6 +480,7 @@ void ImageLoader::DoUpdateFromElement(
return;
AtomicString image_source_url = element_->ImageSourceURL();
+ const KURL url = ImageSourceToKURL(image_source_url);
ImageResourceContent* new_image_content = nullptr;
if (!url.IsNull() && !url.IsEmpty()) {
// Unlike raw <img>, we block mixed content inside of <picture> or
@@ -523,36 +535,37 @@ void ImageLoader::DoUpdateFromElement(
ConfigureRequest(params, bypass_behavior, *element_,
document.GetFrame()->GetClientHintsPreferences());
- if (update_behavior != kUpdateForcedReload &&
- lazy_image_load_state_ == LazyImageLoadState::kNone) {
+ if ((update_behavior != kUpdateForcedReload &&
+ lazy_image_load_state_ == LazyImageLoadState::kNone) ||
+ (update_behavior == kUpdateSizeChanged &&
+ lazy_image_load_state_ == LazyImageLoadState::kDeferred)) {
const auto* frame = document.GetFrame();
if (auto* html_image = DynamicTo<HTMLImageElement>(GetElement())) {
+ LoadingAttributeValue loading_attr = GetLoadingAttributeValue(
+ html_image->FastGetAttribute(html_names::kLoadingAttr));
switch (LazyImageHelper::DetermineEligibilityAndTrackVisibilityMetrics(
*frame, html_image, params.Url())) {
case LazyImageHelper::Eligibility::kEnabledFullyDeferred:
lazy_image_load_state_ = LazyImageLoadState::kDeferred;
- was_fully_deferred_ = true;
+ was_deferred_explicitly_ =
+ (loading_attr == LoadingAttributeValue::kLazy);
params.SetLazyImageDeferred();
if (frame->Client()) {
frame->Client()->DidObserveLazyLoadBehavior(
WebLocalFrameClient::LazyLoadBehavior::kDeferredImage);
}
break;
- case LazyImageHelper::Eligibility::kEnabledFetchPlaceholder:
- lazy_image_load_state_ = LazyImageLoadState::kDeferred;
- params.SetLazyImagePlaceholder();
- break;
case LazyImageHelper::Eligibility::kDisabled:
break;
}
}
}
- // If the image was previously set to full image and had no dimensions, it
- // is a full load of a placeholder image.
- if (!was_fully_deferred_ &&
+ // If we're now loading in a once-deferred image, make sure it doesn't block
+ // the load event.
+ if (was_deferred_explicitly_ &&
lazy_image_load_state_ == LazyImageLoadState::kFullImage) {
- params.SetLazyImageAutoReload();
+ params.SetLazyImageNonBlocking();
}
// Enable subresource redirect for <img> elements created by parser when
@@ -597,9 +610,7 @@ void ImageLoader::DoUpdateFromElement(
new_image_content == old_image_content) {
ToLayoutImage(element_->GetLayoutObject())->IntrinsicSizeChanged();
} else {
- bool is_lazyload =
- lazy_image_load_state_ == LazyImageLoadState::kDeferred &&
- was_fully_deferred_;
+ bool is_lazyload = lazy_image_load_state_ == LazyImageLoadState::kDeferred;
// Loading didn't start (loading of images was disabled). We show fallback
// contents here, while we don't dispatch an 'error' event etc., because
@@ -677,10 +688,8 @@ void ImageLoader::UpdateFromElement(
delay_until_do_update_from_element_ = nullptr;
}
- KURL url = ImageSourceToKURL(image_source_url);
-
- if (ShouldLoadImmediately(url)) {
- DoUpdateFromElement(kDoNotBypassMainWorldCSP, update_behavior, url,
+ if (ShouldLoadImmediately(ImageSourceToKURL(image_source_url))) {
+ DoUpdateFromElement(kDoNotBypassMainWorldCSP, update_behavior,
referrer_policy, UpdateType::kSync);
return;
}
@@ -705,7 +714,7 @@ void ImageLoader::UpdateFromElement(
// images we don't intend to display.
Document& document = element_->GetDocument();
if (!document.IsContextDestroyed() && document.IsActive())
- EnqueueImageLoadingMicroTask(url, update_behavior, referrer_policy);
+ EnqueueImageLoadingMicroTask(update_behavior, referrer_policy);
}
KURL ImageLoader::ImageSourceToKURL(AtomicString image_source_url) const {
@@ -951,7 +960,7 @@ void ImageLoader::LoadDeferredImage(
// If the image has been fully deferred (no placeholder fetch), report it as
// fully loaded now.
LocalFrame* frame = element_->GetDocument().GetFrame();
- if (was_fully_deferred_ && frame && frame->Client()) {
+ if (frame && frame->Client()) {
frame->Client()->DidObserveLazyLoadBehavior(
WebLocalFrameClient::LazyLoadBehavior::kLazyLoadedImage);
}
diff --git a/chromium/third_party/blink/renderer/core/loader/image_loader.h b/chromium/third_party/blink/renderer/core/loader/image_loader.h
index 181069a59f9..a2c3147fbc0 100644
--- a/chromium/third_party/blink/renderer/core/loader/image_loader.h
+++ b/chromium/third_party/blink/renderer/core/loader/image_loader.h
@@ -160,20 +160,17 @@ class CORE_EXPORT ImageLoader : public GarbageCollected<ImageLoader>,
enum class LazyImageLoadState {
kNone, // LazyImages not active.
kDeferred, // Full image load not started, and image load event will not be
- // fired. If image dimensions is present, document load event
- // will be unblocked. Otherwise placeholder fetch will start,
- // and once its done document load event is unblocked.
+ // fired. Image will not block the document's load event.
kFullImage // Full image is loading/loaded, due to element coming near the
- // viewport or if a placeholder load actually fetched the full
- // image. image_complete_ can differentiate if the fetch is
- // complete or not. After the fetch, image load event is fired.
+ // viewport. image_complete_ can be used to differentiate if the
+ // fetch is complete or not. After the fetch, image load event
+ // is fired.
};
// Called from the task or from updateFromElement to initiate the load.
void DoUpdateFromElement(
BypassMainWorldBehavior,
UpdateFromElementBehavior,
- const KURL&,
network::mojom::ReferrerPolicy = network::mojom::ReferrerPolicy::kDefault,
UpdateType = UpdateType::kAsync);
@@ -197,8 +194,7 @@ class CORE_EXPORT ImageLoader : public GarbageCollected<ImageLoader>,
void ClearFailedLoadURL();
void DispatchErrorEvent();
void CrossSiteOrCSPViolationOccurred(AtomicString);
- void EnqueueImageLoadingMicroTask(const KURL&,
- UpdateFromElementBehavior,
+ void EnqueueImageLoadingMicroTask(UpdateFromElementBehavior,
network::mojom::ReferrerPolicy);
KURL ImageSourceToKURL(AtomicString) const;
@@ -252,7 +248,12 @@ class CORE_EXPORT ImageLoader : public GarbageCollected<ImageLoader>,
bool image_complete_ : 1;
bool suppress_error_events_ : 1;
- bool was_fully_deferred_ : 1; // Used by LazyImageLoad.
+ // Tracks whether or not an image whose load was deferred was explicitly lazy
+ // (i.e., had developer-supplied `loading=lazy`). This matters because images
+ // that were not explicitly lazy but were deferred via automatic lazy image
+ // loading should continue to block the window load event, whereas explicitly
+ // lazy images should never block the window load event.
+ bool was_deferred_explicitly_ : 1;
LazyImageLoadState lazy_image_load_state_;
diff --git a/chromium/third_party/blink/renderer/core/loader/interactive_detector.cc b/chromium/third_party/blink/renderer/core/loader/interactive_detector.cc
index 8ce504fc1fe..09ac77e0bdb 100644
--- a/chromium/third_party/blink/renderer/core/loader/interactive_detector.cc
+++ b/chromium/third_party/blink/renderer/core/loader/interactive_detector.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/core/loader/interactive_detector.h"
#include "base/metrics/histogram_macros.h"
+#include "base/profiler/sample_metadata.h"
#include "base/time/default_tick_clock.h"
#include "services/metrics/public/cpp/ukm_builders.h"
#include "services/metrics/public/cpp/ukm_recorder.h"
@@ -19,7 +20,7 @@ namespace blink {
namespace {
// Used to generate a unique id when emitting the "Long Input Delay" trace
-// event.
+// event and metadata.
int g_num_long_input_events = 0;
// The threshold to emit the "Long Input Delay" trace event is the 99th
@@ -67,7 +68,7 @@ InteractiveDetector::InteractiveDetector(
Document& document,
NetworkActivityChecker* network_activity_checker)
: Supplement<Document>(document),
- ExecutionContextLifecycleObserver(&document),
+ ExecutionContextLifecycleObserver(document.GetExecutionContext()),
clock_(base::DefaultTickClock::GetInstance()),
network_activity_checker_(network_activity_checker),
time_to_interactive_timer_(
@@ -251,6 +252,11 @@ void InteractiveDetector::HandleForInputDelay(
TRACE_EVENT_ASYNC_END_WITH_TIMESTAMP0(
"latency", "Long Input Delay", TRACE_ID_LOCAL(g_num_long_input_events),
event_timestamp + delay);
+ // Apply metadata on stack samples.
+ base::ApplyMetadataToPastSamples(
+ event_timestamp, event_timestamp + delay,
+ "PageLoad.InteractiveTiming.LongInputDelay", g_num_long_input_events,
+ 1);
g_num_long_input_events++;
}
diff --git a/chromium/third_party/blink/renderer/core/loader/lazy_image_helper.cc b/chromium/third_party/blink/renderer/core/loader/lazy_image_helper.cc
index 0624d7cfffd..2678cc365a5 100644
--- a/chromium/third_party/blink/renderer/core/loader/lazy_image_helper.cc
+++ b/chromium/third_party/blink/renderer/core/loader/lazy_image_helper.cc
@@ -12,23 +12,12 @@
#include "third_party/blink/renderer/core/frame/web_feature.h"
#include "third_party/blink/renderer/core/html/html_image_element.h"
#include "third_party/blink/renderer/core/html/lazy_load_image_observer.h"
+#include "third_party/blink/renderer/core/html/loading_attribute.h"
namespace blink {
namespace {
-enum class LoadingAttrValue { kAuto, kLazy, kEager };
-
-LoadingAttrValue GetLoadingAttrValue(const HTMLImageElement& html_image) {
- const auto& attribute_value =
- html_image.FastGetAttribute(html_names::kLoadingAttr);
- return EqualIgnoringASCIICase(attribute_value, "eager")
- ? LoadingAttrValue::kEager
- : EqualIgnoringASCIICase(attribute_value, "lazy")
- ? LoadingAttrValue::kLazy
- : LoadingAttrValue::kAuto;
-}
-
// Returns true if absolute dimension is specified in the width and height
// attributes or in the inline style.
bool IsDimensionAbsoluteLarge(const HTMLImageElement& html_image) {
@@ -83,12 +72,19 @@ void LazyImageHelper::StartMonitoring(blink::Element* element) {
using DeferralMessage = LazyLoadImageObserver::DeferralMessage;
auto deferral_message = DeferralMessage::kNone;
if (auto* html_image = DynamicTo<HTMLImageElement>(element)) {
- LoadingAttrValue loading_attr = GetLoadingAttrValue(*html_image);
- DCHECK_NE(loading_attr, LoadingAttrValue::kEager);
- if (loading_attr == LoadingAttrValue::kAuto) {
+ LoadingAttributeValue effective_loading_attr = GetLoadingAttributeValue(
+ html_image->FastGetAttribute(html_names::kLoadingAttr));
+ // If the 'lazyload' feature policy is enforced, the attribute value
+ // loading='eager' is considered as 'auto'.
+ if (effective_loading_attr == LoadingAttributeValue::kEager &&
+ document->IsLazyLoadPolicyEnforced()) {
+ effective_loading_attr = LoadingAttributeValue::kAuto;
+ }
+ DCHECK_NE(effective_loading_attr, LoadingAttributeValue::kEager);
+ if (effective_loading_attr == LoadingAttributeValue::kAuto) {
deferral_message = DeferralMessage::kLoadEventsDeferred;
} else if (!IsDimensionAbsoluteLarge(*html_image)) {
- DCHECK_EQ(loading_attr, LoadingAttrValue::kLazy);
+ DCHECK_EQ(effective_loading_attr, LoadingAttributeValue::kLazy);
deferral_message = DeferralMessage::kMissingDimensionForLazy;
}
}
@@ -117,25 +113,22 @@ LazyImageHelper::DetermineEligibilityAndTrackVisibilityMetrics(
return LazyImageHelper::Eligibility::kDisabled;
const auto lazy_load_image_setting = frame.GetLazyLoadImageSetting();
- LoadingAttrValue loading_attr = GetLoadingAttrValue(*html_image);
+ LoadingAttributeValue loading_attr = GetLoadingAttributeValue(
+ html_image->FastGetAttribute(html_names::kLoadingAttr));
bool is_fully_loadable =
IsFullyLoadableFirstKImageAndDecrementCount(html_image);
- if (loading_attr == LoadingAttrValue::kLazy) {
+ if (loading_attr == LoadingAttributeValue::kLazy) {
StartMonitoringVisibility(html_image);
UseCounter::Count(frame.GetDocument(),
WebFeature::kLazyLoadImageLoadingAttributeLazy);
if (lazy_load_image_setting !=
LocalFrame::LazyLoadImageSetting::kDisabled) {
// Developer opt-in lazyload.
- if (!RuntimeEnabledFeatures::LazyImageLoadingMetadataFetchEnabled() ||
- IsDimensionAbsoluteLarge(*html_image)) {
- return LazyImageHelper::Eligibility::kEnabledFullyDeferred;
- }
- return LazyImageHelper::Eligibility::kEnabledFetchPlaceholder;
+ return LazyImageHelper::Eligibility::kEnabledFullyDeferred;
}
}
- if (loading_attr == LoadingAttrValue::kEager &&
+ if (loading_attr == LoadingAttributeValue::kEager &&
!frame.GetDocument()->IsLazyLoadPolicyEnforced()) {
UseCounter::Count(frame.GetDocument(),
WebFeature::kLazyLoadImageLoadingAttributeEager);
@@ -174,11 +167,7 @@ LazyImageHelper::DetermineEligibilityAndTrackVisibilityMetrics(
lazy_load_image_setting ==
LocalFrame::LazyLoadImageSetting::kEnabledAutomatic) {
// Automatic lazyload
- if (!RuntimeEnabledFeatures::LazyImageLoadingMetadataFetchEnabled() ||
- IsDimensionAbsoluteLarge(*html_image)) {
- return LazyImageHelper::Eligibility::kEnabledFullyDeferred;
- }
- return LazyImageHelper::Eligibility::kEnabledFetchPlaceholder;
+ return LazyImageHelper::Eligibility::kEnabledFullyDeferred;
}
return LazyImageHelper::Eligibility::kDisabled;
}
diff --git a/chromium/third_party/blink/renderer/core/loader/lazy_image_helper.h b/chromium/third_party/blink/renderer/core/loader/lazy_image_helper.h
index f6bd807ee46..3eef6ae3110 100644
--- a/chromium/third_party/blink/renderer/core/loader/lazy_image_helper.h
+++ b/chromium/third_party/blink/renderer/core/loader/lazy_image_helper.h
@@ -22,7 +22,6 @@ class LazyImageHelper final {
enum class Eligibility {
kDisabled,
kEnabledFullyDeferred,
- kEnabledFetchPlaceholder,
};
static void StartMonitoring(Element* element);
diff --git a/chromium/third_party/blink/renderer/core/loader/link_loader.cc b/chromium/third_party/blink/renderer/core/loader/link_loader.cc
index 755214834da..031eeedf530 100644
--- a/chromium/third_party/blink/renderer/core/loader/link_loader.cc
+++ b/chromium/third_party/blink/renderer/core/loader/link_loader.cc
@@ -33,6 +33,7 @@
#include "third_party/blink/public/common/prerender/prerender_rel_type.h"
#include "third_party/blink/renderer/core/dom/document.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/web_feature.h"
#include "third_party/blink/renderer/core/loader/importance_attribute.h"
@@ -223,10 +224,9 @@ void LinkLoader::LoadStylesheet(const LinkLoadParameters& params,
// context document for getting origin and ResourceFetcher to use the main
// Document's origin, while using element document for CompleteURL() to use
// imported Documents' base URLs.
- document_for_origin = document.ContextDocument();
+ document_for_origin =
+ To<LocalDOMWindow>(document.GetExecutionContext())->document();
}
- if (!document_for_origin)
- return;
ResourceRequest resource_request(document.CompleteURL(params.href));
resource_request.SetReferrerPolicy(params.referrer_policy);
@@ -257,7 +257,7 @@ void LinkLoader::LoadStylesheet(const LinkLoadParameters& params,
IntegrityMetadataSet metadata_set;
SubresourceIntegrity::ParseIntegrityAttribute(
integrity_attr,
- SubresourceIntegrityHelper::GetFeatures(document.ToExecutionContext()),
+ SubresourceIntegrityHelper::GetFeatures(document.GetExecutionContext()),
metadata_set);
link_fetch_params.SetIntegrityMetadata(metadata_set);
link_fetch_params.MutableResourceRequest().SetFetchIntegrity(
diff --git a/chromium/third_party/blink/renderer/core/loader/loader_factory_for_frame.cc b/chromium/third_party/blink/renderer/core/loader/loader_factory_for_frame.cc
index d0bbcb27424..dd52906f326 100644
--- a/chromium/third_party/blink/renderer/core/loader/loader_factory_for_frame.cc
+++ b/chromium/third_party/blink/renderer/core/loader/loader_factory_for_frame.cc
@@ -16,24 +16,22 @@
#include "third_party/blink/renderer/core/fileapi/public_url_manager.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/loader/document_loader.h"
-#include "third_party/blink/renderer/core/loader/frame_or_imported_document.h"
#include "third_party/blink/renderer/core/loader/prefetched_signed_exchange_manager.h"
#include "third_party/blink/renderer/platform/exported/wrapped_resource_request.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
namespace blink {
-LoaderFactoryForFrame::LoaderFactoryForFrame(
- const FrameOrImportedDocument& frame_or_imported_document)
- : frame_or_imported_document_(frame_or_imported_document),
+LoaderFactoryForFrame::LoaderFactoryForFrame(DocumentLoader& document_loader,
+ Document& document)
+ : document_loader_(document_loader),
+ document_(document),
prefetched_signed_exchange_manager_(
- frame_or_imported_document_->GetDocumentLoader()
- ? frame_or_imported_document_->GetDocumentLoader()
- ->GetPrefetchedSignedExchangeManager()
- : nullptr) {}
+ document_loader.GetPrefetchedSignedExchangeManager()) {}
void LoaderFactoryForFrame::Trace(Visitor* visitor) {
- visitor->Trace(frame_or_imported_document_);
+ visitor->Trace(document_loader_);
+ visitor->Trace(document_);
visitor->Trace(prefetched_signed_exchange_manager_);
LoaderFactory::Trace(visitor);
}
@@ -71,11 +69,12 @@ std::unique_ptr<WebURLLoader> LoaderFactoryForFrame::CreateURLLoader(
// callsite when we make Shared Worker loading off-main-thread.
if (request.Url().ProtocolIs("blob") && !url_loader_factory &&
request.GetRequestContext() != mojom::RequestContextType::SHARED_WORKER) {
- frame_or_imported_document_->GetDocument().GetPublicURLManager().Resolve(
+ document_->GetPublicURLManager().Resolve(
request.Url(), url_loader_factory.InitWithNewPipeAndPassReceiver());
}
- LocalFrame& frame = frame_or_imported_document_->GetFrame();
- FrameScheduler* frame_scheduler = frame.GetFrameScheduler();
+ LocalFrame* frame = document_->GetFrame();
+ DCHECK(frame);
+ FrameScheduler* frame_scheduler = frame->GetFrameScheduler();
DCHECK(frame_scheduler);
// TODO(altimin): frame_scheduler->CreateResourceLoadingTaskRunnerHandle is
@@ -90,11 +89,9 @@ std::unique_ptr<WebURLLoader> LoaderFactoryForFrame::CreateURLLoader(
webreq, frame_scheduler->CreateResourceLoadingTaskRunnerHandle());
}
- DocumentLoader& document_loader =
- frame_or_imported_document_->GetMasterDocumentLoader();
- if (document_loader.GetServiceWorkerNetworkProvider()) {
+ if (document_loader_->GetServiceWorkerNetworkProvider()) {
auto loader =
- document_loader.GetServiceWorkerNetworkProvider()->CreateURLLoader(
+ document_loader_->GetServiceWorkerNetworkProvider()->CreateURLLoader(
webreq, frame_scheduler->CreateResourceLoadingTaskRunnerHandle());
if (loader)
return loader;
@@ -106,7 +103,7 @@ std::unique_ptr<WebURLLoader> LoaderFactoryForFrame::CreateURLLoader(
if (loader)
return loader;
}
- return frame.GetURLLoaderFactory()->CreateURLLoader(
+ return frame->GetURLLoaderFactory()->CreateURLLoader(
webreq, frame_scheduler->CreateResourceLoadingTaskRunnerHandle());
}
diff --git a/chromium/third_party/blink/renderer/core/loader/loader_factory_for_frame.h b/chromium/third_party/blink/renderer/core/loader/loader_factory_for_frame.h
index 85d0fa090f1..cdea44d046b 100644
--- a/chromium/third_party/blink/renderer/core/loader/loader_factory_for_frame.h
+++ b/chromium/third_party/blink/renderer/core/loader/loader_factory_for_frame.h
@@ -12,12 +12,13 @@
namespace blink {
-class FrameOrImportedDocument;
+class Document;
+class DocumentLoader;
class PrefetchedSignedExchangeManager;
class LoaderFactoryForFrame final : public ResourceFetcher::LoaderFactory {
public:
- explicit LoaderFactoryForFrame(const FrameOrImportedDocument&);
+ LoaderFactoryForFrame(DocumentLoader& loader, Document& document);
void Trace(Visitor*) override;
@@ -29,7 +30,8 @@ class LoaderFactoryForFrame final : public ResourceFetcher::LoaderFactory {
std::unique_ptr<CodeCacheLoader> CreateCodeCacheLoader() override;
private:
- const Member<const FrameOrImportedDocument> frame_or_imported_document_;
+ const Member<DocumentLoader> document_loader_;
+ const Member<Document> document_;
const Member<PrefetchedSignedExchangeManager>
prefetched_signed_exchange_manager_;
};
diff --git a/chromium/third_party/blink/renderer/core/loader/mixed_content_checker.cc b/chromium/third_party/blink/renderer/core/loader/mixed_content_checker.cc
index 76cf757241c..53a51cbceae 100644
--- a/chromium/third_party/blink/renderer/core/loader/mixed_content_checker.cc
+++ b/chromium/third_party/blink/renderer/core/loader/mixed_content_checker.cc
@@ -33,6 +33,7 @@
#include "services/network/public/mojom/ip_address_space.mojom-blink.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/common/security_context/insecure_request_policy.h"
+#include "third_party/blink/public/mojom/devtools/inspector_issue.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/web_content_settings_client.h"
@@ -41,6 +42,7 @@
#include "third_party/blink/public/platform/web_worker_fetch_context.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/frame/frame.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/local_frame_client.h"
#include "third_party/blink/renderer/core/frame/settings.h"
@@ -48,6 +50,7 @@
#include "third_party/blink/renderer/core/loader/document_loader.h"
#include "third_party/blink/renderer/core/loader/frame_fetch_context.h"
#include "third_party/blink/renderer/core/loader/worker_fetch_context.h"
+#include "third_party/blink/renderer/core/probe/core_probes.h"
#include "third_party/blink/renderer/core/workers/worker_global_scope.h"
#include "third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.h"
#include "third_party/blink/renderer/core/workers/worker_settings.h"
@@ -209,6 +212,38 @@ bool IsWebSocketAllowedInWorker(const BaseFetchContext& fetch_context,
return settings && settings->GetAllowRunningOfInsecureContent();
}
+void CreateMixedContentIssue(
+ const KURL& main_resource_url,
+ const KURL& insecure_url,
+ const mojom::blink::RequestContextType request_context,
+ LocalFrame* frame,
+ const mojom::blink::MixedContentResolutionStatus resolution_status,
+ const base::Optional<String>& devtools_id) {
+ auto mixedContent = mojom::blink::MixedContentIssueDetails::New();
+ mixedContent->request_context = request_context,
+ mixedContent->resolution_status = resolution_status;
+ mixedContent->insecure_url = insecure_url.GetString();
+ mixedContent->main_resource_url = main_resource_url.GetString();
+
+ if (devtools_id) {
+ auto affected_request = mojom::blink::AffectedRequest::New();
+ affected_request->request_id = *devtools_id;
+ affected_request->url = insecure_url.GetString();
+ mixedContent->request = std::move(affected_request);
+ }
+
+ auto affected_frame = mojom::blink::AffectedFrame::New();
+ affected_frame->frame_id = frame->GetDevToolsFrameToken().ToString().c_str();
+ mixedContent->frame = std::move(affected_frame);
+
+ auto details = mojom::blink::InspectorIssueDetails::New();
+ details->mixed_content_issue_details = std::move(mixedContent);
+
+ frame->AddInspectorIssue(mojom::blink::InspectorIssueInfo::New(
+ mojom::blink::InspectorIssueCode::kMixedContentIssue,
+ std::move(details)));
+}
+
} // namespace
static void MeasureStricterVersionOfIsMixedContent(Frame& frame,
@@ -254,8 +289,14 @@ static bool IsInsecureUrl(const KURL& url) {
// static
bool MixedContentChecker::IsMixedContent(const SecurityOrigin* security_origin,
const KURL& url) {
+ return IsMixedContent(security_origin->Protocol(), url);
+}
+
+// static
+bool MixedContentChecker::IsMixedContent(const String& origin_protocol,
+ const KURL& url) {
if (!SchemeRegistry::ShouldTreatURLSchemeAsRestrictingMixedContent(
- security_origin->Protocol()))
+ origin_protocol))
return false;
return IsInsecureUrl(url);
@@ -381,6 +422,7 @@ bool MixedContentChecker::ShouldBlockFetch(
mojom::RequestContextType request_context,
ResourceRequest::RedirectStatus redirect_status,
const KURL& url,
+ const base::Optional<String>& devtools_id,
ReportingDisposition reporting_disposition) {
Frame* mixed_frame = InWhichFrameIsContentMixed(frame, url);
if (!mixed_frame)
@@ -496,6 +538,14 @@ bool MixedContentChecker::ShouldBlockFetch(
CreateConsoleMessageAboutFetch(MainResourceUrlForFrame(mixed_frame),
url, request_context, allowed, nullptr));
}
+ // Issue is created even when reporting disposition is false i.e. for
+ // speculative prefetches. Otherwise the DevTools frontend would not
+ // receive an issue with a devtools_id which it can match to a request.
+ CreateMixedContentIssue(
+ MainResourceUrlForFrame(mixed_frame), url, request_context, frame,
+ allowed ? mojom::blink::MixedContentResolutionStatus::MixedContentWarning
+ : mojom::blink::MixedContentResolutionStatus::MixedContentBlocked,
+ devtools_id);
return !allowed;
}
@@ -612,7 +662,12 @@ bool MixedContentChecker::IsWebSocketAllowed(
frame->GetDocument()->AddConsoleMessage(CreateConsoleMessageAboutWebSocket(
MainResourceUrlForFrame(mixed_frame), url, allowed));
-
+ CreateMixedContentIssue(
+ MainResourceUrlForFrame(mixed_frame), url,
+ mojom::blink::RequestContextType::FETCH, frame,
+ allowed ? mojom::blink::MixedContentResolutionStatus::MixedContentWarning
+ : mojom::blink::MixedContentResolutionStatus::MixedContentBlocked,
+ base::Optional<String>());
return allowed;
}
@@ -679,6 +734,14 @@ bool MixedContentChecker::IsMixedFormAction(
mojom::ConsoleMessageSource::kSecurity,
mojom::ConsoleMessageLevel::kWarning, message));
}
+ // Issue is created even when reporting disposition is false i.e. for
+ // speculative prefetches. Otherwise the DevTools frontend would not
+ // receive an issue with a devtools_id which it can match to a request.
+ CreateMixedContentIssue(
+ MainResourceUrlForFrame(mixed_frame), url,
+ mojom::blink::RequestContextType::FORM, frame,
+ mojom::blink::MixedContentResolutionStatus::MixedContentWarning,
+ base::Optional<String>());
return true;
}
@@ -775,6 +838,13 @@ void MixedContentChecker::MixedContentFound(
frame->GetDocument()->AddConsoleMessage(CreateConsoleMessageAboutFetch(
main_resource_url, mixed_content_url, request_context, was_allowed,
std::move(source_location)));
+
+ CreateMixedContentIssue(
+ main_resource_url, mixed_content_url, request_context, frame,
+ was_allowed
+ ? mojom::blink::MixedContentResolutionStatus::MixedContentWarning
+ : mojom::blink::MixedContentResolutionStatus::MixedContentBlocked,
+ base::Optional<String>());
// Reports to the CSP policy.
ContentSecurityPolicy* policy =
frame->GetSecurityContext()->GetContentSecurityPolicy();
@@ -854,13 +924,19 @@ void MixedContentChecker::UpgradeInsecureRequest(
// due to scheme not being http, so any redirects get upgraded.
resource_request.SetUpgradeIfInsecure(true);
if (resource_request.Url().ProtocolIs("http")) {
- if (execution_context_for_logging->IsDocument()) {
- Document* document = Document::From(execution_context_for_logging);
- document->AddConsoleMessage(
+ if (auto* window =
+ DynamicTo<LocalDOMWindow>(execution_context_for_logging)) {
+ window->AddConsoleMessage(
MixedContentChecker::CreateConsoleMessageAboutFetchAutoupgrade(
fetch_client_settings_object->GlobalObjectUrl(),
resource_request.Url()));
- resource_request.SetUkmSourceId(document->UkmSourceID());
+ resource_request.SetUkmSourceId(window->document()->UkmSourceID());
+ CreateMixedContentIssue(fetch_client_settings_object->GlobalObjectUrl(),
+ resource_request.Url(), context,
+ window->document()->GetFrame(),
+ mojom::blink::MixedContentResolutionStatus::
+ MixedContentAutomaticallyUpgraded,
+ resource_request.GetDevToolsId());
}
resource_request.SetIsAutomaticUpgrade(true);
} else {
diff --git a/chromium/third_party/blink/renderer/core/loader/mixed_content_checker.h b/chromium/third_party/blink/renderer/core/loader/mixed_content_checker.h
index 66b5f126416..c5ad31eb998 100644
--- a/chromium/third_party/blink/renderer/core/loader/mixed_content_checker.h
+++ b/chromium/third_party/blink/renderer/core/loader/mixed_content_checker.h
@@ -69,12 +69,13 @@ class CORE_EXPORT MixedContentChecker final {
DISALLOW_NEW();
public:
- static bool ShouldBlockFetch(
- LocalFrame*,
- mojom::RequestContextType,
- ResourceRequest::RedirectStatus,
- const KURL&,
- ReportingDisposition = ReportingDisposition::kReport);
+ static bool ShouldBlockFetch(LocalFrame* frame,
+ mojom::blink::RequestContextType request_context,
+ ResourceRequest::RedirectStatus redirect_status,
+ const KURL& url,
+ const base::Optional<String>& devtools_id,
+ ReportingDisposition reporting_disposition =
+ ReportingDisposition::kReport);
static bool ShouldBlockFetchOnWorker(const WorkerFetchContext&,
mojom::RequestContextType,
@@ -89,6 +90,7 @@ class CORE_EXPORT MixedContentChecker final {
static bool IsWebSocketAllowed(const WorkerFetchContext&, const KURL&);
static bool IsMixedContent(const SecurityOrigin*, const KURL&);
+ static bool IsMixedContent(const String& origin_protocol, const KURL&);
static bool IsMixedContent(const FetchClientSettingsObject&, const KURL&);
static bool IsMixedFormAction(
LocalFrame*,
diff --git a/chromium/third_party/blink/renderer/core/loader/mixed_content_checker_test.cc b/chromium/third_party/blink/renderer/core/loader/mixed_content_checker_test.cc
index 2ce38372705..7a36999af2e 100644
--- a/chromium/third_party/blink/renderer/core/loader/mixed_content_checker_test.cc
+++ b/chromium/third_party/blink/renderer/core/loader/mixed_content_checker_test.cc
@@ -7,7 +7,7 @@
#include <base/macros.h>
#include <memory>
#include "base/memory/scoped_refptr.h"
-#include "testing/gmock/include/gmock/gmock-generated-function-mockers.h"
+#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/mojom/loader/request_context_frame_type.mojom-blink.h"
#include "third_party/blink/public/platform/web_mixed_content.h"
@@ -206,13 +206,13 @@ TEST(MixedContentCheckerTest, DetectMixedFavicon) {
EXPECT_TRUE(MixedContentChecker::ShouldBlockFetch(
&dummy_page_holder->GetFrame(), mojom::RequestContextType::FAVICON,
ResourceRequest::RedirectStatus::kNoRedirect, http_favicon_url,
- ReportingDisposition::kSuppressReporting));
+ base::Optional<String>(), ReportingDisposition::kSuppressReporting));
// Test that a secure favicon is not blocked.
EXPECT_FALSE(MixedContentChecker::ShouldBlockFetch(
&dummy_page_holder->GetFrame(), mojom::RequestContextType::FAVICON,
ResourceRequest::RedirectStatus::kNoRedirect, https_favicon_url,
- ReportingDisposition::kSuppressReporting));
+ base::Optional<String>(), ReportingDisposition::kSuppressReporting));
}
class TestFetchClientSettingsObject : public FetchClientSettingsObject {
diff --git a/chromium/third_party/blink/renderer/core/loader/modulescript/module_script_loader.cc b/chromium/third_party/blink/renderer/core/loader/modulescript/module_script_loader.cc
index 0296fc6c786..60517e94b89 100644
--- a/chromium/third_party/blink/renderer/core/loader/modulescript/module_script_loader.cc
+++ b/chromium/third_party/blink/renderer/core/loader/modulescript/module_script_loader.cc
@@ -147,8 +147,8 @@ void ModuleScriptLoader::FetchInternal(
options.reject_coep_unsafe_none = options_.GetRejectCoepUnsafeNone();
if (level == ModuleGraphLevel::kDependentModuleFetch) {
- options.initiator_info.imported_module_referrer =
- module_request.ReferrerString();
+ options.initiator_info.is_imported_module = true;
+ options.initiator_info.referrer = module_request.ReferrerString();
options.initiator_info.position = module_request.GetReferrerPosition();
}
diff --git a/chromium/third_party/blink/renderer/core/loader/modulescript/module_script_loader_test.cc b/chromium/third_party/blink/renderer/core/loader/modulescript/module_script_loader_test.cc
index 42631bf83d8..27198816336 100644
--- a/chromium/third_party/blink/renderer/core/loader/modulescript/module_script_loader_test.cc
+++ b/chromium/third_party/blink/renderer/core/loader/modulescript/module_script_loader_test.cc
@@ -210,10 +210,13 @@ void ModuleScriptLoaderTest::InitializeForWorklet() {
nullptr /* worker_clients */, nullptr /* content_settings_client */,
network::mojom::IPAddressSpace::kLocal, nullptr /* origin_trial_token */,
base::UnguessableToken::Create(), nullptr /* worker_settings */,
- kV8CacheOptionsDefault,
- MakeGarbageCollected<WorkletModuleResponsesMap>());
+ kV8CacheOptionsDefault, MakeGarbageCollected<WorkletModuleResponsesMap>(),
+ mojo::NullRemote() /* browser_interface_broker */,
+ BeginFrameProviderParams(), nullptr /* parent_feature_policy */,
+ base::UnguessableToken::Create() /* agent_cluster_id */);
global_scope_ = MakeGarbageCollected<WorkletGlobalScope>(
- std::move(creation_params), *reporting_proxy_, &GetFrame());
+ std::move(creation_params), *reporting_proxy_, &GetFrame(),
+ false /* create_microtask_queue */);
global_scope_->ScriptController()->Initialize(NullURL());
modulator_ = MakeGarbageCollected<ModuleScriptLoaderTestModulator>(
global_scope_->ScriptController()->GetScriptState());
diff --git a/chromium/third_party/blink/renderer/core/loader/navigation_policy.cc b/chromium/third_party/blink/renderer/core/loader/navigation_policy.cc
index 7184c533596..fcf11e4572e 100644
--- a/chromium/third_party/blink/renderer/core/loader/navigation_policy.cc
+++ b/chromium/third_party/blink/renderer/core/loader/navigation_policy.cc
@@ -102,7 +102,7 @@ NavigationPolicy NavigationPolicyFromCurrentEvent() {
return kNavigationPolicyCurrentTab;
int16_t button = 0;
- if (event->GetType() == WebInputEvent::kMouseUp) {
+ if (event->GetType() == WebInputEvent::Type::kMouseUp) {
const WebMouseEvent* mouse_event = static_cast<const WebMouseEvent*>(event);
switch (mouse_event->button) {
diff --git a/chromium/third_party/blink/renderer/core/loader/navigation_policy_test.cc b/chromium/third_party/blink/renderer/core/loader/navigation_policy_test.cc
index 44f91a9568c..67e7e4a5c2a 100644
--- a/chromium/third_party/blink/renderer/core/loader/navigation_policy_test.cc
+++ b/chromium/third_party/blink/renderer/core/loader/navigation_policy_test.cc
@@ -48,7 +48,7 @@ class NavigationPolicyTest : public testing::Test {
NavigationPolicy GetPolicyForCreateWindow(int modifiers,
WebMouseEvent::Button button,
bool as_popup) {
- WebMouseEvent event(WebInputEvent::kMouseUp, modifiers,
+ WebMouseEvent event(WebInputEvent::Type::kMouseUp, modifiers,
WebInputEvent::GetStaticTimeStampForTests());
event.button = button;
if (as_popup)
@@ -82,7 +82,7 @@ class NavigationPolicyTest : public testing::Test {
WebMouseEvent::Button button,
int user_modifiers,
WebMouseEvent::Button user_button) {
- WebMouseEvent event(WebInputEvent::kMouseUp, user_modifiers,
+ WebMouseEvent event(WebInputEvent::Type::kMouseUp, user_modifiers,
WebInputEvent::GetStaticTimeStampForTests());
event.button = user_button;
base::AutoReset<const WebInputEvent*> current_event_change(
diff --git a/chromium/third_party/blink/renderer/core/loader/preload_helper.cc b/chromium/third_party/blink/renderer/core/loader/preload_helper.cc
index 7ad53e5e884..775f84c3426 100644
--- a/chromium/third_party/blink/renderer/core/loader/preload_helper.cc
+++ b/chromium/third_party/blink/renderer/core/loader/preload_helper.cc
@@ -122,7 +122,7 @@ KURL GetBestFitImageURL(const Document& document,
const String& image_srcset,
const String& image_sizes) {
float source_size = SizesAttributeParser(media_values, image_sizes,
- document.ToExecutionContext())
+ document.GetExecutionContext())
.length();
ImageCandidate candidate = BestFitSourceForImageAttributes(
media_values->DevicePixelRatio(), source_size, href, image_srcset);
@@ -280,7 +280,7 @@ Resource* PreloadHelper::PreloadIfNeeded(
if (!media_values)
media_values = CreateMediaValues(document, viewport_description);
if (!MediaMatches(params.media, media_values,
- document.ToExecutionContext()))
+ document.GetExecutionContext()))
return nullptr;
}
@@ -328,6 +328,8 @@ Resource* PreloadHelper::PreloadIfNeeded(
}
const String& integrity_attr = params.integrity;
+ // A corresponding check for the preload-scanner code path is in
+ // TokenPreloadScanner::StartTagScanner::CreatePreloadRequest().
// TODO(crbug.com/981419): Honor the integrity attribute value for all
// supported preload destinations, not just the destinations that support SRI
// in the first place.
@@ -338,7 +340,7 @@ Resource* PreloadHelper::PreloadIfNeeded(
SubresourceIntegrity::ParseIntegrityAttribute(
integrity_attr,
SubresourceIntegrityHelper::GetFeatures(
- document.ToExecutionContext()),
+ document.GetExecutionContext()),
metadata_set);
link_fetch_params.SetIntegrityMetadata(metadata_set);
link_fetch_params.MutableResourceRequest().SetFetchIntegrity(
@@ -393,9 +395,9 @@ void PreloadHelper::ModulePreloadIfNeeded(
// settings object." [spec text]
// |document| is the node document here, and its context document is the
// relevant settings object.
- Document* context_document = document.ContextDocument();
+ LocalDOMWindow* window = To<LocalDOMWindow>(document.GetExecutionContext());
Modulator* modulator =
- Modulator::From(ToScriptStateForMainWorld(context_document->GetFrame()));
+ Modulator::From(ToScriptStateForMainWorld(window->GetFrame()));
DCHECK(modulator);
if (!modulator)
return;
@@ -444,7 +446,7 @@ void PreloadHelper::ModulePreloadIfNeeded(
MediaValues* media_values =
CreateMediaValues(document, viewport_description);
if (!MediaMatches(params.media, media_values,
- document.ToExecutionContext()))
+ document.GetExecutionContext()))
return;
}
@@ -462,11 +464,11 @@ void PreloadHelper::ModulePreloadIfNeeded(
IntegrityMetadataSet integrity_metadata;
if (!params.integrity.IsEmpty()) {
SubresourceIntegrity::IntegrityFeatures integrity_features =
- SubresourceIntegrityHelper::GetFeatures(document.ToExecutionContext());
+ SubresourceIntegrityHelper::GetFeatures(document.GetExecutionContext());
SubresourceIntegrity::ReportInfo report_info;
SubresourceIntegrity::ParseIntegrityAttribute(
params.integrity, integrity_features, integrity_metadata, &report_info);
- SubresourceIntegrityHelper::DoReport(*document.ToExecutionContext(),
+ SubresourceIntegrityHelper::DoReport(*document.GetExecutionContext(),
report_info);
}
@@ -490,7 +492,7 @@ void PreloadHelper::ModulePreloadIfNeeded(
// destination, options, settings object, "client", and with the top-level
// module fetch flag set. Wait until algorithm asynchronously completes with
// result." [spec text]
- modulator->FetchSingle(request, context_document->Fetcher(),
+ modulator->FetchSingle(request, window->Fetcher(),
ModuleGraphLevel::kDependentModuleFetch,
ModuleScriptCustomFetchType::kNone, client);
@@ -515,17 +517,14 @@ Resource* PreloadHelper::PrefetchIfNeeded(const LinkLoadParameters& params,
ResourceRequest resource_request(params.href);
- if (base::FeatureList::IsEnabled(
- network::features::kPrefetchMainResourceNetworkIsolationKey)) {
- if (EqualIgnoringASCIICase(params.as, "document"))
- resource_request.SetPrefetchMaybeForTopLevelNavigation(true);
+ if (EqualIgnoringASCIICase(params.as, "document"))
+ resource_request.SetPrefetchMaybeForTopLevelNavigation(true);
- // If this request was originally a preload header on a prefetch response,
- // it may have a recursive prefetch token, used by the browser process to
- // ensure this request is cached correctly.
- resource_request.SetRecursivePrefetchToken(
- params.recursive_prefetch_token);
- }
+ // This request could have originally been a preload header on a prefetch
+ // response, that was promoted to a prefetch request by LoadLinksFromHeader.
+ // In that case, it may have a recursive prefetch token used by the browser
+ // process to ensure this request is cached correctly. Propagate it.
+ resource_request.SetRecursivePrefetchToken(params.recursive_prefetch_token);
resource_request.SetReferrerPolicy(params.referrer_policy);
resource_request.SetFetchImportanceMode(
diff --git a/chromium/third_party/blink/renderer/core/loader/previews_resource_loading_hints_test.cc b/chromium/third_party/blink/renderer/core/loader/previews_resource_loading_hints_test.cc
index 87db913bd4b..fff74cd93db 100644
--- a/chromium/third_party/blink/renderer/core/loader/previews_resource_loading_hints_test.cc
+++ b/chromium/third_party/blink/renderer/core/loader/previews_resource_loading_hints_test.cc
@@ -13,6 +13,7 @@
#include "services/metrics/public/cpp/ukm_recorder.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/features.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/loader/frame_loader.h"
#include "third_party/blink/renderer/core/testing/dummy_page_holder.h"
@@ -42,7 +43,7 @@ TEST_F(PreviewsResourceLoadingHintsTest, NoPatterns) {
Vector<WTF::String> subresources_to_block;
PreviewsResourceLoadingHints* hints = PreviewsResourceLoadingHints::Create(
- *dummy_page_holder_->GetDocument().ToExecutionContext(),
+ *dummy_page_holder_->GetFrame().DomWindow(),
ukm::UkmRecorder::GetNewSourceID(), subresources_to_block);
EXPECT_TRUE(hints->AllowLoad(ResourceType::kScript,
KURL("https://www.example.com/"),
@@ -54,7 +55,7 @@ TEST_F(PreviewsResourceLoadingHintsTest, OnePattern) {
subresources_to_block.push_back("foo.jpg");
PreviewsResourceLoadingHints* hints = PreviewsResourceLoadingHints::Create(
- *dummy_page_holder_->GetDocument().ToExecutionContext(),
+ *dummy_page_holder_->GetFrame().DomWindow(),
ukm::UkmRecorder::GetNewSourceID(), subresources_to_block);
const struct {
@@ -117,7 +118,7 @@ TEST_F(PreviewsResourceLoadingHintsTest, MultiplePatterns) {
subresources_to_block.push_back(".example2.com/baz.jpg");
PreviewsResourceLoadingHints* hints = PreviewsResourceLoadingHints::Create(
- *dummy_page_holder_->GetDocument().ToExecutionContext(),
+ *dummy_page_holder_->GetFrame().DomWindow(),
ukm::UkmRecorder::GetNewSourceID(), subresources_to_block);
const struct {
@@ -149,7 +150,7 @@ TEST_F(PreviewsResourceLoadingHintsTest, OnePatternHistogramChecker) {
subresources_to_block.push_back("foo.jpg");
PreviewsResourceLoadingHints* hints = PreviewsResourceLoadingHints::Create(
- *dummy_page_holder_->GetDocument().ToExecutionContext(),
+ *dummy_page_holder_->GetFrame().DomWindow(),
ukm::UkmRecorder::GetNewSourceID(), subresources_to_block);
const struct {
@@ -210,7 +211,7 @@ TEST_F(PreviewsResourceLoadingHintsTest, MultiplePatternUKMChecker) {
subresources_to_block.push_back(".example3.com/very_low_2_and_medium_3.jpg");
PreviewsResourceLoadingHints* hints = PreviewsResourceLoadingHints::Create(
- *dummy_page_holder_->GetDocument().ToExecutionContext(),
+ *dummy_page_holder_->GetFrame().DomWindow(),
ukm::UkmRecorder::GetNewSourceID(), subresources_to_block);
const struct {
@@ -301,7 +302,7 @@ TEST_F(PreviewsResourceLoadingHintsTestBlockImages,
subresources_to_block.push_back("foo.jpg");
PreviewsResourceLoadingHints* hints = PreviewsResourceLoadingHints::Create(
- *dummy_page_holder_->GetDocument().ToExecutionContext(),
+ *dummy_page_holder_->GetFrame().DomWindow(),
ukm::UkmRecorder::GetNewSourceID(), subresources_to_block);
const struct {
@@ -357,7 +358,7 @@ TEST_F(PreviewsResourceLoadingHintsTestAllowCSS,
subresources_to_block.push_back("foo.jpg");
PreviewsResourceLoadingHints* hints = PreviewsResourceLoadingHints::Create(
- *dummy_page_holder_->GetDocument().ToExecutionContext(),
+ *dummy_page_holder_->GetFrame().DomWindow(),
ukm::UkmRecorder::GetNewSourceID(), subresources_to_block);
const struct {
diff --git a/chromium/third_party/blink/renderer/core/loader/private/frame_client_hints_preferences_context.cc b/chromium/third_party/blink/renderer/core/loader/private/frame_client_hints_preferences_context.cc
index a8701e6cb7e..1101c74f839 100644
--- a/chromium/third_party/blink/renderer/core/loader/private/frame_client_hints_preferences_context.cc
+++ b/chromium/third_party/blink/renderer/core/loader/private/frame_client_hints_preferences_context.cc
@@ -27,12 +27,14 @@ static constexpr WebFeature kWebFeatureMapping[] = {
WebFeature::kClientHintsUA,
WebFeature::kClientHintsUAArch,
WebFeature::kClientHintsUAPlatform,
+ WebFeature::kClientHintsUAPlatformVersion,
WebFeature::kClientHintsUAModel,
WebFeature::kClientHintsUAMobile,
WebFeature::kClientHintsUAFullVersion,
};
-static_assert(static_cast<int>(mojom::WebClientHintsType::kMaxValue) + 1 ==
+static_assert(static_cast<int>(network::mojom::WebClientHintsType::kMaxValue) +
+ 1 ==
base::size(kWebFeatureMapping),
"unhandled client hint type");
@@ -43,7 +45,7 @@ FrameClientHintsPreferencesContext::FrameClientHintsPreferencesContext(
: frame_(frame) {}
void FrameClientHintsPreferencesContext::CountClientHints(
- mojom::WebClientHintsType type) {
+ network::mojom::WebClientHintsType type) {
UseCounter::Count(*frame_->GetDocument(),
kWebFeatureMapping[static_cast<int32_t>(type)]);
}
diff --git a/chromium/third_party/blink/renderer/core/loader/private/frame_client_hints_preferences_context.h b/chromium/third_party/blink/renderer/core/loader/private/frame_client_hints_preferences_context.h
index b1d439d660e..432cbb34014 100644
--- a/chromium/third_party/blink/renderer/core/loader/private/frame_client_hints_preferences_context.h
+++ b/chromium/third_party/blink/renderer/core/loader/private/frame_client_hints_preferences_context.h
@@ -19,7 +19,7 @@ class FrameClientHintsPreferencesContext final
public:
explicit FrameClientHintsPreferencesContext(LocalFrame*);
- void CountClientHints(mojom::WebClientHintsType) override;
+ void CountClientHints(network::mojom::WebClientHintsType) override;
void CountPersistentClientHintHeaders() override;
private:
diff --git a/chromium/third_party/blink/renderer/core/loader/private/prerender_handle.cc b/chromium/third_party/blink/renderer/core/loader/private/prerender_handle.cc
index 97fc5fd0bbd..08821a5c267 100644
--- a/chromium/third_party/blink/renderer/core/loader/private/prerender_handle.cc
+++ b/chromium/third_party/blink/renderer/core/loader/private/prerender_handle.cc
@@ -73,10 +73,13 @@ PrerenderHandle* PrerenderHandle::Create(Document& document,
prerender_handle_client;
auto receiver = prerender_handle_client.InitWithNewPipeAndPassReceiver();
- mojo::Remote<mojom::blink::PrerenderHandle> remote_handle;
- prerender_processor->AddPrerender(std::move(attributes),
- std::move(prerender_handle_client),
- remote_handle.BindNewPipeAndPassReceiver());
+ HeapMojoRemote<mojom::blink::PrerenderHandle,
+ HeapMojoWrapperMode::kWithoutContextObserver>
+ remote_handle(document.GetExecutionContext());
+ prerender_processor->AddPrerender(
+ std::move(attributes), std::move(prerender_handle_client),
+ remote_handle.BindNewPipeAndPassReceiver(
+ document.GetTaskRunner(TaskType::kMiscPlatformAPI)));
return MakeGarbageCollected<PrerenderHandle>(PassKey(), document, client, url,
std::move(remote_handle),
@@ -88,18 +91,22 @@ PrerenderHandle::PrerenderHandle(
Document& document,
PrerenderClient* client,
const KURL& url,
- mojo::Remote<mojom::blink::PrerenderHandle> remote_handle,
+ HeapMojoRemote<mojom::blink::PrerenderHandle,
+ HeapMojoWrapperMode::kWithoutContextObserver> remote_handle,
mojo::PendingReceiver<mojom::blink::PrerenderHandleClient> receiver)
- : ExecutionContextLifecycleObserver(&document),
+ : ExecutionContextLifecycleObserver(document.GetExecutionContext()),
url_(url),
client_(client),
remote_handle_(std::move(remote_handle)),
- receiver_(this, std::move(receiver)) {}
+ receiver_(this, document.GetExecutionContext()) {
+ receiver_.Bind(std::move(receiver),
+ document.GetTaskRunner(TaskType::kMiscPlatformAPI));
+}
PrerenderHandle::~PrerenderHandle() = default;
void PrerenderHandle::Dispose() {
- if (remote_handle_)
+ if (remote_handle_.is_bound())
remote_handle_->Abandon();
Detach();
}
@@ -109,7 +116,7 @@ void PrerenderHandle::Cancel() {
// case, the LinkLoader cancels the PrerenderHandle as the Document is
// destroyed, even through the ExecutionContextLifecycleObserver has already
// abandoned it.
- if (remote_handle_)
+ if (remote_handle_.is_bound())
remote_handle_->Cancel();
Detach();
}
@@ -148,6 +155,8 @@ void PrerenderHandle::OnPrerenderStop() {
void PrerenderHandle::Trace(Visitor* visitor) {
visitor->Trace(client_);
+ visitor->Trace(remote_handle_);
+ visitor->Trace(receiver_);
ExecutionContextLifecycleObserver::Trace(visitor);
}
diff --git a/chromium/third_party/blink/renderer/core/loader/private/prerender_handle.h b/chromium/third_party/blink/renderer/core/loader/private/prerender_handle.h
index 18df853e178..0935af059b6 100644
--- a/chromium/third_party/blink/renderer/core/loader/private/prerender_handle.h
+++ b/chromium/third_party/blink/renderer/core/loader/private/prerender_handle.h
@@ -34,10 +34,12 @@
#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "base/util/type_safety/pass_key.h"
-#include "mojo/public/cpp/bindings/remote.h"
#include "third_party/blink/public/mojom/prerender/prerender.mojom-blink.h"
#include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
+#include "third_party/blink/renderer/platform/mojo/heap_mojo_receiver.h"
+#include "third_party/blink/renderer/platform/mojo/heap_mojo_remote.h"
+#include "third_party/blink/renderer/platform/mojo/heap_mojo_wrapper_mode.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
namespace blink {
@@ -62,7 +64,8 @@ class PrerenderHandle final : public GarbageCollected<PrerenderHandle>,
Document&,
PrerenderClient*,
const KURL&,
- mojo::Remote<mojom::blink::PrerenderHandle>,
+ HeapMojoRemote<mojom::blink::PrerenderHandle,
+ HeapMojoWrapperMode::kWithoutContextObserver>,
mojo::PendingReceiver<mojom::blink::PrerenderHandleClient>);
~PrerenderHandle() override;
void Dispose();
@@ -86,8 +89,13 @@ class PrerenderHandle final : public GarbageCollected<PrerenderHandle>,
KURL url_;
WeakMember<PrerenderClient> client_;
- mojo::Remote<mojom::blink::PrerenderHandle> remote_handle_;
- mojo::Receiver<mojom::blink::PrerenderHandleClient> receiver_;
+ HeapMojoRemote<mojom::blink::PrerenderHandle,
+ HeapMojoWrapperMode::kWithoutContextObserver>
+ remote_handle_;
+ HeapMojoReceiver<mojom::blink::PrerenderHandleClient,
+ PrerenderHandle,
+ HeapMojoWrapperMode::kWithoutContextObserver>
+ receiver_;
DISALLOW_COPY_AND_ASSIGN(PrerenderHandle);
};
diff --git a/chromium/third_party/blink/renderer/core/loader/resource/document_resource.cc b/chromium/third_party/blink/renderer/core/loader/resource/document_resource.cc
deleted file mode 100644
index ea05b85bb25..00000000000
--- a/chromium/third_party/blink/renderer/core/loader/resource/document_resource.cc
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- Copyright (C) 2010 Rob Buis <rwlbuis@gmail.com>
- Copyright (C) 2011 Cosmin Truta <ctruta@gmail.com>
- Copyright (C) 2012 University of Szeged
- Copyright (C) 2012 Renata Hodovan <reni@webkit.org>
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public License
- along with this library; see the file COPYING.LIB. If not, write to
- the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA.
-*/
-
-#include "third_party/blink/renderer/core/loader/resource/document_resource.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/renderer/core/dom/document_init.h"
-#include "third_party/blink/renderer/core/dom/xml_document.h"
-#include "third_party/blink/renderer/platform/loader/fetch/fetch_parameters.h"
-#include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h"
-#include "third_party/blink/renderer/platform/loader/fetch/text_resource_decoder_options.h"
-#include "third_party/blink/renderer/platform/wtf/shared_buffer.h"
-#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
-
-namespace blink {
-
-DocumentResource* DocumentResource::FetchSVGDocument(
- FetchParameters& params,
- const Document& context_document,
- ResourceClient* client) {
- DCHECK_EQ(params.GetResourceRequest().GetMode(),
- network::mojom::RequestMode::kSameOrigin);
- params.SetRequestContext(mojom::RequestContextType::IMAGE);
- params.SetRequestDestination(network::mojom::RequestDestination::kImage);
- auto* resource =
- To<DocumentResource>(context_document.Fetcher()->RequestResource(
- params, SVGDocumentResourceFactory(), client));
- if (!resource->document_ && !resource->context_document_)
- resource->context_document_ = const_cast<Document*>(&context_document);
- return resource;
-}
-
-DocumentResource::DocumentResource(
- const ResourceRequest& request,
- ResourceType type,
- const ResourceLoaderOptions& options,
- const TextResourceDecoderOptions& decoder_options)
- : TextResource(request, type, options, decoder_options) {
- // FIXME: We'll support more types to support HTMLImports.
- DCHECK_EQ(type, ResourceType::kSVGDocument);
-}
-
-DocumentResource::~DocumentResource() = default;
-
-void DocumentResource::Trace(Visitor* visitor) {
- visitor->Trace(document_);
- visitor->Trace(context_document_);
- Resource::Trace(visitor);
-}
-
-void DocumentResource::NotifyFinished() {
- if (Data() && MimeTypeAllowed()) {
- // We don't need to create a new frame because the new document belongs to
- // the parent UseElement.
- document_ = CreateDocument(GetResponse().CurrentRequestUrl());
- document_->SetContent(DecodedText());
- }
- Resource::NotifyFinished();
-}
-
-bool DocumentResource::MimeTypeAllowed() const {
- DCHECK_EQ(GetType(), ResourceType::kSVGDocument);
- AtomicString mime_type = GetResponse().MimeType();
- if (GetResponse().IsHTTP())
- mime_type = HttpContentType();
- return mime_type == "image/svg+xml" || mime_type == "text/xml" ||
- mime_type == "application/xml" || mime_type == "application/xhtml+xml";
-}
-
-Document* DocumentResource::CreateDocument(const KURL& url) {
- switch (GetType()) {
- case ResourceType::kSVGDocument:
- return XMLDocument::CreateSVG(
- DocumentInit::Create().WithURL(url).WithContextDocument(
- context_document_));
- default:
- // FIXME: We'll add more types to support HTMLImports.
- NOTREACHED();
- return nullptr;
- }
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/loader/resource/document_resource.h b/chromium/third_party/blink/renderer/core/loader/resource/document_resource.h
deleted file mode 100644
index a468525c68f..00000000000
--- a/chromium/third_party/blink/renderer/core/loader/resource/document_resource.h
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- Copyright (C) 2010 Rob Buis <rwlbuis@gmail.com>
- Copyright (C) 2011 Cosmin Truta <ctruta@gmail.com>
- Copyright (C) 2012 University of Szeged
- Copyright (C) 2012 Renata Hodovan <reni@webkit.org>
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public License
- along with this library; see the file COPYING.LIB. If not, write to
- the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA.
-*/
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_RESOURCE_DOCUMENT_RESOURCE_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_RESOURCE_DOCUMENT_RESOURCE_H_
-
-#include <memory>
-#include "third_party/blink/renderer/core/loader/resource/text_resource.h"
-#include "third_party/blink/renderer/platform/heap/handle.h"
-#include "third_party/blink/renderer/platform/loader/fetch/resource.h"
-#include "third_party/blink/renderer/platform/loader/fetch/resource_client.h"
-#include "third_party/blink/renderer/platform/loader/fetch/text_resource_decoder_options.h"
-#include "third_party/blink/renderer/platform/wtf/casting.h"
-
-namespace blink {
-
-class Document;
-class FetchParameters;
-
-class CORE_EXPORT DocumentResource final : public TextResource {
- public:
- static DocumentResource* FetchSVGDocument(FetchParameters&,
- const Document& context_document,
- ResourceClient*);
-
- DocumentResource(const ResourceRequest&,
- ResourceType,
- const ResourceLoaderOptions&,
- const TextResourceDecoderOptions&);
- ~DocumentResource() override;
- void Trace(Visitor*) override;
-
- Document* GetDocument() const { return document_.Get(); }
-
- void NotifyFinished() override;
-
- private:
- class SVGDocumentResourceFactory : public ResourceFactory {
- public:
- SVGDocumentResourceFactory()
- : ResourceFactory(ResourceType::kSVGDocument,
- TextResourceDecoderOptions::kXMLContent) {}
-
- Resource* Create(
- const ResourceRequest& request,
- const ResourceLoaderOptions& options,
- const TextResourceDecoderOptions& decoder_options) const override {
- return MakeGarbageCollected<DocumentResource>(
- request, ResourceType::kSVGDocument, options, decoder_options);
- }
- };
-
- bool MimeTypeAllowed() const;
- Document* CreateDocument(const KURL&);
-
- Member<Document> document_;
- WeakMember<Document> context_document_;
-};
-
-template <>
-struct DowncastTraits<DocumentResource> {
- static bool AllowFrom(const Resource& resource) {
- return resource.GetType() == ResourceType::kSVGDocument;
- }
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_RESOURCE_DOCUMENT_RESOURCE_H_
diff --git a/chromium/third_party/blink/renderer/core/loader/resource/font_resource.cc b/chromium/third_party/blink/renderer/core/loader/resource/font_resource.cc
index 794161c5fa6..53320e7669b 100644
--- a/chromium/third_party/blink/renderer/core/loader/resource/font_resource.cc
+++ b/chromium/third_party/blink/renderer/core/loader/resource/font_resource.cc
@@ -119,6 +119,8 @@ scoped_refptr<FontCustomPlatformData> FontResource::GetCustomFontData() {
if (!font_data_)
SetStatus(ResourceStatus::kDecodeError);
+ else
+ ClearData();
}
return font_data_;
}
@@ -173,11 +175,6 @@ void FontResource::NotifyClientsLongLimitExceeded() {
client->FontLoadLongLimitExceeded(this);
}
-void FontResource::AllClientsAndObserversRemoved() {
- font_data_ = nullptr;
- Resource::AllClientsAndObserversRemoved();
-}
-
void FontResource::NotifyFinished() {
font_load_short_limit_.Cancel();
font_load_long_limit_.Cancel();
diff --git a/chromium/third_party/blink/renderer/core/loader/resource/font_resource.h b/chromium/third_party/blink/renderer/core/loader/resource/font_resource.h
index d31b28d8ba3..713dc38d4c0 100644
--- a/chromium/third_party/blink/renderer/core/loader/resource/font_resource.h
+++ b/chromium/third_party/blink/renderer/core/loader/resource/font_resource.h
@@ -55,7 +55,6 @@ class CORE_EXPORT FontResource final : public Resource {
void SetRevalidatingRequest(const ResourceRequestHead&) override;
- void AllClientsAndObserversRemoved() override;
void StartLoadLimitTimersIfNecessary(base::SingleThreadTaskRunner*);
String OtsParsingMessage() const { return ots_parsing_message_; }
@@ -134,4 +133,4 @@ class FontResourceClient : public ResourceClient {
} // namespace blink
-#endif
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_RESOURCE_FONT_RESOURCE_H_
diff --git a/chromium/third_party/blink/renderer/core/loader/resource/font_resource_test.cc b/chromium/third_party/blink/renderer/core/loader/resource/font_resource_test.cc
index d67532f2701..6488a0d7046 100644
--- a/chromium/third_party/blink/renderer/core/loader/resource/font_resource_test.cc
+++ b/chromium/third_party/blink/renderer/core/loader/resource/font_resource_test.cc
@@ -130,7 +130,8 @@ TEST_F(CacheAwareFontResourceTest, CacheAwareFontLoading) {
CSSFontFaceSrcValue* src_value = CSSFontFaceSrcValue::Create(
url.GetString(), url.GetString(),
Referrer(document.Url(), document.GetReferrerPolicy()),
- network::mojom::CSPDisposition::DO_NOT_CHECK, OriginClean::kTrue);
+ network::mojom::CSPDisposition::DO_NOT_CHECK, OriginClean::kTrue,
+ false /* is_ad_related */);
// Route font requests in this test through CSSFontFaceSrcValue::Fetch
// instead of calling FontResource::Fetch directly. CSSFontFaceSrcValue
@@ -141,7 +142,7 @@ TEST_F(CacheAwareFontResourceTest, CacheAwareFontLoading) {
Persistent<MockFontResourceClient> client =
MakeGarbageCollected<MockFontResourceClient>();
FontResource& resource =
- src_value->Fetch(document.ToExecutionContext(), client);
+ src_value->Fetch(document.GetExecutionContext(), client);
fetcher->StartLoad(&resource);
EXPECT_TRUE(resource.Loader()->IsCacheAwareLoadingActivated());
@@ -164,7 +165,7 @@ TEST_F(CacheAwareFontResourceTest, CacheAwareFontLoading) {
Persistent<MockFontResourceClient> client2 =
MakeGarbageCollected<MockFontResourceClient>();
FontResource& resource2 =
- src_value->Fetch(document.ToExecutionContext(), client2);
+ src_value->Fetch(document.GetExecutionContext(), client2);
EXPECT_EQ(&resource, &resource2);
EXPECT_TRUE(client2->FontLoadShortLimitExceededCalled());
EXPECT_FALSE(client2->FontLoadLongLimitExceededCalled());
@@ -177,7 +178,7 @@ TEST_F(CacheAwareFontResourceTest, CacheAwareFontLoading) {
Persistent<MockFontResourceClient> client3 =
MakeGarbageCollected<MockFontResourceClient>();
FontResource& resource3 =
- src_value->Fetch(document.ToExecutionContext(), client3);
+ src_value->Fetch(document.GetExecutionContext(), client3);
EXPECT_EQ(&resource, &resource3);
EXPECT_TRUE(client3->FontLoadShortLimitExceededCalled());
EXPECT_TRUE(client3->FontLoadLongLimitExceededCalled());
diff --git a/chromium/third_party/blink/renderer/core/loader/resource/image_resource.cc b/chromium/third_party/blink/renderer/core/loader/resource/image_resource.cc
index eefacdf9ba1..96def6caf44 100644
--- a/chromium/third_party/blink/renderer/core/loader/resource/image_resource.cc
+++ b/chromium/third_party/blink/renderer/core/loader/resource/image_resource.cc
@@ -88,25 +88,12 @@ class ImageResource::ImageResourceInfoImpl final
base::TimeTicks LoadResponseEnd() const override {
return resource_->LoadResponseEnd();
}
- bool IsSchedulingReload() const override {
- return resource_->is_scheduling_reload_;
- }
const ResourceResponse& GetResponse() const override {
return resource_->GetResponse();
}
- bool ShouldShowPlaceholder() const override {
- return resource_->ShouldShowPlaceholder();
- }
- bool ShouldShowLazyImagePlaceholder() const override {
- return resource_->ShouldShowLazyImagePlaceholder();
- }
bool IsCacheValidator() const override {
return resource_->IsCacheValidator();
}
- bool SchedulingReloadOrShouldReloadBrokenPlaceholder() const override {
- return resource_->is_scheduling_reload_ ||
- resource_->ShouldReloadBrokenPlaceholder();
- }
bool IsAccessAllowed(
DoesCurrentFrameHaveSingleSecurityOrigin
does_current_frame_has_single_security_origin) const override {
@@ -157,21 +144,14 @@ class ImageResource::ImageResourceFactory : public NonTextResourceFactory {
STACK_ALLOCATED();
public:
- explicit ImageResourceFactory(const FetchParameters& fetch_params)
- : NonTextResourceFactory(ResourceType::kImage),
- fetch_params_(&fetch_params) {}
+ explicit ImageResourceFactory()
+ : NonTextResourceFactory(ResourceType::kImage) {}
Resource* Create(const ResourceRequest& request,
const ResourceLoaderOptions& options) const override {
return MakeGarbageCollected<ImageResource>(
- request, options, ImageResourceContent::CreateNotStarted(),
- fetch_params_->GetImageRequestOptimization() ==
- FetchParameters::kAllowPlaceholder);
+ request, options, ImageResourceContent::CreateNotStarted());
}
-
- private:
- // Weak, unowned pointer. Must outlive |this|.
- const FetchParameters* fetch_params_;
};
ImageResource* ImageResource::Fetch(FetchParameters& params,
@@ -183,7 +163,7 @@ ImageResource* ImageResource::Fetch(FetchParameters& params,
}
ImageResource* resource = ToImageResource(
- fetcher->RequestResource(params, ImageResourceFactory(params), nullptr));
+ fetcher->RequestResource(params, ImageResourceFactory(), nullptr));
// If the fetch originated from user agent CSS we should mark it as a user
// agent resource.
@@ -193,19 +173,6 @@ ImageResource* ImageResource::Fetch(FetchParameters& params,
return resource;
}
-Resource::MatchStatus ImageResource::CanReuse(
- const FetchParameters& params) const {
- // If the image is a placeholder, but this fetch doesn't allow a
- // placeholder, then do not reuse this resource.
- if (params.GetImageRequestOptimization() !=
- FetchParameters::kAllowPlaceholder &&
- placeholder_option_ != PlaceholderOption::kDoNotReloadPlaceholder) {
- return MatchStatus::kImagePlaceholder;
- }
-
- return Resource::CanReuse(params);
-}
-
bool ImageResource::CanUseCacheValidator() const {
// Disable revalidation while ImageResourceContent is still waiting for
// SVG load completion.
@@ -219,7 +186,7 @@ bool ImageResource::CanUseCacheValidator() const {
ImageResource* ImageResource::Create(const ResourceRequest& request) {
ResourceLoaderOptions options;
return MakeGarbageCollected<ImageResource>(
- request, options, ImageResourceContent::CreateNotStarted(), false);
+ request, options, ImageResourceContent::CreateNotStarted());
}
ImageResource* ImageResource::CreateForTest(const KURL& url) {
@@ -237,14 +204,9 @@ ImageResource* ImageResource::CreateForTest(const KURL& url) {
ImageResource::ImageResource(const ResourceRequest& resource_request,
const ResourceLoaderOptions& options,
- ImageResourceContent* content,
- bool is_placeholder)
+ ImageResourceContent* content)
: Resource(resource_request, ResourceType::kImage, options),
- content_(content),
- is_scheduling_reload_(false),
- placeholder_option_(
- is_placeholder ? PlaceholderOption::kShowAndReloadPlaceholderAlways
- : PlaceholderOption::kDoNotReloadPlaceholder) {
+ content_(content) {
DCHECK(GetContent());
RESOURCE_LOADING_DVLOG(1)
<< "MakeGarbageCollected<ImageResource>(ResourceRequest) " << this;
@@ -275,15 +237,6 @@ void ImageResource::Trace(Visitor* visitor) {
MultipartImageResourceParser::Client::Trace(visitor);
}
-void ImageResource::NotifyFinished() {
- // Don't notify clients of completion if this ImageResource is
- // about to be reloaded.
- if (is_scheduling_reload_ || ShouldReloadBrokenPlaceholder())
- return;
-
- Resource::NotifyFinished();
-}
-
bool ImageResource::HasClientsOrObservers() const {
return Resource::HasClientsOrObservers() || GetContent()->HasObservers();
}
@@ -292,11 +245,6 @@ void ImageResource::DidAddClient(ResourceClient* client) {
DCHECK((multipart_parser_ && IsLoading()) || !Data() ||
GetContent()->HasImage());
- // Don't notify observers and clients of completion if this ImageResource is
- // about to be reloaded.
- if (is_scheduling_reload_ || ShouldReloadBrokenPlaceholder())
- return;
-
Resource::DidAddClient(client);
}
@@ -465,22 +413,6 @@ void ImageResource::FinishAsError(const ResourceError& error,
true);
}
-// Determines if |response| likely contains the entire resource for the purposes
-// of determining whether or not to show a placeholder, e.g. if the server
-// responded with a full 200 response or if the full image is smaller than the
-// requested range.
-static bool IsEntireResource(const ResourceResponse& response) {
- if (response.HttpStatusCode() != 206)
- return true;
-
- int64_t first_byte_position = -1, last_byte_position = -1,
- instance_length = -1;
- return ParseContentRangeHeaderFor206(
- response.HttpHeaderField("Content-Range"), &first_byte_position,
- &last_byte_position, &instance_length) &&
- first_byte_position == 0 && last_byte_position + 1 == instance_length;
-}
-
void ImageResource::ResponseReceived(const ResourceResponse& response) {
DCHECK(!multipart_parser_);
if (response.MimeType() == "multipart/x-mixed-replace") {
@@ -499,108 +431,6 @@ void ImageResource::ResponseReceived(const ResourceResponse& response) {
// (e.g. a 304) with a partial set of updated headers that were folded into
// the cached response.
Resource::ResponseReceived(response);
-
- if (placeholder_option_ ==
- PlaceholderOption::kShowAndReloadPlaceholderAlways &&
- IsEntireResource(GetResponse())) {
- if (GetResponse().HttpStatusCode() < 400 ||
- GetResponse().HttpStatusCode() >= 600) {
- // Don't treat a complete and broken image as a placeholder if the
- // response code is something other than a 4xx or 5xx error.
- // This is done to prevent reissuing the request in cases like
- // "204 No Content" responses to tracking requests triggered by <img>
- // tags, and <img> tags used to preload non-image resources.
- placeholder_option_ = PlaceholderOption::kDoNotReloadPlaceholder;
- } else {
- placeholder_option_ = PlaceholderOption::kReloadPlaceholderOnDecodeError;
- }
- }
-}
-
-bool ImageResource::ShouldShowPlaceholder() const {
- switch (placeholder_option_) {
- case PlaceholderOption::kShowAndReloadPlaceholderAlways:
- case PlaceholderOption::kShowAndDoNotReloadPlaceholder:
- return true;
- case PlaceholderOption::kReloadPlaceholderOnDecodeError:
- case PlaceholderOption::kDoNotReloadPlaceholder:
- return false;
- }
- NOTREACHED();
- return false;
-}
-
-bool ImageResource::ShouldShowLazyImagePlaceholder() const {
- switch (placeholder_option_) {
- case PlaceholderOption::kShowAndReloadPlaceholderAlways:
- case PlaceholderOption::kShowAndDoNotReloadPlaceholder:
- return RuntimeEnabledFeatures::LazyImageLoadingEnabled() &&
- (GetResourceRequest().GetPreviewsState() &
- WebURLRequest::kLazyImageLoadDeferred);
- case PlaceholderOption::kReloadPlaceholderOnDecodeError:
- case PlaceholderOption::kDoNotReloadPlaceholder:
- return false;
- }
- NOTREACHED();
- return false;
-}
-
-bool ImageResource::ShouldReloadBrokenPlaceholder() const {
- switch (placeholder_option_) {
- case PlaceholderOption::kShowAndReloadPlaceholderAlways:
- return ErrorOccurred();
- case PlaceholderOption::kReloadPlaceholderOnDecodeError:
- return GetStatus() == ResourceStatus::kDecodeError;
- case PlaceholderOption::kShowAndDoNotReloadPlaceholder:
- case PlaceholderOption::kDoNotReloadPlaceholder:
- return false;
- }
- NOTREACHED();
- return false;
-}
-
-void ImageResource::ReloadIfLoFiOrPlaceholderImage(
- ResourceFetcher* fetcher,
- ReloadLoFiOrPlaceholderPolicy policy) {
- if (policy == kReloadIfNeeded && !ShouldReloadBrokenPlaceholder())
- return;
-
- // Prevent clients and observers from being notified of completion while the
- // reload is being scheduled, so that e.g. canceling an existing load in
- // progress doesn't cause clients and observers to be notified of completion
- // prematurely.
- DCHECK(!is_scheduling_reload_);
- is_scheduling_reload_ = true;
-
- // The reloaded image should not use any previews transformations.
- WebURLRequest::PreviewsState previews_state_for_reload =
- WebURLRequest::kPreviewsNoTransform;
-
- SetPreviewsState(previews_state_for_reload);
-
- if (placeholder_option_ != PlaceholderOption::kDoNotReloadPlaceholder) {
- ClearRangeRequestHeader();
- placeholder_option_ = PlaceholderOption::kDoNotReloadPlaceholder;
- }
-
- if (IsLoading()) {
- Loader()->Cancel();
- // Canceling the loader causes error() to be called, which in turn calls
- // clear() and notifyObservers(), so there's no need to call these again
- // here.
- } else {
- ClearData();
- SetEncodedSize(0);
- UpdateImage(nullptr, ImageResourceContent::kClearImageAndNotifyObservers,
- false);
- }
-
- SetStatus(ResourceStatus::kNotStarted);
-
- DCHECK(is_scheduling_reload_);
- is_scheduling_reload_ = false;
-
- fetcher->StartLoad(this);
}
void ImageResource::OnePartInMultipartReceived(
diff --git a/chromium/third_party/blink/renderer/core/loader/resource/image_resource.h b/chromium/third_party/blink/renderer/core/loader/resource/image_resource.h
index 129be3d3b19..557800e494d 100644
--- a/chromium/third_party/blink/renderer/core/loader/resource/image_resource.h
+++ b/chromium/third_party/blink/renderer/core/loader/resource/image_resource.h
@@ -65,23 +65,18 @@ class CORE_EXPORT ImageResource final
ImageResource(const ResourceRequest&,
const ResourceLoaderOptions&,
- ImageResourceContent*,
- bool is_placeholder);
+ ImageResourceContent*);
~ImageResource() override;
ImageResourceContent* GetContent();
const ImageResourceContent* GetContent() const;
- void ReloadIfLoFiOrPlaceholderImage(ResourceFetcher*,
- ReloadLoFiOrPlaceholderPolicy) override;
-
void DidAddClient(ResourceClient*) override;
ResourcePriority PriorityFromObservers() override;
void AllClientsAndObserversRemoved() override;
- MatchStatus CanReuse(const FetchParameters&) const override;
bool CanUseCacheValidator() const override;
scoped_refptr<const SharedBuffer> ResourceBuffer() const override;
@@ -100,9 +95,6 @@ class CORE_EXPORT ImageResource final
void OnePartInMultipartReceived(const ResourceResponse&) final;
void MultipartDataReceived(const char*, size_t) final;
- bool ShouldShowPlaceholder() const;
- bool ShouldShowLazyImagePlaceholder() const;
-
// If the ImageResource came from a user agent CSS stylesheet then we should
// flag it so that it can persist beyond navigation.
void FlagAsUserAgentResource();
@@ -134,44 +126,17 @@ class CORE_EXPORT ImageResource final
ImageResourceContent::UpdateImageOption,
bool all_data_received);
- void NotifyFinished() override;
-
void DestroyDecodedDataIfPossible() override;
void DestroyDecodedDataForFailedRevalidation() override;
void FlushImageIfNeeded();
- bool ShouldReloadBrokenPlaceholder() const;
-
Member<ImageResourceContent> content_;
Member<MultipartImageResourceParser> multipart_parser_;
MultipartParsingState multipart_parsing_state_ =
MultipartParsingState::kWaitingForFirstPart;
- // Indicates if the ImageResource is currently scheduling a reload, e.g.
- // because reloadIfLoFi() was called.
- bool is_scheduling_reload_;
-
- // Indicates if this ImageResource is either attempting to load a placeholder
- // image, or is a (possibly broken) placeholder image.
- enum class PlaceholderOption {
- // Do not show or reload placeholder.
- kDoNotReloadPlaceholder,
-
- // Show placeholder, and do not reload. The original image will still be
- // loaded and shown if the image is explicitly reloaded, e.g. when
- // ReloadIfLoFiOrPlaceholderImage is called with kReloadAlways.
- kShowAndDoNotReloadPlaceholder,
-
- // Do not show placeholder, reload only when decode error occurs.
- kReloadPlaceholderOnDecodeError,
-
- // Show placeholder and reload.
- kShowAndReloadPlaceholderAlways,
- };
- PlaceholderOption placeholder_option_;
-
base::TimeTicks last_flush_time_;
bool is_during_finish_as_error_ = false;
diff --git a/chromium/third_party/blink/renderer/core/loader/resource/image_resource_content.cc b/chromium/third_party/blink/renderer/core/loader/resource/image_resource_content.cc
index 854baaa5e41..3f5e21f8f29 100644
--- a/chromium/third_party/blink/renderer/core/loader/resource/image_resource_content.cc
+++ b/chromium/third_party/blink/renderer/core/loader/resource/image_resource_content.cc
@@ -16,7 +16,6 @@
#include "third_party/blink/renderer/core/svg/graphics/svg_image.h"
#include "third_party/blink/renderer/platform/geometry/int_size.h"
#include "third_party/blink/renderer/platform/graphics/bitmap_image.h"
-#include "third_party/blink/renderer/platform/graphics/placeholder_image.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
#include "third_party/blink/renderer/platform/network/http_parsers.h"
#include "third_party/blink/renderer/platform/network/mime/mime_type_registry.h"
@@ -42,14 +41,8 @@ class NullImageResourceInfo final
private:
const KURL& Url() const override { return url_; }
base::TimeTicks LoadResponseEnd() const override { return base::TimeTicks(); }
- bool IsSchedulingReload() const override { return false; }
const ResourceResponse& GetResponse() const override { return response_; }
- bool ShouldShowPlaceholder() const override { return false; }
- bool ShouldShowLazyImagePlaceholder() const override { return false; }
bool IsCacheValidator() const override { return false; }
- bool SchedulingReloadOrShouldReloadBrokenPlaceholder() const override {
- return false;
- }
bool IsAccessAllowed(
DoesCurrentFrameHaveSingleSecurityOrigin) const override {
return true;
@@ -75,31 +68,6 @@ class NullImageResourceInfo final
const ResourceResponse response_;
};
-int64_t EstimateOriginalImageSizeForPlaceholder(
- const ResourceResponse& response) {
- if (response.HttpHeaderField("chrome-proxy-content-transform") ==
- "empty-image") {
- const String& str = response.HttpHeaderField("chrome-proxy");
- wtf_size_t index = str.Find("ofcl=");
- if (index != kNotFound) {
- bool ok = false;
- int bytes = str.Substring(index + (sizeof("ofcl=") - 1)).ToInt(&ok);
- if (ok && bytes >= 0)
- return bytes;
- }
- }
-
- int64_t first = -1, last = -1, length = -1;
- if (response.HttpStatusCode() == 206 &&
- ParseContentRangeHeaderFor206(response.HttpHeaderField("content-range"),
- &first, &last, &length) &&
- length >= 0) {
- return length;
- }
-
- return response.EncodedBodyLength();
-}
-
} // namespace
ImageResourceContent::ImageResourceContent(scoped_refptr<blink::Image> image)
@@ -121,14 +89,6 @@ ImageResourceContent* ImageResourceContent::CreateLoaded(
return content;
}
-ImageResourceContent* ImageResourceContent::CreateLazyImagePlaceholder() {
- ImageResourceContent* content = MakeGarbageCollected<ImageResourceContent>();
- content->content_status_ = ResourceStatus::kCached;
- content->image_ =
- PlaceholderImage::CreateForLazyImages(content, IntSize(1, 1));
- return content;
-}
-
ImageResourceContent* ImageResourceContent::Fetch(FetchParameters& params,
ResourceFetcher* fetcher) {
// TODO(hiroshige): Remove direct references to ImageResource by making
@@ -150,8 +110,6 @@ void ImageResourceContent::Trace(Visitor* visitor) {
void ImageResourceContent::HandleObserverFinished(
ImageResourceObserver* observer) {
- if (info_->SchedulingReloadOrShouldReloadBrokenPlaceholder())
- return;
{
ProhibitAddRemoveObserverInScope prohibit_add_remove_observer_in_scope(
this);
@@ -449,22 +407,6 @@ ImageResourceContent::UpdateImageResult ImageResourceContent::UpdateImage(
if (size_available_ == Image::kSizeUnavailable && !all_data_received)
return UpdateImageResult::kNoDecodeError;
- if ((info_->ShouldShowPlaceholder() ||
- info_->ShouldShowLazyImagePlaceholder()) &&
- all_data_received) {
- if (image_ && !image_->IsNull()) {
- IntSize dimensions = image_->Size();
- ClearImage();
- if (info_->ShouldShowLazyImagePlaceholder()) {
- image_ = PlaceholderImage::CreateForLazyImages(this, dimensions);
- } else {
- image_ = PlaceholderImage::Create(
- this, dimensions,
- EstimateOriginalImageSizeForPlaceholder(info_->GetResponse()));
- }
- }
- }
-
// As per spec, zero intrinsic size SVG is a valid image so do not
// consider such an image as DecodeError.
// https://www.w3.org/TR/SVG/struct.html#SVGElementWidthAttribute
diff --git a/chromium/third_party/blink/renderer/core/loader/resource/image_resource_content.h b/chromium/third_party/blink/renderer/core/loader/resource/image_resource_content.h
index 9e9fe6c6d22..72db3c60520 100644
--- a/chromium/third_party/blink/renderer/core/loader/resource/image_resource_content.h
+++ b/chromium/third_party/blink/renderer/core/loader/resource/image_resource_content.h
@@ -56,8 +56,6 @@ class CORE_EXPORT ImageResourceContent final
// Creates ImageResourceContent from an already loaded image.
static ImageResourceContent* CreateLoaded(scoped_refptr<blink::Image>);
- static ImageResourceContent* CreateLazyImagePlaceholder();
-
static ImageResourceContent* Fetch(FetchParameters&, ResourceFetcher*);
explicit ImageResourceContent(scoped_refptr<blink::Image> = nullptr);
diff --git a/chromium/third_party/blink/renderer/core/loader/resource/image_resource_info.h b/chromium/third_party/blink/renderer/core/loader/resource/image_resource_info.h
index f459616c35e..b3a105a6b7c 100644
--- a/chromium/third_party/blink/renderer/core/loader/resource/image_resource_info.h
+++ b/chromium/third_party/blink/renderer/core/loader/resource/image_resource_info.h
@@ -30,12 +30,8 @@ class CORE_EXPORT ImageResourceInfo : public GarbageCollectedMixin {
~ImageResourceInfo() = default;
virtual const KURL& Url() const = 0;
virtual base::TimeTicks LoadResponseEnd() const = 0;
- virtual bool IsSchedulingReload() const = 0;
virtual const ResourceResponse& GetResponse() const = 0;
- virtual bool ShouldShowPlaceholder() const = 0;
- virtual bool ShouldShowLazyImagePlaceholder() const = 0;
virtual bool IsCacheValidator() const = 0;
- virtual bool SchedulingReloadOrShouldReloadBrokenPlaceholder() const = 0;
enum DoesCurrentFrameHaveSingleSecurityOrigin {
kHasMultipleSecurityOrigin,
kHasSingleSecurityOrigin
diff --git a/chromium/third_party/blink/renderer/core/loader/resource/image_resource_test.cc b/chromium/third_party/blink/renderer/core/loader/resource/image_resource_test.cc
index 5abd3cc3903..a960dd7d1d6 100644
--- a/chromium/third_party/blink/renderer/core/loader/resource/image_resource_test.cc
+++ b/chromium/third_party/blink/renderer/core/loader/resource/image_resource_test.cc
@@ -202,164 +202,11 @@ void ReceiveResponse(ImageResource* image_resource,
image_resource->FinishForTest();
}
-void TestThatReloadIsStartedThenServeReload(
- const KURL& test_url,
- ImageResource* image_resource,
- ImageResourceContent* content,
- MockImageResourceObserver* observer,
- bool placeholder_before_reload) {
- const char* data = reinterpret_cast<const char*>(kJpegImage2);
- constexpr size_t kDataLength = sizeof(kJpegImage2);
- constexpr int kImageWidth = 50;
- constexpr int kImageHeight = 50;
-
- // Checks that |imageResource| and |content| are ready for non-placeholder
- // reloading.
- EXPECT_EQ(ResourceStatus::kPending, image_resource->GetStatus());
- EXPECT_FALSE(image_resource->ResourceBuffer());
- EXPECT_EQ(placeholder_before_reload, image_resource->ShouldShowPlaceholder());
- EXPECT_EQ(g_null_atom,
- image_resource->GetResourceRequest().HttpHeaderField("range"));
- EXPECT_EQ(content, image_resource->GetContent());
- EXPECT_FALSE(content->HasImage());
-
- // Checks |observer| before reloading.
- const int original_image_changed_count = observer->ImageChangedCount();
- const bool already_notified_finish = observer->ImageNotifyFinishedCalled();
- const int image_width_on_image_notify_finished =
- observer->ImageWidthOnImageNotifyFinished();
- ASSERT_NE(kImageWidth, image_width_on_image_notify_finished);
-
- // Does Reload.
- ResourceResponse resource_response(test_url);
- resource_response.SetMimeType("image/jpeg");
- resource_response.SetExpectedContentLength(kDataLength);
- image_resource->Loader()->DidReceiveResponse(
- WrappedResourceResponse(resource_response));
- image_resource->Loader()->DidReceiveData(data, kDataLength);
- image_resource->Loader()->DidFinishLoading(base::TimeTicks(), kDataLength,
- kDataLength, kDataLength, false);
-
- // Checks |imageResource|'s status after reloading.
- EXPECT_EQ(ResourceStatus::kCached, image_resource->GetStatus());
- EXPECT_FALSE(image_resource->ErrorOccurred());
- EXPECT_EQ(kDataLength, image_resource->EncodedSize());
-
- // Checks |observer| after reloading that it is notified of updates/finish.
- EXPECT_LT(original_image_changed_count, observer->ImageChangedCount());
- EXPECT_EQ(kImageWidth, observer->ImageWidthOnLastImageChanged());
- EXPECT_TRUE(observer->ImageNotifyFinishedCalled());
- if (!already_notified_finish) {
- // If imageNotifyFinished() has not been called before the reloaded
- // response is served, then imageNotifyFinished() should be called with
- // the new image (of width |imageWidth|).
- EXPECT_EQ(kImageWidth, observer->ImageWidthOnImageNotifyFinished());
- }
-
- // Checks |content| receives the correct image.
- EXPECT_TRUE(content->HasImage());
- EXPECT_FALSE(content->GetImage()->IsNull());
- EXPECT_EQ(kImageWidth, content->GetImage()->width());
- EXPECT_EQ(kImageHeight, content->GetImage()->height());
- EXPECT_FALSE(content->GetImage()->PaintImageForCurrentFrame().is_multipart());
-}
-
AtomicString BuildContentRange(size_t range_length, size_t total_length) {
return AtomicString(String("bytes 0-" + String::Number(range_length - 1) +
"/" + String::Number(total_length)));
}
-void TestThatIsPlaceholderRequestAndServeResponse(
- const KURL& url,
- ImageResource* image_resource,
- MockImageResourceObserver* observer) {
- // Checks that |imageResource| is requesting for placeholder.
- EXPECT_TRUE(image_resource->ShouldShowPlaceholder());
- EXPECT_EQ("bytes=0-2047",
- image_resource->GetResourceRequest().HttpHeaderField("range"));
- EXPECT_EQ(0, observer->ImageChangedCount());
-
- // Serves partial response that is sufficient for creating a placeholder.
- ResourceResponse resource_response(url);
- resource_response.SetMimeType("image/jpeg");
- resource_response.SetExpectedContentLength(
- kJpegImageSubrangeWithDimensionsLength);
- resource_response.SetHttpStatusCode(206);
- resource_response.SetHttpHeaderField(
- "content-range", BuildContentRange(kJpegImageSubrangeWithDimensionsLength,
- sizeof(kJpegImage)));
- image_resource->Loader()->DidReceiveResponse(
- WrappedResourceResponse(resource_response));
- image_resource->Loader()->DidReceiveData(
- reinterpret_cast<const char*>(kJpegImage),
- kJpegImageSubrangeWithDimensionsLength);
- image_resource->Loader()->DidFinishLoading(
- base::TimeTicks(), kJpegImageSubrangeWithDimensionsLength,
- kJpegImageSubrangeWithDimensionsLength,
- kJpegImageSubrangeWithDimensionsLength, false);
-
- // Checks that |imageResource| is successfully loaded, showing a placeholder.
- EXPECT_EQ(ResourceStatus::kCached, image_resource->GetStatus());
- EXPECT_EQ(kJpegImageSubrangeWithDimensionsLength,
- image_resource->EncodedSize());
-
- EXPECT_LT(0, observer->ImageChangedCount());
- EXPECT_EQ(kJpegImageWidth, observer->ImageWidthOnLastImageChanged());
- EXPECT_TRUE(observer->ImageNotifyFinishedCalled());
- EXPECT_EQ(kJpegImageWidth, observer->ImageWidthOnImageNotifyFinished());
- ASSERT_TRUE(image_resource->GetContent()->HasImage());
- EXPECT_EQ(kJpegImageWidth, image_resource->GetContent()->GetImage()->width());
- EXPECT_EQ(kJpegImageHeight,
- image_resource->GetContent()->GetImage()->height());
-
- // A placeholder image.
- EXPECT_TRUE(image_resource->ShouldShowPlaceholder());
- EXPECT_FALSE(IsA<BitmapImage>(image_resource->GetContent()->GetImage()));
- EXPECT_FALSE(IsA<SVGImage>(image_resource->GetContent()->GetImage()));
-}
-
-void TestThatIsNotPlaceholderRequestAndServeResponse(
- const KURL& url,
- ImageResource* image_resource,
- MockImageResourceObserver* observer) {
- // Checks that |imageResource| is NOT requesting for placeholder.
- EXPECT_FALSE(image_resource->ShouldShowPlaceholder());
- EXPECT_EQ(g_null_atom,
- image_resource->GetResourceRequest().HttpHeaderField("range"));
- EXPECT_EQ(0, observer->ImageChangedCount());
-
- // Serves full response.
- ResourceResponse resource_response(url);
- resource_response.SetMimeType("image/jpeg");
- resource_response.SetExpectedContentLength(sizeof(kJpegImage));
- image_resource->Loader()->DidReceiveResponse(
- WrappedResourceResponse(resource_response));
- image_resource->Loader()->DidReceiveData(
- reinterpret_cast<const char*>(kJpegImage), sizeof(kJpegImage));
- image_resource->Loader()->DidFinishLoading(
- base::TimeTicks(), sizeof(kJpegImage), sizeof(kJpegImage),
- sizeof(kJpegImage), false);
-
- // Checks that |imageResource| is successfully loaded,
- // showing a non-placeholder image.
- EXPECT_EQ(ResourceStatus::kCached, image_resource->GetStatus());
- EXPECT_EQ(sizeof(kJpegImage), image_resource->EncodedSize());
-
- EXPECT_LT(0, observer->ImageChangedCount());
- EXPECT_EQ(kJpegImageWidth, observer->ImageWidthOnLastImageChanged());
- EXPECT_TRUE(observer->ImageNotifyFinishedCalled());
- EXPECT_EQ(kJpegImageWidth, observer->ImageWidthOnImageNotifyFinished());
- ASSERT_TRUE(image_resource->GetContent()->HasImage());
- EXPECT_EQ(kJpegImageWidth, image_resource->GetContent()->GetImage()->width());
- EXPECT_EQ(kJpegImageHeight,
- image_resource->GetContent()->GetImage()->height());
-
- // A non-placeholder bitmap image.
- EXPECT_FALSE(image_resource->ShouldShowPlaceholder());
- EXPECT_TRUE(IsA<BitmapImage>(image_resource->GetContent()->GetImage()));
- EXPECT_FALSE(IsA<SVGImage>(image_resource->GetContent()->GetImage()));
-}
-
ResourceFetcher* CreateFetcher() {
auto* properties = MakeGarbageCollected<TestResourceFetcherProperties>();
return MakeGarbageCollected<ResourceFetcher>(ResourceFetcherInit(
@@ -643,33 +490,6 @@ TEST_F(ImageResourceTest, UpdateBitmapImages) {
EXPECT_TRUE(IsA<BitmapImage>(image_resource->GetContent()->GetImage()));
}
-class ImageResourceReloadTest : public testing::Test,
- private ScopedMockOverlayScrollbars {};
-
-TEST_F(ImageResourceReloadTest, ReloadIfLoFiOrPlaceholderForPlaceholder) {
- KURL test_url(kTestURL);
- ScopedMockedURLLoad scoped_mocked_url_load(test_url, GetTestFilePath());
-
- ResourceFetcher* fetcher = CreateFetcher();
- FetchParameters params{ResourceRequest(test_url)};
- params.SetAllowImagePlaceholder();
- ImageResource* image_resource = ImageResource::Fetch(params, fetcher);
- EXPECT_EQ(FetchParameters::kAllowPlaceholder,
- params.GetImageRequestOptimization());
- auto observer =
- std::make_unique<MockImageResourceObserver>(image_resource->GetContent());
-
- TestThatIsPlaceholderRequestAndServeResponse(test_url, image_resource,
- observer.get());
-
- image_resource->ReloadIfLoFiOrPlaceholderImage(fetcher,
- Resource::kReloadAlways);
-
- TestThatReloadIsStartedThenServeReload(test_url, image_resource,
- image_resource->GetContent(),
- observer.get(), false);
-}
-
TEST_F(ImageResourceTest, SVGImage) {
KURL url("http://127.0.0.1:8000/foo");
ImageResource* image_resource = ImageResource::CreateForTest(url);
@@ -1072,419 +892,6 @@ TEST_F(ImageResourceTest, PartialContentWithoutDimensions) {
EXPECT_FALSE(image_resource->IsLoading());
}
-TEST_F(ImageResourceTest, FetchDisallowPlaceholder) {
- KURL test_url(kTestURL);
- ScopedMockedURLLoad scoped_mocked_url_load(test_url, GetTestFilePath());
-
- FetchParameters params{ResourceRequest(test_url)};
- ImageResource* image_resource = ImageResource::Fetch(params, CreateFetcher());
- EXPECT_EQ(FetchParameters::kNone, params.GetImageRequestOptimization());
- auto observer =
- std::make_unique<MockImageResourceObserver>(image_resource->GetContent());
-
- TestThatIsNotPlaceholderRequestAndServeResponse(test_url, image_resource,
- observer.get());
-}
-
-TEST_F(ImageResourceTest, FetchAllowPlaceholderDataURL) {
- KURL test_url("data:image/jpeg;base64," + Base64Encode(kJpegImage));
- FetchParameters params{ResourceRequest(test_url)};
- params.SetAllowImagePlaceholder();
- ImageResource* image_resource = ImageResource::Fetch(params, CreateFetcher());
- EXPECT_EQ(FetchParameters::kNone, params.GetImageRequestOptimization());
- EXPECT_EQ(g_null_atom,
- image_resource->GetResourceRequest().HttpHeaderField("range"));
- EXPECT_FALSE(image_resource->ShouldShowPlaceholder());
-}
-
-TEST_F(ImageResourceTest, FetchAllowPlaceholderPostRequest) {
- KURL test_url(kTestURL);
- ScopedMockedURLLoad scoped_mocked_url_load(test_url, GetTestFilePath());
- ResourceRequest resource_request(test_url);
- resource_request.SetHttpMethod(http_names::kPOST);
- FetchParameters params(std::move(resource_request));
- params.SetAllowImagePlaceholder();
- ImageResource* image_resource = ImageResource::Fetch(params, CreateFetcher());
- EXPECT_EQ(FetchParameters::kNone, params.GetImageRequestOptimization());
- EXPECT_EQ(g_null_atom,
- image_resource->GetResourceRequest().HttpHeaderField("range"));
- EXPECT_FALSE(image_resource->ShouldShowPlaceholder());
-
- image_resource->Loader()->Cancel();
-}
-
-TEST_F(ImageResourceTest, FetchAllowPlaceholderExistingRangeHeader) {
- KURL test_url(kTestURL);
- ScopedMockedURLLoad scoped_mocked_url_load(test_url, GetTestFilePath());
- ResourceRequest resource_request(test_url);
- resource_request.SetHttpHeaderField("range", "bytes=128-255");
- FetchParameters params(std::move(resource_request));
- params.SetAllowImagePlaceholder();
- ImageResource* image_resource = ImageResource::Fetch(params, CreateFetcher());
- EXPECT_EQ(FetchParameters::kNone, params.GetImageRequestOptimization());
- EXPECT_EQ("bytes=128-255",
- image_resource->GetResourceRequest().HttpHeaderField("range"));
- EXPECT_FALSE(image_resource->ShouldShowPlaceholder());
-
- image_resource->Loader()->Cancel();
-}
-
-TEST_F(ImageResourceTest, FetchAllowPlaceholderSuccessful) {
- KURL test_url(kTestURL);
- ScopedMockedURLLoad scoped_mocked_url_load(test_url, GetTestFilePath());
-
- FetchParameters params{ResourceRequest(test_url)};
- params.SetAllowImagePlaceholder();
- ImageResource* image_resource = ImageResource::Fetch(params, CreateFetcher());
- EXPECT_EQ(FetchParameters::kAllowPlaceholder,
- params.GetImageRequestOptimization());
- auto observer =
- std::make_unique<MockImageResourceObserver>(image_resource->GetContent());
-
- TestThatIsPlaceholderRequestAndServeResponse(test_url, image_resource,
- observer.get());
-}
-
-TEST_F(ImageResourceTest, FetchAllowPlaceholderUnsuccessful) {
- KURL test_url(kTestURL);
- ScopedMockedURLLoad scoped_mocked_url_load(test_url, GetTestFilePath());
-
- FetchParameters params{ResourceRequest(test_url)};
- params.SetAllowImagePlaceholder();
- ImageResource* image_resource = ImageResource::Fetch(params, CreateFetcher());
- EXPECT_EQ(FetchParameters::kAllowPlaceholder,
- params.GetImageRequestOptimization());
- EXPECT_EQ("bytes=0-2047",
- image_resource->GetResourceRequest().HttpHeaderField("range"));
- EXPECT_TRUE(image_resource->ShouldShowPlaceholder());
- auto observer =
- std::make_unique<MockImageResourceObserver>(image_resource->GetContent());
-
- const char kBadData[] = "notanimageresponse";
-
- ResourceResponse bad_response(test_url);
- bad_response.SetMimeType("image/jpeg");
- bad_response.SetExpectedContentLength(sizeof(kBadData));
- bad_response.SetHttpStatusCode(206);
- bad_response.SetHttpHeaderField(
- "content-range", BuildContentRange(sizeof(kBadData), sizeof(kJpegImage)));
-
- image_resource->Loader()->DidReceiveResponse(
- WrappedResourceResponse(bad_response));
-
- EXPECT_EQ(0, observer->ImageChangedCount());
-
- image_resource->Loader()->DidReceiveData(kBadData, sizeof(kBadData));
-
- // The dimensions could not be extracted, so the full original image should be
- // loading.
- EXPECT_FALSE(observer->ImageNotifyFinishedCalled());
- EXPECT_EQ(2, observer->ImageChangedCount());
- EXPECT_FALSE(image_resource->ShouldShowPlaceholder());
-
- TestThatReloadIsStartedThenServeReload(test_url, image_resource,
- image_resource->GetContent(),
- observer.get(), false);
-}
-
-TEST_F(ImageResourceTest, FetchAllowPlaceholderPartialContentWithoutDimensions) {
- const struct {
- WebURLRequest::PreviewsState initial_previews_state;
- WebURLRequest::PreviewsState expected_reload_previews_state;
- bool placeholder_before_reload;
- bool placeholder_after_reload;
- } tests[] = {
- {WebURLRequest::kPreviewsUnspecified, WebURLRequest::kPreviewsNoTransform,
- false},
- };
-
- for (const auto& test : tests) {
- KURL test_url(kTestURL);
- ScopedMockedURLLoad scoped_mocked_url_load(test_url, GetTestFilePath());
-
- ResourceRequest resource_request(test_url);
- resource_request.SetPreviewsState(test.initial_previews_state);
- FetchParameters params(std::move(resource_request));
-
- params.SetAllowImagePlaceholder();
- ImageResource* image_resource =
- ImageResource::Fetch(params, CreateFetcher());
- EXPECT_EQ(FetchParameters::kAllowPlaceholder,
- params.GetImageRequestOptimization());
- EXPECT_EQ("bytes=0-2047",
- image_resource->GetResourceRequest().HttpHeaderField("range"));
- EXPECT_TRUE(image_resource->ShouldShowPlaceholder());
- auto observer = std::make_unique<MockImageResourceObserver>(
- image_resource->GetContent());
-
- // TODO(hiroshige): Make the range request header and partial content length
- // consistent. https://crbug.com/689760.
- ResourceResponse partial_response(test_url);
- partial_response.SetMimeType("image/jpeg");
- partial_response.SetExpectedContentLength(
- kJpegImageSubrangeWithoutDimensionsLength);
- partial_response.SetHttpStatusCode(206);
- partial_response.SetHttpHeaderField(
- "content-range",
- BuildContentRange(kJpegImageSubrangeWithoutDimensionsLength,
- sizeof(kJpegImage)));
-
- image_resource->Loader()->DidReceiveResponse(
- WrappedResourceResponse(partial_response));
- image_resource->Loader()->DidReceiveData(
- reinterpret_cast<const char*>(kJpegImage),
- kJpegImageSubrangeWithoutDimensionsLength);
-
- EXPECT_EQ(0, observer->ImageChangedCount());
-
- image_resource->Loader()->DidFinishLoading(
- base::TimeTicks(), kJpegImageSubrangeWithoutDimensionsLength,
- kJpegImageSubrangeWithoutDimensionsLength,
- kJpegImageSubrangeWithoutDimensionsLength, false);
-
- EXPECT_FALSE(observer->ImageNotifyFinishedCalled());
- EXPECT_EQ(2, observer->ImageChangedCount());
-
- TestThatReloadIsStartedThenServeReload(
- test_url, image_resource, image_resource->GetContent(), observer.get(),
- test.placeholder_before_reload);
-
- EXPECT_EQ(test.expected_reload_previews_state,
- image_resource->GetResourceRequest().GetPreviewsState());
- }
-}
-
-TEST_F(ImageResourceTest, FetchAllowPlaceholderThenDisallowPlaceholder) {
- KURL test_url(kTestURL);
- ScopedMockedURLLoad scoped_mocked_url_load(test_url, GetTestFilePath());
-
- ResourceFetcher* fetcher = CreateFetcher();
-
- FetchParameters placeholder_params{ResourceRequest(test_url)};
- placeholder_params.SetAllowImagePlaceholder();
- ImageResource* image_resource =
- ImageResource::Fetch(placeholder_params, fetcher);
- auto observer =
- std::make_unique<MockImageResourceObserver>(image_resource->GetContent());
-
- FetchParameters non_placeholder_params{ResourceRequest(test_url)};
- ImageResource* image_resource2 =
- ImageResource::Fetch(non_placeholder_params, fetcher);
- auto observer2 = std::make_unique<MockImageResourceObserver>(
- image_resource2->GetContent());
-
- ImageResource* image_resource3 =
- ImageResource::Fetch(non_placeholder_params, fetcher);
- auto observer3 = std::make_unique<MockImageResourceObserver>(
- image_resource3->GetContent());
-
- // |imageResource| remains a placeholder, while following non-placeholder
- // requests start non-placeholder loading with a separate ImageResource.
- ASSERT_NE(image_resource, image_resource2);
- ASSERT_NE(image_resource->Loader(), image_resource2->Loader());
- ASSERT_NE(image_resource->GetContent(), image_resource2->GetContent());
- ASSERT_EQ(image_resource2, image_resource3);
-
- EXPECT_FALSE(observer->ImageNotifyFinishedCalled());
- EXPECT_FALSE(observer2->ImageNotifyFinishedCalled());
- EXPECT_FALSE(observer3->ImageNotifyFinishedCalled());
-
- // Checks that |imageResource2| (and |imageResource3|) loads a
- // non-placeholder image.
- TestThatIsNotPlaceholderRequestAndServeResponse(test_url, image_resource2,
- observer2.get());
- EXPECT_TRUE(observer3->ImageNotifyFinishedCalled());
-
- // Checks that |imageResource| will loads a placeholder image.
- TestThatIsPlaceholderRequestAndServeResponse(test_url, image_resource,
- observer.get());
-
- // |imageResource2| is still a non-placeholder image.
- EXPECT_FALSE(image_resource2->ShouldShowPlaceholder());
- EXPECT_TRUE(IsA<BitmapImage>(image_resource2->GetContent()->GetImage()));
-}
-
-TEST_F(ImageResourceTest,
- FetchAllowPlaceholderThenDisallowPlaceholderAfterLoaded) {
- KURL test_url(kTestURL);
- ScopedMockedURLLoad scoped_mocked_url_load(test_url, GetTestFilePath());
-
- ResourceFetcher* fetcher = CreateFetcher();
- FetchParameters placeholder_params{ResourceRequest(test_url)};
- placeholder_params.SetAllowImagePlaceholder();
- ImageResource* image_resource =
- ImageResource::Fetch(placeholder_params, fetcher);
- auto observer =
- std::make_unique<MockImageResourceObserver>(image_resource->GetContent());
-
- TestThatIsPlaceholderRequestAndServeResponse(test_url, image_resource,
- observer.get());
-
- FetchParameters non_placeholder_params{ResourceRequest(test_url)};
- ImageResource* image_resource2 =
- ImageResource::Fetch(non_placeholder_params, fetcher);
- auto observer2 = std::make_unique<MockImageResourceObserver>(
- image_resource2->GetContent());
-
- ImageResource* image_resource3 =
- ImageResource::Fetch(non_placeholder_params, fetcher);
- auto observer3 = std::make_unique<MockImageResourceObserver>(
- image_resource3->GetContent());
-
- EXPECT_FALSE(observer2->ImageNotifyFinishedCalled());
- EXPECT_FALSE(observer3->ImageNotifyFinishedCalled());
-
- // |imageResource| remains a placeholder, while following non-placeholder
- // requests start non-placeholder loading with a separate ImageResource.
- ASSERT_NE(image_resource, image_resource2);
- ASSERT_EQ(image_resource2, image_resource3);
-
- TestThatIsNotPlaceholderRequestAndServeResponse(test_url, image_resource2,
- observer2.get());
- EXPECT_TRUE(observer3->ImageNotifyFinishedCalled());
-}
-
-TEST_F(ImageResourceTest, FetchAllowPlaceholderFullResponseDecodeSuccess) {
- const struct {
- int status_code;
- AtomicString content_range;
- } tests[] = {
- {200, g_null_atom},
- {404, g_null_atom},
- {206, BuildContentRange(sizeof(kJpegImage), sizeof(kJpegImage))},
- };
- for (const auto& test : tests) {
- KURL test_url(kTestURL);
- ScopedMockedURLLoad scoped_mocked_url_load(test_url, GetTestFilePath());
-
- FetchParameters params{ResourceRequest(test_url)};
- params.SetAllowImagePlaceholder();
- ImageResource* image_resource =
- ImageResource::Fetch(params, CreateFetcher());
- EXPECT_EQ(FetchParameters::kAllowPlaceholder,
- params.GetImageRequestOptimization());
- EXPECT_EQ("bytes=0-2047",
- image_resource->GetResourceRequest().HttpHeaderField("range"));
- EXPECT_TRUE(image_resource->ShouldShowPlaceholder());
- auto observer = std::make_unique<MockImageResourceObserver>(
- image_resource->GetContent());
-
- ResourceResponse resource_response(test_url);
- resource_response.SetMimeType("imapge/jpeg");
- resource_response.SetExpectedContentLength(sizeof(kJpegImage));
- resource_response.SetHttpStatusCode(test.status_code);
- if (test.content_range != g_null_atom)
- resource_response.SetHttpHeaderField("content-range", test.content_range);
- image_resource->Loader()->DidReceiveResponse(
- WrappedResourceResponse(resource_response));
- image_resource->Loader()->DidReceiveData(
- reinterpret_cast<const char*>(kJpegImage), sizeof(kJpegImage));
- image_resource->Loader()->DidFinishLoading(
- base::TimeTicks(), sizeof(kJpegImage), sizeof(kJpegImage),
- sizeof(kJpegImage), false);
-
- EXPECT_EQ(ResourceStatus::kCached, image_resource->GetStatus());
- EXPECT_EQ(sizeof(kJpegImage), image_resource->EncodedSize());
- EXPECT_FALSE(image_resource->ShouldShowPlaceholder());
- EXPECT_LT(0, observer->ImageChangedCount());
- EXPECT_EQ(kJpegImageWidth, observer->ImageWidthOnLastImageChanged());
- EXPECT_TRUE(observer->ImageNotifyFinishedCalled());
- EXPECT_EQ(kJpegImageWidth, observer->ImageWidthOnImageNotifyFinished());
-
- ASSERT_TRUE(image_resource->GetContent()->HasImage());
- EXPECT_EQ(kJpegImageWidth,
- image_resource->GetContent()->GetImage()->width());
- EXPECT_EQ(kJpegImageHeight,
- image_resource->GetContent()->GetImage()->height());
- EXPECT_TRUE(IsA<BitmapImage>(image_resource->GetContent()->GetImage()));
- }
-}
-
-TEST_F(ImageResourceTest,
- FetchAllowPlaceholderFullResponseDecodeFailureNoReload) {
- static const char kBadImageData[] = "bad image data";
-
- const struct {
- int status_code;
- AtomicString content_range;
- uint32_t data_size;
- } tests[] = {
- {200, g_null_atom, sizeof(kBadImageData)},
- {206, BuildContentRange(sizeof(kBadImageData), sizeof(kBadImageData)),
- sizeof(kBadImageData)},
- {204, g_null_atom, 0},
- };
- for (const auto& test : tests) {
- KURL test_url(kTestURL);
- ScopedMockedURLLoad scoped_mocked_url_load(test_url, GetTestFilePath());
-
- FetchParameters params{ResourceRequest(test_url)};
- params.SetAllowImagePlaceholder();
- ImageResource* image_resource =
- ImageResource::Fetch(params, CreateFetcher());
- EXPECT_EQ(FetchParameters::kAllowPlaceholder,
- params.GetImageRequestOptimization());
- EXPECT_EQ("bytes=0-2047",
- image_resource->GetResourceRequest().HttpHeaderField("range"));
- EXPECT_TRUE(image_resource->ShouldShowPlaceholder());
- auto observer = std::make_unique<MockImageResourceObserver>(
- image_resource->GetContent());
-
- ResourceResponse resource_response(test_url);
- resource_response.SetMimeType("image/jpeg");
- resource_response.SetExpectedContentLength(test.data_size);
- resource_response.SetHttpStatusCode(test.status_code);
- if (test.content_range != g_null_atom)
- resource_response.SetHttpHeaderField("content-range", test.content_range);
- image_resource->Loader()->DidReceiveResponse(
- WrappedResourceResponse(resource_response));
- image_resource->Loader()->DidReceiveData(kBadImageData, test.data_size);
-
- EXPECT_EQ(ResourceStatus::kDecodeError, image_resource->GetStatus());
- EXPECT_FALSE(image_resource->ShouldShowPlaceholder());
- }
-}
-
-TEST_F(ImageResourceTest,
- FetchAllowPlaceholderFullResponseDecodeFailureWithReload) {
- const int kStatusCodes[] = {404, 500};
- for (int status_code : kStatusCodes) {
- KURL test_url(kTestURL);
- ScopedMockedURLLoad scoped_mocked_url_load(test_url, GetTestFilePath());
-
- FetchParameters params{ResourceRequest(test_url)};
- params.SetAllowImagePlaceholder();
- ImageResource* image_resource =
- ImageResource::Fetch(params, CreateFetcher());
- EXPECT_EQ(FetchParameters::kAllowPlaceholder,
- params.GetImageRequestOptimization());
- EXPECT_EQ("bytes=0-2047",
- image_resource->GetResourceRequest().HttpHeaderField("range"));
- EXPECT_TRUE(image_resource->ShouldShowPlaceholder());
- auto observer = std::make_unique<MockImageResourceObserver>(
- image_resource->GetContent());
-
- static const char kBadImageData[] = "bad image data";
-
- ResourceResponse resource_response(test_url);
- resource_response.SetMimeType("image/jpeg");
- resource_response.SetExpectedContentLength(sizeof(kBadImageData));
- resource_response.SetHttpStatusCode(status_code);
- image_resource->Loader()->DidReceiveResponse(
- WrappedResourceResponse(resource_response));
- image_resource->Loader()->DidReceiveData(kBadImageData,
- sizeof(kBadImageData));
-
- EXPECT_FALSE(observer->ImageNotifyFinishedCalled());
-
- // The dimensions could not be extracted, and the response code was a 4xx
- // error, so the full original image should be loading.
- TestThatReloadIsStartedThenServeReload(test_url, image_resource,
- image_resource->GetContent(),
- observer.get(), false);
- }
-}
-
TEST_F(ImageResourceTest, PeriodicFlushTest) {
ScopedTestingPlatformSupport<TestingPlatformSupportWithMockScheduler>
platform;
@@ -1511,7 +918,8 @@ TEST_F(ImageResourceTest, PeriodicFlushTest) {
MakeGarbageCollected<TestLoaderFactory>()));
auto frame_scheduler = std::make_unique<scheduler::FakeFrameScheduler>();
auto* scheduler = MakeGarbageCollected<ResourceLoadScheduler>(
- ResourceLoadScheduler::ThrottlingPolicy::kNormal, properties,
+ ResourceLoadScheduler::ThrottlingPolicy::kNormal,
+ ResourceLoadScheduler::ThrottleOptionOverride::kNone, properties,
frame_scheduler.get(), *MakeGarbageCollected<DetachableConsoleLogger>());
ImageResource* image_resource = ImageResource::CreateForTest(test_url);
diff --git a/chromium/third_party/blink/renderer/core/loader/resource/script_resource.cc b/chromium/third_party/blink/renderer/core/loader/resource/script_resource.cc
index a7a69c2617a..4b30c7c7ede 100644
--- a/chromium/third_party/blink/renderer/core/loader/resource/script_resource.cc
+++ b/chromium/third_party/blink/renderer/core/loader/resource/script_resource.cc
@@ -85,9 +85,7 @@ ScriptResource* ScriptResource::Fetch(FetchParameters& params,
if (streaming_allowed == kAllowStreaming) {
// Start streaming the script as soon as we get it.
- if (RuntimeEnabledFeatures::ScriptStreamingOnPreloadEnabled()) {
- resource->StartStreaming(fetcher->GetTaskRunner());
- }
+ resource->StartStreaming(fetcher->GetTaskRunner());
} else {
// Advance the |streaming_state_| to kStreamingNotAllowed by calling
// SetClientIsWaitingForFinished unless it is explicitly allowed.'
diff --git a/chromium/third_party/blink/renderer/core/loader/resource/text_resource.cc b/chromium/third_party/blink/renderer/core/loader/resource/text_resource.cc
index 8da9c8489ce..a7466df223d 100644
--- a/chromium/third_party/blink/renderer/core/loader/resource/text_resource.cc
+++ b/chromium/third_party/blink/renderer/core/loader/resource/text_resource.cc
@@ -5,12 +5,39 @@
#include "third_party/blink/renderer/core/loader/resource/text_resource.h"
#include "third_party/blink/renderer/core/html/parser/text_resource_decoder.h"
+#include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h"
#include "third_party/blink/renderer/platform/loader/fetch/text_resource_decoder_options.h"
#include "third_party/blink/renderer/platform/wtf/shared_buffer.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
namespace blink {
+namespace {
+
+class SVGDocumentResourceFactory : public ResourceFactory {
+ public:
+ SVGDocumentResourceFactory()
+ : ResourceFactory(ResourceType::kSVGDocument,
+ TextResourceDecoderOptions::kXMLContent) {}
+
+ Resource* Create(
+ const ResourceRequest& request,
+ const ResourceLoaderOptions& options,
+ const TextResourceDecoderOptions& decoder_options) const override {
+ return MakeGarbageCollected<TextResource>(
+ request, ResourceType::kSVGDocument, options, decoder_options);
+ }
+};
+
+} // namespace
+
+TextResource* TextResource::FetchSVGDocument(FetchParameters& params,
+ ResourceFetcher* fetcher,
+ ResourceClient* client) {
+ return To<TextResource>(
+ fetcher->RequestResource(params, SVGDocumentResourceFactory(), client));
+}
+
TextResource::TextResource(const ResourceRequest& resource_request,
ResourceType type,
const ResourceLoaderOptions& options,
diff --git a/chromium/third_party/blink/renderer/core/loader/resource/text_resource.h b/chromium/third_party/blink/renderer/core/loader/resource/text_resource.h
index 6016e3ab40b..214e246c21f 100644
--- a/chromium/third_party/blink/renderer/core/loader/resource/text_resource.h
+++ b/chromium/third_party/blink/renderer/core/loader/resource/text_resource.h
@@ -10,11 +10,23 @@
#include "third_party/blink/renderer/core/html/parser/text_resource_decoder.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource.h"
#include "third_party/blink/renderer/platform/loader/fetch/text_resource_decoder_options.h"
+#include "third_party/blink/renderer/platform/wtf/casting.h"
namespace blink {
+class ResourceFetcher;
+
class CORE_EXPORT TextResource : public Resource {
public:
+ static TextResource* FetchSVGDocument(FetchParameters&,
+ ResourceFetcher*,
+ ResourceClient*);
+ TextResource(const ResourceRequest&,
+ ResourceType,
+ const ResourceLoaderOptions&,
+ const TextResourceDecoderOptions&);
+ ~TextResource() override;
+
// Returns the decoded data in text form. The data has to be available at
// call time.
String DecodedText() const;
@@ -23,19 +35,25 @@ class CORE_EXPORT TextResource : public Resource {
void SetEncodingForTest(const String& encoding) { SetEncoding(encoding); }
- protected:
- TextResource(const ResourceRequest&,
- ResourceType,
- const ResourceLoaderOptions&,
- const TextResourceDecoderOptions&);
- ~TextResource() override;
+ bool HasData() const { return Data(); }
+ protected:
void SetEncoding(const String&) override;
private:
std::unique_ptr<TextResourceDecoder> decoder_;
};
+template <>
+struct DowncastTraits<TextResource> {
+ static bool AllowFrom(const Resource& resource) {
+ return resource.GetType() == ResourceType::kCSSStyleSheet ||
+ resource.GetType() == ResourceType::kScript ||
+ resource.GetType() == ResourceType::kXSLStyleSheet ||
+ resource.GetType() == ResourceType::kSVGDocument;
+ }
+};
+
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_RESOURCE_TEXT_RESOURCE_H_
diff --git a/chromium/third_party/blink/renderer/core/loader/resource_load_observer_for_frame.cc b/chromium/third_party/blink/renderer/core/loader/resource_load_observer_for_frame.cc
index 6d296c859f8..a6cf0175f6a 100644
--- a/chromium/third_party/blink/renderer/core/loader/resource_load_observer_for_frame.cc
+++ b/chromium/third_party/blink/renderer/core/loader/resource_load_observer_for_frame.cc
@@ -13,7 +13,6 @@
#include "third_party/blink/renderer/core/loader/alternate_signed_exchange_resource_info.h"
#include "third_party/blink/renderer/core/loader/document_loader.h"
#include "third_party/blink/renderer/core/loader/frame_loader.h"
-#include "third_party/blink/renderer/core/loader/frame_or_imported_document.h"
#include "third_party/blink/renderer/core/loader/idleness_detector.h"
#include "third_party/blink/renderer/core/loader/interactive_detector.h"
#include "third_party/blink/renderer/core/loader/mixed_content_checker.h"
@@ -34,9 +33,11 @@
namespace blink {
ResourceLoadObserverForFrame::ResourceLoadObserverForFrame(
- const FrameOrImportedDocument& frame_or_imported_document,
+ DocumentLoader& loader,
+ Document& document,
const ResourceFetcherProperties& fetcher_properties)
- : frame_or_imported_document_(frame_or_imported_document),
+ : document_loader_(loader),
+ document_(document),
fetcher_properties_(fetcher_properties) {}
ResourceLoadObserverForFrame::~ResourceLoadObserverForFrame() = default;
@@ -45,10 +46,8 @@ void ResourceLoadObserverForFrame::DidStartRequest(
ResourceType resource_type) {
// TODO(yhirano): Consider removing ResourceLoadObserver::DidStartRequest
// completely when we remove V8DOMActivityLogger.
- DocumentLoader* document_loader =
- frame_or_imported_document_->GetDocumentLoader();
- if (document_loader && !document_loader->Archive() &&
- params.Url().IsValid() && !params.IsSpeculativePreload()) {
+ if (!document_loader_->Archive() && params.Url().IsValid() &&
+ !params.IsSpeculativePreload()) {
V8DOMActivityLogger* activity_logger = nullptr;
const AtomicString& initiator_name = params.Options().initiator_info.name;
if (initiator_name == fetch_initiator_type_names::kXmlhttprequest) {
@@ -73,22 +72,20 @@ void ResourceLoadObserverForFrame::WillSendRequest(
const ResourceResponse& redirect_response,
ResourceType resource_type,
const FetchInitiatorInfo& initiator_info) {
- LocalFrame& frame = frame_or_imported_document_->GetFrame();
+ LocalFrame* frame = document_->GetFrame();
+ DCHECK(frame);
if (redirect_response.IsNull()) {
// Progress doesn't care about redirects, only notify it when an
// initial request is sent.
- frame.Loader().Progress().WillStartLoading(identifier, request.Priority());
+ frame->Loader().Progress().WillStartLoading(identifier, request.Priority());
}
- DocumentLoader& document_loader =
- frame_or_imported_document_->GetMasterDocumentLoader();
- Document& document = frame_or_imported_document_->GetDocument();
probe::WillSendRequest(
- GetProbe(), identifier, &document_loader,
+ GetProbe(), identifier, document_loader_,
fetcher_properties_->GetFetchClientSettingsObject().GlobalObjectUrl(),
request, redirect_response, initiator_info, resource_type);
- if (auto* idleness_detector = frame.GetIdlenessDetector())
- idleness_detector->OnWillSendRequest(document.Fetcher());
- if (auto* interactive_detector = InteractiveDetector::From(document))
+ if (auto* idleness_detector = frame->GetIdlenessDetector())
+ idleness_detector->OnWillSendRequest(document_->Fetcher());
+ if (auto* interactive_detector = InteractiveDetector::From(*document_))
interactive_detector->OnResourceLoadBegin(base::nullopt);
}
@@ -96,13 +93,11 @@ void ResourceLoadObserverForFrame::DidChangePriority(
uint64_t identifier,
ResourceLoadPriority priority,
int intra_priority_value) {
- DocumentLoader& document_loader =
- frame_or_imported_document_->GetMasterDocumentLoader();
TRACE_EVENT1("devtools.timeline", "ResourceChangePriority", "data",
inspector_change_resource_priority_event::Data(
- &document_loader, identifier, priority));
- probe::DidChangeResourcePriority(&frame_or_imported_document_->GetFrame(),
- &document_loader, identifier, priority);
+ document_loader_, identifier, priority));
+ probe::DidChangeResourcePriority(document_->GetFrame(), document_loader_,
+ identifier, priority);
}
void ResourceLoadObserverForFrame::DidReceiveResponse(
@@ -111,12 +106,11 @@ void ResourceLoadObserverForFrame::DidReceiveResponse(
const ResourceResponse& response,
const Resource* resource,
ResponseSource response_source) {
- LocalFrame& frame = frame_or_imported_document_->GetFrame();
- DocumentLoader& document_loader =
- frame_or_imported_document_->GetMasterDocumentLoader();
- LocalFrameClient* frame_client = frame.Client();
+ LocalFrame* frame = document_->GetFrame();
+ DCHECK(frame);
+ LocalFrameClient* frame_client = frame->Client();
SubresourceFilter* subresource_filter =
- document_loader.GetSubresourceFilter();
+ document_loader_->GetSubresourceFilter();
if (subresource_filter && resource->GetResourceRequest().IsAdResource())
subresource_filter->ReportAdRequestId(response.RequestId());
@@ -124,7 +118,7 @@ void ResourceLoadObserverForFrame::DidReceiveResponse(
if (response.GetCTPolicyCompliance() ==
ResourceResponse::kCTPolicyDoesNotComply) {
CountUsage(
- frame.IsMainFrame()
+ frame->IsMainFrame()
? WebFeature::
kCertificateTransparencyNonCompliantSubresourceInMainFrame
: WebFeature::
@@ -132,16 +126,23 @@ void ResourceLoadObserverForFrame::DidReceiveResponse(
}
if (response_source == ResponseSource::kFromMemoryCache) {
- frame_client->DispatchDidLoadResourceFromMemoryCache(
- ResourceRequest(resource->GetResourceRequest()), response);
+ ResourceRequest request(resource->GetResourceRequest());
+
+ if (!request.Url().ProtocolIs(url::kDataScheme)) {
+ frame_client->DispatchDidLoadResourceFromMemoryCache(request, response);
+ frame->GetLocalFrameHostRemote().DidLoadResourceFromMemoryCache(
+ request.Url(), String::FromUTF8(request.HttpMethod().Utf8()),
+ String::FromUTF8(response.MimeType().Utf8()),
+ request.GetRequestDestination());
+ }
// Note: probe::WillSendRequest needs to precede before this probe method.
- probe::MarkResourceAsCached(&frame, &document_loader, identifier);
+ probe::MarkResourceAsCached(frame, document_loader_, identifier);
if (response.IsNull())
return;
}
- MixedContentChecker::CheckMixedPrivatePublic(&frame,
+ MixedContentChecker::CheckMixedPrivatePublic(frame,
response.RemoteIPAddress());
std::unique_ptr<AlternateSignedExchangeResourceInfo> alternate_resource_info;
@@ -152,7 +153,7 @@ void ResourceLoadObserverForFrame::DidReceiveResponse(
CountUsage(WebFeature::kLinkRelPrefetchForSignedExchanges);
if (RuntimeEnabledFeatures::SignedExchangeSubresourcePrefetchEnabled(
- &frame_or_imported_document_->GetDocument()) &&
+ document_) &&
resource->LastResourceResponse()) {
// See if the outer response (which must be the last response in
// the redirect chain) had provided alternate links for the prefetch.
@@ -170,38 +171,36 @@ void ResourceLoadObserverForFrame::DidReceiveResponse(
: PreloadHelper::kLoadResourcesAndPreconnect;
PreloadHelper::LoadLinksFromHeader(
response.HttpHeaderField(http_names::kLink), response.CurrentRequestUrl(),
- frame, &frame_or_imported_document_->GetDocument(),
- resource_loading_policy, PreloadHelper::kLoadAll,
+ *frame, document_, resource_loading_policy, PreloadHelper::kLoadAll,
nullptr /* viewport_description */, std::move(alternate_resource_info),
base::OptionalOrNullptr(response.RecursivePrefetchToken()));
if (response.HasMajorCertificateErrors()) {
- MixedContentChecker::HandleCertificateError(&frame, response,
+ MixedContentChecker::HandleCertificateError(frame, response,
request.GetRequestContext());
}
if (response.IsLegacyTLSVersion()) {
- frame.Loader().ReportLegacyTLSVersion(
+ frame->Loader().ReportLegacyTLSVersion(
response.CurrentRequestUrl(), true /* is_subresource */,
resource->GetResourceRequest().IsAdResource());
}
- frame.Loader().Progress().IncrementProgress(identifier, response);
- probe::DidReceiveResourceResponse(GetProbe(), identifier, &document_loader,
+ frame->Loader().Progress().IncrementProgress(identifier, response);
+ probe::DidReceiveResourceResponse(GetProbe(), identifier, document_loader_,
response, resource);
// It is essential that inspector gets resource response BEFORE console.
- frame.Console().ReportResourceResponseReceived(&document_loader, identifier,
- response);
+ frame->Console().ReportResourceResponseReceived(document_loader_, identifier,
+ response);
}
void ResourceLoadObserverForFrame::DidReceiveData(
uint64_t identifier,
base::span<const char> chunk) {
- LocalFrame& frame = frame_or_imported_document_->GetFrame();
- DocumentLoader& document_loader =
- frame_or_imported_document_->GetMasterDocumentLoader();
- frame.Loader().Progress().IncrementProgress(identifier, chunk.size());
- probe::DidReceiveData(GetProbe(), identifier, &document_loader, chunk.data(),
+ LocalFrame* frame = document_->GetFrame();
+ DCHECK(frame);
+ frame->Loader().Progress().IncrementProgress(identifier, chunk.size());
+ probe::DidReceiveData(GetProbe(), identifier, document_loader_, chunk.data(),
chunk.size());
}
@@ -209,18 +208,14 @@ void ResourceLoadObserverForFrame::DidReceiveTransferSizeUpdate(
uint64_t identifier,
int transfer_size_diff) {
DCHECK_GT(transfer_size_diff, 0);
- DocumentLoader& document_loader =
- frame_or_imported_document_->GetMasterDocumentLoader();
- probe::DidReceiveEncodedDataLength(GetProbe(), &document_loader, identifier,
+ probe::DidReceiveEncodedDataLength(GetProbe(), document_loader_, identifier,
transfer_size_diff);
}
void ResourceLoadObserverForFrame::DidDownloadToBlob(uint64_t identifier,
BlobDataHandle* blob) {
if (blob) {
- probe::DidReceiveBlob(
- GetProbe(), identifier,
- &frame_or_imported_document_->GetMasterDocumentLoader(), blob);
+ probe::DidReceiveBlob(GetProbe(), identifier, document_loader_, blob);
}
}
@@ -230,24 +225,20 @@ void ResourceLoadObserverForFrame::DidFinishLoading(
int64_t encoded_data_length,
int64_t decoded_body_length,
bool should_report_corb_blocking) {
- LocalFrame& frame = frame_or_imported_document_->GetFrame();
- DocumentLoader& document_loader =
- frame_or_imported_document_->GetMasterDocumentLoader();
- frame.Loader().Progress().CompleteProgress(identifier);
- probe::DidFinishLoading(GetProbe(), identifier, &document_loader, finish_time,
+ LocalFrame* frame = document_->GetFrame();
+ DCHECK(frame);
+ frame->Loader().Progress().CompleteProgress(identifier);
+ probe::DidFinishLoading(GetProbe(), identifier, document_loader_, finish_time,
encoded_data_length, decoded_body_length,
should_report_corb_blocking);
- Document& document = frame_or_imported_document_->GetDocument();
- if (auto* interactive_detector = InteractiveDetector::From(document)) {
+ if (auto* interactive_detector = InteractiveDetector::From(*document_)) {
interactive_detector->OnResourceLoadEnd(finish_time);
}
- if (LocalFrame* frame = document.GetFrame()) {
- if (IdlenessDetector* idleness_detector = frame->GetIdlenessDetector()) {
- idleness_detector->OnDidLoadResource();
- }
+ if (IdlenessDetector* idleness_detector = frame->GetIdlenessDetector()) {
+ idleness_detector->OnDidLoadResource();
}
- document.CheckCompleted();
+ document_->CheckCompleted();
}
void ResourceLoadObserverForFrame::DidFailLoading(
@@ -256,46 +247,40 @@ void ResourceLoadObserverForFrame::DidFailLoading(
const ResourceError& error,
int64_t,
IsInternalRequest is_internal_request) {
- LocalFrame& frame = frame_or_imported_document_->GetFrame();
- DocumentLoader& document_loader =
- frame_or_imported_document_->GetMasterDocumentLoader();
- frame.Loader().Progress().CompleteProgress(identifier);
- probe::DidFailLoading(GetProbe(), identifier, &document_loader, error);
+ LocalFrame* frame = document_->GetFrame();
+ DCHECK(frame);
+ frame->Loader().Progress().CompleteProgress(identifier);
+ probe::DidFailLoading(GetProbe(), identifier, document_loader_, error);
// Notification to FrameConsole should come AFTER InspectorInstrumentation
// call, DevTools front-end relies on this.
if (!is_internal_request) {
- frame.Console().DidFailLoading(&document_loader, identifier, error);
+ frame->Console().DidFailLoading(document_loader_, identifier, error);
}
- Document& document = frame_or_imported_document_->GetDocument();
- if (auto* interactive_detector = InteractiveDetector::From(document)) {
+ if (auto* interactive_detector = InteractiveDetector::From(*document_)) {
// We have not yet recorded load_finish_time. Pass nullopt here; we will
// call base::TimeTicks::Now() lazily when we need it.
interactive_detector->OnResourceLoadEnd(base::nullopt);
}
- if (LocalFrame* frame = document.GetFrame()) {
- if (IdlenessDetector* idleness_detector = frame->GetIdlenessDetector()) {
- idleness_detector->OnDidLoadResource();
- }
+ if (IdlenessDetector* idleness_detector = frame->GetIdlenessDetector()) {
+ idleness_detector->OnDidLoadResource();
}
- document.CheckCompleted();
+ document_->CheckCompleted();
}
void ResourceLoadObserverForFrame::Trace(Visitor* visitor) {
- visitor->Trace(frame_or_imported_document_);
+ visitor->Trace(document_loader_);
+ visitor->Trace(document_);
visitor->Trace(fetcher_properties_);
ResourceLoadObserver::Trace(visitor);
}
CoreProbeSink* ResourceLoadObserverForFrame::GetProbe() {
- return probe::ToCoreProbeSink(
- frame_or_imported_document_->GetFrame().GetDocument());
+ return probe::ToCoreProbeSink(*document_);
}
void ResourceLoadObserverForFrame::CountUsage(WebFeature feature) {
- frame_or_imported_document_->GetMasterDocumentLoader()
- .GetUseCounterHelper()
- .Count(feature, &frame_or_imported_document_->GetFrame());
+ document_loader_->GetUseCounterHelper().Count(feature, document_->GetFrame());
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/loader/resource_load_observer_for_frame.h b/chromium/third_party/blink/renderer/core/loader/resource_load_observer_for_frame.h
index 4ed13e134b3..33241651752 100644
--- a/chromium/third_party/blink/renderer/core/loader/resource_load_observer_for_frame.h
+++ b/chromium/third_party/blink/renderer/core/loader/resource_load_observer_for_frame.h
@@ -15,16 +15,17 @@
namespace blink {
class CoreProbeSink;
-class FrameOrImportedDocument;
+class Document;
+class DocumentLoader;
class ResourceFetcherProperties;
// ResourceLoadObserver implementation associated with a frame.
class CORE_EXPORT ResourceLoadObserverForFrame final
: public ResourceLoadObserver {
public:
- ResourceLoadObserverForFrame(
- const FrameOrImportedDocument& frame_or_imported_document,
- const ResourceFetcherProperties& properties);
+ ResourceLoadObserverForFrame(DocumentLoader& loader,
+ Document& document,
+ const ResourceFetcherProperties& properties);
~ResourceLoadObserverForFrame() override;
// ResourceLoadObserver implementation.
@@ -63,11 +64,10 @@ class CORE_EXPORT ResourceLoadObserverForFrame final
CoreProbeSink* GetProbe();
void CountUsage(WebFeature);
- // There are some overlap between |frame_or_imported_document| and
- // |fetcher_properties_|.
- // Use this when you want to access frame, document, etc. directly.
- const Member<const FrameOrImportedDocument> frame_or_imported_document_;
- // Use this whenever possible.
+ // There are some overlap between |document_loader_|, |document_| and
+ // |fetcher_properties_|. Use |fetcher_properties_| whenever possible.
+ const Member<DocumentLoader> document_loader_;
+ const Member<Document> document_;
const Member<const ResourceFetcherProperties> fetcher_properties_;
};
diff --git a/chromium/third_party/blink/renderer/core/loader/resource_load_observer_for_frame_test.cc b/chromium/third_party/blink/renderer/core/loader/resource_load_observer_for_frame_test.cc
index 4b2a1e5ea27..18cc346db5a 100644
--- a/chromium/third_party/blink/renderer/core/loader/resource_load_observer_for_frame_test.cc
+++ b/chromium/third_party/blink/renderer/core/loader/resource_load_observer_for_frame_test.cc
@@ -6,7 +6,6 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/core/loader/empty_clients.h"
-#include "third_party/blink/renderer/core/loader/frame_or_imported_document.h"
#include "third_party/blink/renderer/core/testing/dummy_page_holder.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource.h"
@@ -39,8 +38,7 @@ TEST(ResourceLoadObserverForFrameTest, MemoryCacheCertificateError) {
std::make_unique<DummyPageHolder>(IntSize(), nullptr, client);
LocalFrame& frame = dummy_page_holder->GetFrame();
auto* observer = MakeGarbageCollected<ResourceLoadObserverForFrame>(
- *MakeGarbageCollected<FrameOrImportedDocument>(
- *frame.GetDocument()->Loader(), *frame.GetDocument()),
+ *frame.GetDocument()->Loader(), *frame.GetDocument(),
*MakeGarbageCollected<TestResourceFetcherProperties>());
KURL url("https://www.example.com/");
ResourceRequest resource_request(url);
diff --git a/chromium/third_party/blink/renderer/core/loader/subresource_filter.cc b/chromium/third_party/blink/renderer/core/loader/subresource_filter.cc
index f82f2ffd50d..2c4b51cd6ce 100644
--- a/chromium/third_party/blink/renderer/core/loader/subresource_filter.cc
+++ b/chromium/third_party/blink/renderer/core/loader/subresource_filter.cc
@@ -10,6 +10,7 @@
#include "base/single_thread_task_runner.h"
#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/renderer/core/dom/document.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/inspector/console_message.h"
#include "third_party/blink/renderer/core/loader/document_loader.h"
@@ -43,10 +44,11 @@ SubresourceFilter::SubresourceFilter(
DCHECK(subresource_filter_);
// Report the main resource as an ad if the subresource filter is
// associated with an ad subframe.
- if (auto* document = Document::DynamicFrom(execution_context_.Get())) {
- auto* loader = document->Loader();
- if (document->GetFrame()->IsAdSubframe()) {
- ReportAdRequestId(loader->GetResponse().RequestId());
+ if (auto* window = DynamicTo<LocalDOMWindow>(execution_context_.Get())) {
+ auto* frame = window->GetFrame();
+ if (frame->IsAdSubframe()) {
+ ReportAdRequestId(
+ frame->Loader().GetDocumentLoader()->GetResponse().RequestId());
}
}
}
@@ -132,9 +134,9 @@ void SubresourceFilter::ReportLoad(
// TODO(csharrison): Consider posting a task to the main thread from
// worker thread, or adding support for DidObserveLoadingBehavior to
// ExecutionContext.
- if (auto* document = Document::DynamicFrom(execution_context_.Get())) {
- if (DocumentLoader* loader = document->Loader()) {
- loader->DidObserveLoadingBehavior(
+ if (auto* window = DynamicTo<LocalDOMWindow>(execution_context_.Get())) {
+ if (auto* frame = window->GetFrame()) {
+ frame->Loader().GetDocumentLoader()->DidObserveLoadingBehavior(
kLoadingBehaviorSubresourceFilterMatch);
}
}
diff --git a/chromium/third_party/blink/renderer/core/loader/threadable_loader.cc b/chromium/third_party/blink/renderer/core/loader/threadable_loader.cc
index 2eabb5f8cf7..4fed84a7914 100644
--- a/chromium/third_party/blink/renderer/core/loader/threadable_loader.cc
+++ b/chromium/third_party/blink/renderer/core/loader/threadable_loader.cc
@@ -45,6 +45,7 @@
#include "third_party/blink/public/platform/web_url_request.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/frame/frame_console.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/local_frame_client.h"
#include "third_party/blink/renderer/core/frame/web_feature.h"
@@ -230,7 +231,7 @@ ThreadableLoader::ThreadableLoader(
}
}
-void ThreadableLoader::Start(const ResourceRequest& request) {
+void ThreadableLoader::Start(ResourceRequest request) {
original_security_origin_ = security_origin_ = request.RequestorOrigin();
// Setting an outgoing referer is only supported in the async code path.
DCHECK(async_ ||
@@ -277,16 +278,13 @@ void ThreadableLoader::Start(const ResourceRequest& request) {
request_headers_ = request.HttpHeaderFields();
report_upload_progress_ = request.ReportUploadProgress();
- ResourceRequest new_request;
- new_request.CopyFrom(request);
-
// Set the service worker mode to none if "bypass for network" in DevTools is
// enabled.
bool should_bypass_service_worker = false;
probe::ShouldBypassServiceWorker(execution_context_,
&should_bypass_service_worker);
if (should_bypass_service_worker)
- new_request.SetSkipServiceWorker(true);
+ request.SetSkipServiceWorker(true);
// Process the CORS protocol inside the ThreadableLoader for the
// following cases:
@@ -311,15 +309,16 @@ void ThreadableLoader::Start(const ResourceRequest& request) {
const bool is_controlled_by_service_worker =
resource_fetcher_->IsControlledByServiceWorker() ==
blink::mojom::ControllerServiceWorkerMode::kControlled;
- if (!async_ || new_request.GetSkipServiceWorker() ||
+ if (!async_ || request.GetSkipServiceWorker() ||
!SchemeRegistry::ShouldTreatURLSchemeAsAllowingServiceWorkers(
- new_request.Url().Protocol()) ||
+ request.Url().Protocol()) ||
!is_controlled_by_service_worker) {
- DispatchInitialRequest(new_request);
+ DispatchInitialRequest(request);
return;
}
- if (cors::IsCorsEnabledRequestMode(request.GetMode())) {
+ if (!out_of_blink_cors_ &&
+ cors::IsCorsEnabledRequestMode(request.GetMode())) {
// Save the request to fallback_request_for_service_worker to use when the
// service worker doesn't handle (call respondWith()) a CORS enabled
// request.
@@ -328,7 +327,7 @@ void ThreadableLoader::Start(const ResourceRequest& request) {
fallback_request_for_service_worker_.SetSkipServiceWorker(true);
}
- LoadRequest(new_request, resource_loader_options_);
+ LoadRequest(request, resource_loader_options_);
}
void ThreadableLoader::DispatchInitialRequest(ResourceRequest& request) {
@@ -633,9 +632,7 @@ bool ThreadableLoader::RedirectReceived(
probe::DidReceiveCorsRedirectResponse(
execution_context_, resource->InspectorId(),
- GetDocument() && GetDocument()->GetFrame()
- ? GetDocument()->GetFrame()->Loader().GetDocumentLoader()
- : nullptr,
+ GetFrame() ? GetFrame()->Loader().GetDocumentLoader() : nullptr,
redirect_response_to_pass, resource);
if (auto error_status = cors::CheckRedirectLocation(
@@ -777,7 +774,7 @@ void ThreadableLoader::HandlePreflightResponse(
void ThreadableLoader::ReportResponseReceived(
uint64_t identifier,
const ResourceResponse& response) {
- LocalFrame* frame = GetDocument() ? GetDocument()->GetFrame() : nullptr;
+ LocalFrame* frame = GetFrame();
if (!frame)
return;
DocumentLoader* loader = frame->Loader().GetDocumentLoader();
@@ -1069,8 +1066,9 @@ const SecurityOrigin* ThreadableLoader::GetSecurityOrigin() const {
.GetSecurityOrigin();
}
-Document* ThreadableLoader::GetDocument() const {
- return Document::DynamicFrom(execution_context_.Get());
+LocalFrame* ThreadableLoader::GetFrame() const {
+ auto* window = DynamicTo<LocalDOMWindow>(execution_context_.Get());
+ return window ? window->GetFrame() : nullptr;
}
void ThreadableLoader::Trace(Visitor* visitor) {
diff --git a/chromium/third_party/blink/renderer/core/loader/threadable_loader.h b/chromium/third_party/blink/renderer/core/loader/threadable_loader.h
index 79105495732..d6b9c5edf8c 100644
--- a/chromium/third_party/blink/renderer/core/loader/threadable_loader.h
+++ b/chromium/third_party/blink/renderer/core/loader/threadable_loader.h
@@ -52,8 +52,8 @@
namespace blink {
class ExecutionContext;
-class Document;
class KURL;
+class LocalFrame;
class ResourceRequest;
class SecurityOrigin;
class ThreadableLoaderClient;
@@ -110,7 +110,7 @@ class CORE_EXPORT ThreadableLoader final
CreateAccessControlPreflightRequestForTesting(const ResourceRequest&);
// Must be called to actually begin the request.
- void Start(const ResourceRequest&);
+ void Start(ResourceRequest);
// A ThreadableLoader may have a timeout specified. It is possible, in some
// cases, for the timeout to be overridden after the request is sent (for
@@ -203,9 +203,9 @@ class CORE_EXPORT ThreadableLoader final
const SecurityOrigin* GetSecurityOrigin() const;
- // Returns null if the loader is not associated with Document.
- // TODO(kinuko): Remove dependency to document.
- Document* GetDocument() const;
+ // Returns null if the loader is not associated with a frame.
+ // TODO(kinuko): Remove dependency to frame.
+ LocalFrame* GetFrame() const;
Member<ThreadableLoaderClient> client_;
Member<ExecutionContext> execution_context_;
@@ -218,7 +218,7 @@ class CORE_EXPORT ThreadableLoader final
const ResourceLoaderOptions resource_loader_options_;
// True when feature OutOfBlinkCors is enabled (https://crbug.com/736308).
- bool out_of_blink_cors_;
+ const bool out_of_blink_cors_;
// Corresponds to the CORS flag in the Fetch spec.
bool cors_flag_ = false;
diff --git a/chromium/third_party/blink/renderer/core/loader/threadable_loader_test.cc b/chromium/third_party/blink/renderer/core/loader/threadable_loader_test.cc
index a73c99e7132..ced0190e76e 100644
--- a/chromium/third_party/blink/renderer/core/loader/threadable_loader_test.cc
+++ b/chromium/third_party/blink/renderer/core/loader/threadable_loader_test.cc
@@ -16,6 +16,7 @@
#include "third_party/blink/public/platform/web_url_request.h"
#include "third_party/blink/public/platform/web_url_response.h"
#include "third_party/blink/public/platform/web_worker_fetch_context.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/loader/threadable_loader.h"
#include "third_party/blink/renderer/core/loader/threadable_loader_client.h"
#include "third_party/blink/renderer/core/loader/worker_fetch_context.h"
@@ -166,10 +167,13 @@ class ThreadableLoaderTestHelper final {
void CreateLoader(ThreadableLoaderClient* client) {
ResourceLoaderOptions resource_loader_options;
loader_ = MakeGarbageCollected<ThreadableLoader>(
- *GetDocument().ToExecutionContext(), client, resource_loader_options);
+ *dummy_page_holder_->GetFrame().DomWindow(), client,
+ resource_loader_options);
}
- void StartLoader(const ResourceRequest& request) { loader_->Start(request); }
+ void StartLoader(ResourceRequest request) {
+ loader_->Start(std::move(request));
+ }
void CancelLoader() { loader_->Cancel(); }
void CancelAndClearLoader() {
@@ -193,8 +197,6 @@ class ThreadableLoaderTestHelper final {
}
private:
- Document& GetDocument() { return dummy_page_holder_->GetDocument(); }
-
std::unique_ptr<DummyPageHolder> dummy_page_holder_;
Checkpoint checkpoint_;
Persistent<ThreadableLoader> loader_;
@@ -212,7 +214,7 @@ class ThreadableLoaderTest : public testing::Test {
request.SetRequestContext(mojom::RequestContextType::OBJECT);
request.SetMode(request_mode);
request.SetCredentialsMode(network::mojom::CredentialsMode::kOmit);
- helper_->StartLoader(request);
+ helper_->StartLoader(std::move(request));
}
void CancelLoader() { helper_->CancelLoader(); }
diff --git a/chromium/third_party/blink/renderer/core/loader/threaded_icon_loader.cc b/chromium/third_party/blink/renderer/core/loader/threaded_icon_loader.cc
index 6b05fdda7d0..d4697bf4a2d 100644
--- a/chromium/third_party/blink/renderer/core/loader/threaded_icon_loader.cc
+++ b/chromium/third_party/blink/renderer/core/loader/threaded_icon_loader.cc
@@ -7,6 +7,7 @@
#include <algorithm>
#include "base/metrics/histogram_macros.h"
+#include "base/numerics/ranges.h"
#include "skia/ext/image_operations.h"
#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
@@ -23,18 +24,9 @@
namespace blink {
-namespace {
-
-// Because including base::ClampToRange would be a dependency violation.
-int ClampToRange(const int value, const int min, const int max) {
- return std::min(std::max(value, min), max);
-}
-
-} // namespace
-
void ThreadedIconLoader::Start(
ExecutionContext* execution_context,
- const ResourceRequest& resource_request,
+ const ResourceRequestHead& resource_request,
const base::Optional<gfx::Size>& resize_dimensions,
IconCallback callback) {
DCHECK(!stopped_);
@@ -53,7 +45,7 @@ void ThreadedIconLoader::Start(
threadable_loader_ = MakeGarbageCollected<ThreadableLoader>(
*execution_context, this, resource_loader_options);
threadable_loader_->SetTimeout(resource_request.TimeoutInterval());
- threadable_loader_->Start(resource_request);
+ threadable_loader_->Start(ResourceRequest(resource_request));
start_time_ = base::TimeTicks::Now();
}
@@ -146,11 +138,11 @@ void ThreadedIconLoader::DecodeAndResizeImageOnBackgroundThread(
}
int resized_width =
- ClampToRange(static_cast<int>(scale * decoded_icon_.width()), 1,
- resize_dimensions_->width());
+ base::ClampToRange(static_cast<int>(scale * decoded_icon_.width()), 1,
+ resize_dimensions_->width());
int resized_height =
- ClampToRange(static_cast<int>(scale * decoded_icon_.height()), 1,
- resize_dimensions_->height());
+ base::ClampToRange(static_cast<int>(scale * decoded_icon_.height()), 1,
+ resize_dimensions_->height());
// Use the RESIZE_GOOD quality allowing the implementation to pick an
// appropriate method for the resize. Can be increased to RESIZE_BETTER
diff --git a/chromium/third_party/blink/renderer/core/loader/threaded_icon_loader.h b/chromium/third_party/blink/renderer/core/loader/threaded_icon_loader.h
index 76697561842..2aa8f77e51d 100644
--- a/chromium/third_party/blink/renderer/core/loader/threaded_icon_loader.h
+++ b/chromium/third_party/blink/renderer/core/loader/threaded_icon_loader.h
@@ -17,7 +17,7 @@
namespace blink {
-class ResourceRequest;
+class ResourceRequestHead;
class SegmentReader;
// Utility class for loading, decoding, and potentially rescaling an icon on a
@@ -37,7 +37,7 @@ class CORE_EXPORT ThreadedIconLoader final
// If |resize_dimensions| is provided, the icon will will be downscaled to
// those dimensions.
void Start(ExecutionContext* execution_context,
- const ResourceRequest& resource_request,
+ const ResourceRequestHead& resource_request,
const base::Optional<gfx::Size>& resize_dimensions,
IconCallback callback);
diff --git a/chromium/third_party/blink/renderer/core/loader/threaded_icon_loader_test.cc b/chromium/third_party/blink/renderer/core/loader/threaded_icon_loader_test.cc
index 3963b6e9cbb..e4102f3c39f 100644
--- a/chromium/third_party/blink/renderer/core/loader/threaded_icon_loader_test.cc
+++ b/chromium/third_party/blink/renderer/core/loader/threaded_icon_loader_test.cc
@@ -60,7 +60,8 @@ class ThreadedIconLoaderTest : public PageTestBase {
double resize_scale;
base::RunLoop run_loop;
icon_loader->Start(
- GetDocument().ToExecutionContext(), resource_request, resize_dimensions,
+ GetDocument().GetExecutionContext(), resource_request,
+ resize_dimensions,
WTF::Bind(&ThreadedIconLoaderTest::DidGetIcon, WTF::Unretained(this),
run_loop.QuitClosure(), WTF::Unretained(&icon),
WTF::Unretained(&resize_scale)));
diff --git a/chromium/third_party/blink/renderer/core/loader/web_associated_url_loader_impl.cc b/chromium/third_party/blink/renderer/core/loader/web_associated_url_loader_impl.cc
index bf9f746de74..2df53f0f86f 100644
--- a/chromium/third_party/blink/renderer/core/loader/web_associated_url_loader_impl.cc
+++ b/chromium/third_party/blink/renderer/core/loader/web_associated_url_loader_impl.cc
@@ -48,7 +48,7 @@
#include "third_party/blink/public/platform/web_url_error.h"
#include "third_party/blink/public/platform/web_url_request.h"
#include "third_party/blink/public/web/web_associated_url_loader_client.h"
-#include "third_party/blink/renderer/core/dom/document.h"
+#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.h"
#include "third_party/blink/renderer/core/loader/threadable_loader.h"
#include "third_party/blink/renderer/core/loader/threadable_loader_client.h"
@@ -292,7 +292,7 @@ void WebAssociatedURLLoaderImpl::ClientAdapter::DidFail(
}
void WebAssociatedURLLoaderImpl::ClientAdapter::DidFailRedirectCheck() {
- DidFail(ResourceError::Failure(NullURL()));
+ DidFail(WebURLError(ResourceError::Failure(NullURL())));
}
void WebAssociatedURLLoaderImpl::ClientAdapter::EnableErrorNotifications() {
@@ -320,8 +320,8 @@ class WebAssociatedURLLoaderImpl::Observer final
USING_GARBAGE_COLLECTED_MIXIN(Observer);
public:
- Observer(WebAssociatedURLLoaderImpl* parent, Document* document)
- : ExecutionContextLifecycleObserver(document), parent_(parent) {}
+ Observer(WebAssociatedURLLoaderImpl* parent, ExecutionContext* context)
+ : ExecutionContextLifecycleObserver(context), parent_(parent) {}
void Dispose() {
parent_ = nullptr;
@@ -336,7 +336,7 @@ class WebAssociatedURLLoaderImpl::Observer final
void ContextDestroyed() override {
if (parent_)
- parent_->DocumentDestroyed();
+ parent_->ContextDestroyed();
}
void Trace(Visitor* visitor) override {
@@ -347,11 +347,11 @@ class WebAssociatedURLLoaderImpl::Observer final
};
WebAssociatedURLLoaderImpl::WebAssociatedURLLoaderImpl(
- Document* document,
+ ExecutionContext* context,
const WebAssociatedURLLoaderOptions& options)
: client_(nullptr),
options_(options),
- observer_(MakeGarbageCollected<Observer>(this, document)) {}
+ observer_(MakeGarbageCollected<Observer>(this, context)) {}
WebAssociatedURLLoaderImpl::~WebAssociatedURLLoaderImpl() {
Cancel();
@@ -395,12 +395,12 @@ void WebAssociatedURLLoaderImpl::LoadAsynchronously(
options_.preflight_policy);
scoped_refptr<base::SingleThreadTaskRunner> task_runner;
- // |observer_| can be null if Cancel, DocumentDestroyed or
+ // |observer_| can be null if Cancel, ContextDestroyed or
// ClientAdapterDone gets called between creating the loader and
// calling LoadAsynchronously.
if (observer_) {
- task_runner = Document::From(observer_->GetExecutionContext())
- ->GetTaskRunner(TaskType::kInternalLoading);
+ task_runner = observer_->GetExecutionContext()->GetTaskRunner(
+ TaskType::kInternalLoading);
} else {
task_runner = Thread::Current()->GetTaskRunner();
}
@@ -425,7 +425,7 @@ void WebAssociatedURLLoaderImpl::LoadAsynchronously(
new_request.ToMutableResourceRequest().SetRequestorOrigin(origin);
}
- const ResourceRequest& webcore_request = new_request.ToResourceRequest();
+ ResourceRequest& webcore_request = new_request.ToMutableResourceRequest();
mojom::RequestContextType context = webcore_request.GetRequestContext();
if (context == mojom::RequestContextType::UNSPECIFIED) {
// TODO(yoav): We load URLs without setting a TargetType (and therefore a
@@ -444,17 +444,17 @@ void WebAssociatedURLLoaderImpl::LoadAsynchronously(
}
if (observer_) {
- Document& document = Document::From(*observer_->GetExecutionContext());
loader_ = MakeGarbageCollected<ThreadableLoader>(
- *document.ToExecutionContext(), client_adapter_,
+ *observer_->GetExecutionContext(), client_adapter_,
resource_loader_options);
- loader_->Start(webcore_request);
+ loader_->Start(std::move(webcore_request));
}
}
if (!loader_) {
- client_adapter_->DidFail(ResourceError::CancelledDueToAccessCheckError(
- request.Url(), ResourceRequestBlockedReason::kOther));
+ client_adapter_->DidFail(
+ WebURLError(ResourceError::CancelledDueToAccessCheckError(
+ request.Url(), ResourceRequestBlockedReason::kOther)));
}
client_adapter_->EnableErrorNotifications();
}
@@ -494,14 +494,14 @@ void WebAssociatedURLLoaderImpl::SetLoadingTaskRunner(
// TODO(alexclarke): Maybe support this one day if it proves worthwhile.
}
-void WebAssociatedURLLoaderImpl::DocumentDestroyed() {
+void WebAssociatedURLLoaderImpl::ContextDestroyed() {
DisposeObserver();
CancelLoader();
if (!client_)
return;
- ReleaseClient()->DidFail(ResourceError::CancelledError(KURL()));
+ ReleaseClient()->DidFail(WebURLError(ResourceError::CancelledError(KURL())));
// |this| may be dead here.
}
diff --git a/chromium/third_party/blink/renderer/core/loader/web_associated_url_loader_impl.h b/chromium/third_party/blink/renderer/core/loader/web_associated_url_loader_impl.h
index 35b3e1183fe..d04f74acb5d 100644
--- a/chromium/third_party/blink/renderer/core/loader/web_associated_url_loader_impl.h
+++ b/chromium/third_party/blink/renderer/core/loader/web_associated_url_loader_impl.h
@@ -19,7 +19,7 @@ namespace blink {
class ThreadableLoader;
class WebAssociatedURLLoaderClient;
-class Document;
+class ExecutionContext;
// This class is used to implement WebFrame::createAssociatedURLLoader.
class CORE_EXPORT WebAssociatedURLLoaderImpl final
@@ -27,7 +27,8 @@ class CORE_EXPORT WebAssociatedURLLoaderImpl final
USING_FAST_MALLOC(WebAssociatedURLLoaderImpl);
public:
- WebAssociatedURLLoaderImpl(Document*, const WebAssociatedURLLoaderOptions&);
+ WebAssociatedURLLoaderImpl(ExecutionContext*,
+ const WebAssociatedURLLoaderOptions&);
~WebAssociatedURLLoaderImpl() override;
void LoadAsynchronously(const WebURLRequest&,
@@ -36,10 +37,6 @@ class CORE_EXPORT WebAssociatedURLLoaderImpl final
void SetDefersLoading(bool) override;
void SetLoadingTaskRunner(base::SingleThreadTaskRunner*) override;
- // Called by |observer_| to handle destruction of the Document associated
- // with the frame given to the constructor.
- void DocumentDestroyed();
-
// Called by ClientAdapter to handle completion of loading.
void ClientAdapterDone();
@@ -47,6 +44,7 @@ class CORE_EXPORT WebAssociatedURLLoaderImpl final
class ClientAdapter;
class Observer;
+ void ContextDestroyed();
void CancelLoader();
void DisposeObserver();
@@ -65,7 +63,7 @@ class CORE_EXPORT WebAssociatedURLLoaderImpl final
Persistent<ThreadableLoader> loader_;
// A ExecutionContextLifecycleObserver for cancelling |loader_| when the
- // Document is detached.
+ // context is detached.
Persistent<Observer> observer_;
DISALLOW_COPY_AND_ASSIGN(WebAssociatedURLLoaderImpl);
diff --git a/chromium/third_party/blink/renderer/core/loader/worker_fetch_context.cc b/chromium/third_party/blink/renderer/core/loader/worker_fetch_context.cc
index afa9b00db12..3d37ba03f5b 100644
--- a/chromium/third_party/blink/renderer/core/loader/worker_fetch_context.cc
+++ b/chromium/third_party/blink/renderer/core/loader/worker_fetch_context.cc
@@ -144,7 +144,8 @@ bool WorkerFetchContext::ShouldBlockFetchByMixedContentCheck(
mojom::RequestContextType request_context,
ResourceRequest::RedirectStatus redirect_status,
const KURL& url,
- ReportingDisposition reporting_disposition) const {
+ ReportingDisposition reporting_disposition,
+ const base::Optional<String>& devtools_id) const {
return MixedContentChecker::ShouldBlockFetchOnWorker(
*this, request_context, redirect_status, url, reporting_disposition,
global_scope_->IsWorkletGlobalScope());
@@ -242,6 +243,8 @@ void WorkerFetchContext::PopulateResourceRequest(
const ClientHintsPreferences& hints_preferences,
const FetchParameters::ResourceWidth& resource_width,
ResourceRequest& out_request) {
+ if (!GetResourceFetcherProperties().IsDetached())
+ probe::SetDevToolsIds(Probe(), out_request);
MixedContentChecker::UpgradeInsecureRequest(
out_request,
&GetResourceFetcherProperties().GetFetchClientSettingsObject(),
diff --git a/chromium/third_party/blink/renderer/core/loader/worker_fetch_context.h b/chromium/third_party/blink/renderer/core/loader/worker_fetch_context.h
index f7f18854f7c..0dcad4fa1e4 100644
--- a/chromium/third_party/blink/renderer/core/loader/worker_fetch_context.h
+++ b/chromium/third_party/blink/renderer/core/loader/worker_fetch_context.h
@@ -59,10 +59,12 @@ class WorkerFetchContext final : public BaseFetchContext {
bool ShouldBlockWebSocketByMixedContentCheck(const KURL&) const override;
std::unique_ptr<WebSocketHandshakeThrottle> CreateWebSocketHandshakeThrottle()
override;
- bool ShouldBlockFetchByMixedContentCheck(mojom::RequestContextType,
- ResourceRequest::RedirectStatus,
- const KURL&,
- ReportingDisposition) const override;
+ bool ShouldBlockFetchByMixedContentCheck(
+ mojom::blink::RequestContextType request_context,
+ ResourceRequest::RedirectStatus redirect_status,
+ const KURL& url,
+ ReportingDisposition reporting_disposition,
+ const base::Optional<String>& devtools_id) const override;
bool ShouldBlockFetchAsCredentialedSubresource(const ResourceRequest&,
const KURL&) const override;
const KURL& Url() const override;
diff --git a/chromium/third_party/blink/renderer/core/loader/worker_resource_fetcher_properties.cc b/chromium/third_party/blink/renderer/core/loader/worker_resource_fetcher_properties.cc
index 7f4051e5b04..ee0ce16266f 100644
--- a/chromium/third_party/blink/renderer/core/loader/worker_resource_fetcher_properties.cc
+++ b/chromium/third_party/blink/renderer/core/loader/worker_resource_fetcher_properties.cc
@@ -17,7 +17,9 @@ WorkerResourceFetcherProperties::WorkerResourceFetcherProperties(
scoped_refptr<WebWorkerFetchContext> web_context)
: global_scope_(global_scope),
fetch_client_settings_object_(fetch_client_settings_object),
- web_context_(std::move(web_context)) {
+ web_context_(std::move(web_context)),
+ outstanding_throttled_limit_(
+ global_scope_->GetOutstandingThrottledLimit()) {
DCHECK(web_context_);
}
@@ -40,4 +42,8 @@ const KURL& WorkerResourceFetcherProperties::WebBundlePhysicalUrl() const {
return NullURL();
}
+int WorkerResourceFetcherProperties::GetOutstandingThrottledLimit() const {
+ return outstanding_throttled_limit_;
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/loader/worker_resource_fetcher_properties.h b/chromium/third_party/blink/renderer/core/loader/worker_resource_fetcher_properties.h
index 06683d6e3df..9d9de5f8ae3 100644
--- a/chromium/third_party/blink/renderer/core/loader/worker_resource_fetcher_properties.h
+++ b/chromium/third_party/blink/renderer/core/loader/worker_resource_fetcher_properties.h
@@ -50,11 +50,13 @@ class WorkerResourceFetcherProperties final : public ResourceFetcherProperties {
return scheduler::FrameStatus::kNone;
}
const KURL& WebBundlePhysicalUrl() const override;
+ int GetOutstandingThrottledLimit() const override;
private:
const Member<WorkerOrWorkletGlobalScope> global_scope_;
const Member<const FetchClientSettingsObject> fetch_client_settings_object_;
const scoped_refptr<WebWorkerFetchContext> web_context_;
+ const int outstanding_throttled_limit_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/loader/worker_resource_timing_notifier_impl.cc b/chromium/third_party/blink/renderer/core/loader/worker_resource_timing_notifier_impl.cc
index b78c173ef0e..40ee616d1ee 100644
--- a/chromium/third_party/blink/renderer/core/loader/worker_resource_timing_notifier_impl.cc
+++ b/chromium/third_party/blink/renderer/core/loader/worker_resource_timing_notifier_impl.cc
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/core/loader/worker_resource_timing_notifier_impl.h"
#include <memory>
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/loader/cross_thread_resource_timing_info_copier.h"
#include "third_party/blink/renderer/core/timing/dom_window_performance.h"
#include "third_party/blink/renderer/core/timing/performance.h"
@@ -20,16 +21,11 @@ namespace {
Performance* GetPerformance(ExecutionContext& execution_context) {
DCHECK(execution_context.IsContextThread());
- if (execution_context.IsDocument()) {
- DCHECK(execution_context.ExecutingWindow());
- return DOMWindowPerformance::performance(
- *execution_context.ExecutingWindow());
- }
- if (execution_context.IsWorkerGlobalScope()) {
- return WorkerGlobalScopePerformance::performance(
- To<WorkerGlobalScope>(execution_context));
- }
- NOTREACHED() << "Unexpected execution context, it should be either Document "
+ if (auto* window = DynamicTo<LocalDOMWindow>(execution_context))
+ return DOMWindowPerformance::performance(*window);
+ if (auto* global_scope = DynamicTo<WorkerGlobalScope>(execution_context))
+ return WorkerGlobalScopePerformance::performance(*global_scope);
+ NOTREACHED() << "Unexpected execution context, it should be either Window "
"or WorkerGlobalScope";
return nullptr;
}
diff --git a/chromium/third_party/blink/renderer/core/mathml/BUILD.gn b/chromium/third_party/blink/renderer/core/mathml/BUILD.gn
index 2204ea93ce5..9a8efcacd2e 100644
--- a/chromium/third_party/blink/renderer/core/mathml/BUILD.gn
+++ b/chromium/third_party/blink/renderer/core/mathml/BUILD.gn
@@ -12,7 +12,11 @@ blink_core_sources("mathml") {
"mathml_fraction_element.h",
"mathml_row_element.cc",
"mathml_row_element.h",
+ "mathml_scripts_element.cc",
+ "mathml_scripts_element.h",
"mathml_space_element.cc",
"mathml_space_element.h",
+ "mathml_under_over_element.cc",
+ "mathml_under_over_element.h",
]
}
diff --git a/chromium/third_party/blink/renderer/core/mathml/mathml_attribute_names.json5 b/chromium/third_party/blink/renderer/core/mathml/mathml_attribute_names.json5
index 8d4a66622db..3e0704cca59 100644
--- a/chromium/third_party/blink/renderer/core/mathml/mathml_attribute_names.json5
+++ b/chromium/third_party/blink/renderer/core/mathml/mathml_attribute_names.json5
@@ -17,6 +17,7 @@
"mathbackground",
"mathcolor",
"mathsize",
+ "mathvariant",
"width",
],
}
diff --git a/chromium/third_party/blink/renderer/core/mathml/mathml_element.cc b/chromium/third_party/blink/renderer/core/mathml/mathml_element.cc
index 9e1a4254d27..a3460c2b2f0 100644
--- a/chromium/third_party/blink/renderer/core/mathml/mathml_element.cc
+++ b/chromium/third_party/blink/renderer/core/mathml/mathml_element.cc
@@ -38,6 +38,7 @@ bool MathMLElement::IsPresentationAttribute(const QualifiedName& name) const {
if (name == html_names::kDirAttr || name == mathml_names::kMathsizeAttr ||
name == mathml_names::kMathcolorAttr ||
name == mathml_names::kMathbackgroundAttr ||
+ name == mathml_names::kMathvariantAttr ||
name == mathml_names::kDisplayAttr ||
name == mathml_names::kDisplaystyleAttr)
return true;
@@ -87,6 +88,12 @@ void MathMLElement::CollectStyleForPresentationAttribute(
AddPropertyToPresentationAttributeStyle(style, CSSPropertyID::kMathStyle,
CSSValueID::kDisplay);
}
+ } else if (name == mathml_names::kMathvariantAttr) {
+ // TODO(crbug.com/1076420): this needs to handle all mathvariant values.
+ if (EqualIgnoringASCIICase(value, "normal")) {
+ AddPropertyToPresentationAttributeStyle(
+ style, CSSPropertyID::kTextTransform, CSSValueID::kNone);
+ }
} else {
Element::CollectStyleForPresentationAttribute(name, value, style);
}
diff --git a/chromium/third_party/blink/renderer/core/mathml/mathml_fraction_element.cc b/chromium/third_party/blink/renderer/core/mathml/mathml_fraction_element.cc
index ad316cdd671..74210ebc1f8 100644
--- a/chromium/third_party/blink/renderer/core/mathml/mathml_fraction_element.cc
+++ b/chromium/third_party/blink/renderer/core/mathml/mathml_fraction_element.cc
@@ -4,8 +4,7 @@
#include "third_party/blink/renderer/core/mathml/mathml_fraction_element.h"
-#include "third_party/blink/renderer/core/layout/ng/mathml/layout_ng_mathml_block.h"
-#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
+#include "third_party/blink/renderer/core/style/computed_style.h"
namespace blink {
@@ -20,13 +19,4 @@ void MathMLFractionElement::AddMathFractionBarThicknessIfNeeded(
style.SetMathFractionBarThickness(std::move(*length_or_percentage_value));
}
-LayoutObject* MathMLFractionElement::CreateLayoutObject(
- const ComputedStyle& style,
- LegacyLayout legacy) {
- if (!RuntimeEnabledFeatures::MathMLCoreEnabled() ||
- !style.IsDisplayMathType() || legacy == LegacyLayout::kForce)
- return MathMLElement::CreateLayoutObject(style, legacy);
- return new LayoutNGMathMLBlock(this);
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/mathml/mathml_fraction_element.h b/chromium/third_party/blink/renderer/core/mathml/mathml_fraction_element.h
index eac9e4e5d95..65b250cad05 100644
--- a/chromium/third_party/blink/renderer/core/mathml/mathml_fraction_element.h
+++ b/chromium/third_party/blink/renderer/core/mathml/mathml_fraction_element.h
@@ -11,7 +11,6 @@ namespace blink {
class ComputedStyle;
class CSSToLengthConversionData;
-class LayoutObject;
class MathMLFractionElement final : public MathMLElement {
public:
@@ -19,10 +18,6 @@ class MathMLFractionElement final : public MathMLElement {
void AddMathFractionBarThicknessIfNeeded(ComputedStyle&,
const CSSToLengthConversionData&);
-
- private:
- LayoutObject* CreateLayoutObject(const ComputedStyle&,
- LegacyLayout legacy) final;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/mathml/mathml_scripts_element.cc b/chromium/third_party/blink/renderer/core/mathml/mathml_scripts_element.cc
new file mode 100644
index 00000000000..d754a1d44ad
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/mathml/mathml_scripts_element.cc
@@ -0,0 +1,28 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/mathml/mathml_scripts_element.h"
+
+namespace blink {
+
+static MathScriptType ScriptTypeOf(const QualifiedName& tagName) {
+ if (tagName == mathml_names::kMsubTag)
+ return MathScriptType::kSub;
+ if (tagName == mathml_names::kMsupTag)
+ return MathScriptType::kSuper;
+ if (tagName == mathml_names::kMsubsupTag)
+ return MathScriptType::kSubSup;
+ if (tagName == mathml_names::kMunderTag)
+ return MathScriptType::kUnder;
+ if (tagName == mathml_names::kMoverTag)
+ return MathScriptType::kOver;
+ DCHECK(tagName == mathml_names::kMunderoverTag);
+ return MathScriptType::kUnderOver;
+}
+
+MathMLScriptsElement::MathMLScriptsElement(const QualifiedName& tagName,
+ Document& document)
+ : MathMLElement(tagName, document), script_type_(ScriptTypeOf(tagName)) {}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/mathml/mathml_scripts_element.h b/chromium/third_party/blink/renderer/core/mathml/mathml_scripts_element.h
new file mode 100644
index 00000000000..5ad049a123f
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/mathml/mathml_scripts_element.h
@@ -0,0 +1,48 @@
+// 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_CORE_MATHML_MATHML_SCRIPTS_ELEMENT_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_MATHML_MATHML_SCRIPTS_ELEMENT_H_
+
+#include "third_party/blink/renderer/core/mathml/mathml_element.h"
+
+namespace blink {
+
+class Document;
+
+enum class MathScriptType { kSub, kSuper, kSubSup, kUnder, kOver, kUnderOver };
+
+class CORE_EXPORT MathMLScriptsElement : public MathMLElement {
+ public:
+ MathScriptType GetScriptType() const { return script_type_; }
+
+ MathMLScriptsElement(const QualifiedName& tagName, Document& document);
+
+ private:
+ const MathScriptType script_type_;
+};
+
+template <>
+inline bool IsElementOfType<const MathMLScriptsElement>(const Node& node) {
+ return IsA<MathMLScriptsElement>(node);
+}
+template <>
+struct DowncastTraits<MathMLScriptsElement> {
+ static bool AllowFrom(const Node& node) {
+ auto* mathml_element = DynamicTo<MathMLElement>(node);
+ return mathml_element && AllowFrom(*mathml_element);
+ }
+ static bool AllowFrom(const MathMLElement& mathml_element) {
+ return mathml_element.HasTagName(mathml_names::kMunderTag) ||
+ mathml_element.HasTagName(mathml_names::kMoverTag) ||
+ mathml_element.HasTagName(mathml_names::kMunderoverTag) ||
+ mathml_element.HasTagName(mathml_names::kMsubTag) ||
+ mathml_element.HasTagName(mathml_names::kMsupTag) ||
+ mathml_element.HasTagName(mathml_names::kMsubsupTag);
+ }
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_MATHML_MATHML_SCRIPTS_ELEMENT_H_
diff --git a/chromium/third_party/blink/renderer/core/mathml/mathml_space_element.cc b/chromium/third_party/blink/renderer/core/mathml/mathml_space_element.cc
index 716fe389fb9..76f35589418 100644
--- a/chromium/third_party/blink/renderer/core/mathml/mathml_space_element.cc
+++ b/chromium/third_party/blink/renderer/core/mathml/mathml_space_element.cc
@@ -4,8 +4,7 @@
#include "third_party/blink/renderer/core/mathml/mathml_space_element.h"
-#include "third_party/blink/renderer/core/layout/ng/mathml/layout_ng_mathml_block.h"
-#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
+#include "third_party/blink/renderer/core/style/computed_style.h"
namespace blink {
@@ -54,12 +53,4 @@ void MathMLSpaceElement::CollectStyleForPresentationAttribute(
}
}
-LayoutObject* MathMLSpaceElement::CreateLayoutObject(const ComputedStyle& style,
- LegacyLayout legacy) {
- if (!RuntimeEnabledFeatures::MathMLCoreEnabled() ||
- !style.IsDisplayMathType() || legacy == LegacyLayout::kForce)
- return MathMLElement::CreateLayoutObject(style, legacy);
- return new LayoutNGMathMLBlock(this);
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/mathml/mathml_space_element.h b/chromium/third_party/blink/renderer/core/mathml/mathml_space_element.h
index 719e497324c..8038db6747f 100644
--- a/chromium/third_party/blink/renderer/core/mathml/mathml_space_element.h
+++ b/chromium/third_party/blink/renderer/core/mathml/mathml_space_element.h
@@ -9,7 +9,6 @@
namespace blink {
-class LayoutObject;
class ComputedStyle;
class CSSToLengthConversionData;
@@ -21,8 +20,6 @@ class MathMLSpaceElement final : public MathMLElement {
const CSSToLengthConversionData&);
private:
- LayoutObject* CreateLayoutObject(const ComputedStyle&,
- LegacyLayout legacy) override;
bool IsPresentationAttribute(const QualifiedName&) const override;
void CollectStyleForPresentationAttribute(
const QualifiedName&,
diff --git a/chromium/third_party/blink/renderer/core/mathml/mathml_tag_names.json5 b/chromium/third_party/blink/renderer/core/mathml/mathml_tag_names.json5
index 17fd2a6452f..d0f2d85cff2 100644
--- a/chromium/third_party/blink/renderer/core/mathml/mathml_tag_names.json5
+++ b/chromium/third_party/blink/renderer/core/mathml/mathml_tag_names.json5
@@ -40,6 +40,18 @@
interfaceName: "MathMLElement",
},
{
+ name: "msub",
+ interfaceName: "MathMLScriptsElement",
+ },
+ {
+ name: "msup",
+ interfaceName: "MathMLScriptsElement",
+ },
+ {
+ name: "msubsup",
+ interfaceName: "MathMLScriptsElement",
+ },
+ {
name: "mi",
interfaceName: "MathMLElement",
},
@@ -76,6 +88,18 @@
interfaceName: "MathMLElement",
},
{
+ name: "mover",
+ interfaceName: "MathMLUnderOverElement",
+ },
+ {
+ name: "munder",
+ interfaceName: "MathMLUnderOverElement",
+ },
+ {
+ name: "munderover",
+ interfaceName: "MathMLUnderOverElement",
+ },
+ {
name: "semantics",
interfaceName: "MathMLRowElement",
},
diff --git a/chromium/third_party/blink/renderer/core/mathml/mathml_under_over_element.cc b/chromium/third_party/blink/renderer/core/mathml/mathml_under_over_element.cc
new file mode 100644
index 00000000000..503503cc932
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/mathml/mathml_under_over_element.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/core/mathml/mathml_under_over_element.h"
+
+namespace blink {
+
+MathMLUnderOverElement::MathMLUnderOverElement(const QualifiedName& tagName,
+ Document& document)
+ : MathMLScriptsElement(tagName, document) {}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/mathml/mathml_under_over_element.h b/chromium/third_party/blink/renderer/core/mathml/mathml_under_over_element.h
new file mode 100644
index 00000000000..307767c40f9
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/mathml/mathml_under_over_element.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_CORE_MATHML_MATHML_UNDER_OVER_ELEMENT_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_MATHML_MATHML_UNDER_OVER_ELEMENT_H_
+
+#include "third_party/blink/renderer/core/mathml/mathml_scripts_element.h"
+
+namespace blink {
+
+class Document;
+
+class CORE_EXPORT MathMLUnderOverElement final : public MathMLScriptsElement {
+ public:
+ MathMLUnderOverElement(const QualifiedName& tagName, Document& document);
+};
+
+template <>
+inline bool IsElementOfType<const MathMLUnderOverElement>(const Node& node) {
+ return IsA<MathMLUnderOverElement>(node);
+}
+template <>
+struct DowncastTraits<MathMLUnderOverElement> {
+ static bool AllowFrom(const Node& node) {
+ auto* mathml_element = DynamicTo<MathMLElement>(node);
+ return mathml_element && AllowFrom(*mathml_element);
+ }
+ static bool AllowFrom(const MathMLElement& mathml_element) {
+ return mathml_element.HasTagName(mathml_names::kMunderTag) ||
+ mathml_element.HasTagName(mathml_names::kMoverTag) ||
+ mathml_element.HasTagName(mathml_names::kMunderoverTag);
+ }
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_MATHML_MATHML_UNDER_OVER_ELEMENT_H_
diff --git a/chromium/third_party/blink/renderer/core/messaging/blink_transferable_message_mojom_traits.cc b/chromium/third_party/blink/renderer/core/messaging/blink_transferable_message_mojom_traits.cc
index f501b5d0195..2c45c7441e8 100644
--- a/chromium/third_party/blink/renderer/core/messaging/blink_transferable_message_mojom_traits.cc
+++ b/chromium/third_party/blink/renderer/core/messaging/blink_transferable_message_mojom_traits.cc
@@ -31,8 +31,8 @@ bool StructTraits<blink::mojom::blink::TransferableMessage::DataView,
blink::BlinkTransferableMessage>::
Read(blink::mojom::blink::TransferableMessage::DataView data,
blink::BlinkTransferableMessage* out) {
- Vector<mojo::ScopedMessagePipeHandle> ports;
- Vector<mojo::ScopedMessagePipeHandle> stream_channels;
+ Vector<blink::MessagePortDescriptor> ports;
+ Vector<blink::MessagePortDescriptor> stream_channels;
blink::SerializedScriptValue::ArrayBufferContentsArray
array_buffer_contents_array;
Vector<SkBitmap> sk_bitmaps;
diff --git a/chromium/third_party/blink/renderer/core/messaging/blink_transferable_message_mojom_traits.h b/chromium/third_party/blink/renderer/core/messaging/blink_transferable_message_mojom_traits.h
index bff08e74f1a..cc49afca5e5 100644
--- a/chromium/third_party/blink/renderer/core/messaging/blink_transferable_message_mojom_traits.h
+++ b/chromium/third_party/blink/renderer/core/messaging/blink_transferable_message_mojom_traits.h
@@ -8,6 +8,8 @@
#include "mojo/public/cpp/bindings/array_traits_wtf_vector.h"
#include "skia/public/mojom/bitmap_skbitmap_mojom_traits.h"
#include "third_party/blink/public/common/messaging/message_port_channel.h"
+#include "third_party/blink/public/common/messaging/message_port_descriptor.h"
+#include "third_party/blink/public/common/messaging/message_port_descriptor_mojom_traits.h"
#include "third_party/blink/public/mojom/messaging/transferable_message.mojom-blink.h"
#include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h"
#include "third_party/blink/renderer/core/core_export.h"
@@ -25,18 +27,18 @@ struct CORE_EXPORT
return input;
}
- static Vector<mojo::ScopedMessagePipeHandle> ports(
+ static Vector<blink::MessagePortDescriptor> ports(
blink::BlinkTransferableMessage& input) {
- Vector<mojo::ScopedMessagePipeHandle> result;
+ Vector<blink::MessagePortDescriptor> result;
result.ReserveInitialCapacity(input.ports.size());
for (const auto& port : input.ports)
result.push_back(port.ReleaseHandle());
return result;
}
- static Vector<mojo::ScopedMessagePipeHandle> stream_channels(
+ static Vector<blink::MessagePortDescriptor> stream_channels(
blink::BlinkTransferableMessage& input) {
- Vector<mojo::ScopedMessagePipeHandle> result;
+ Vector<blink::MessagePortDescriptor> result;
auto& stream_channels = input.message->GetStreamChannels();
result.ReserveInitialCapacity(stream_channels.size());
for (const auto& port : stream_channels)
diff --git a/chromium/third_party/blink/renderer/core/messaging/message_channel.cc b/chromium/third_party/blink/renderer/core/messaging/message_channel.cc
index cc86ff2c95d..97f827e508a 100644
--- a/chromium/third_party/blink/renderer/core/messaging/message_channel.cc
+++ b/chromium/third_party/blink/renderer/core/messaging/message_channel.cc
@@ -26,6 +26,7 @@
#include "third_party/blink/renderer/core/messaging/message_channel.h"
+#include "third_party/blink/public/common/messaging/message_port_descriptor.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/core/messaging/message_port.h"
@@ -34,9 +35,9 @@ namespace blink {
MessageChannel::MessageChannel(ExecutionContext* context)
: port1_(MakeGarbageCollected<MessagePort>(*context)),
port2_(MakeGarbageCollected<MessagePort>(*context)) {
- mojo::MessagePipe pipe;
- port1_->Entangle(std::move(pipe.handle0));
- port2_->Entangle(std::move(pipe.handle1));
+ MessagePortDescriptorPair pipe;
+ port1_->Entangle(pipe.TakePort0());
+ port2_->Entangle(pipe.TakePort1());
}
void MessageChannel::Trace(Visitor* visitor) {
diff --git a/chromium/third_party/blink/renderer/core/messaging/message_port.cc b/chromium/third_party/blink/renderer/core/messaging/message_port.cc
index 3e71122bfbc..267fb73bf66 100644
--- a/chromium/third_party/blink/renderer/core/messaging/message_port.cc
+++ b/chromium/third_party/blink/renderer/core/messaging/message_port.cc
@@ -36,10 +36,13 @@
#include "third_party/blink/renderer/core/events/message_event.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/user_activation.h"
#include "third_party/blink/renderer/core/inspector/thread_debugger.h"
#include "third_party/blink/renderer/core/messaging/blink_transferable_message_mojom_traits.h"
#include "third_party/blink/renderer/core/workers/worker_global_scope.h"
+#include "third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.h"
+#include "third_party/blink/renderer/core/workers/worker_thread.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"
#include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
@@ -54,6 +57,11 @@ MessagePort::MessagePort(ExecutionContext& execution_context)
MessagePort::~MessagePort() {
DCHECK(!started_ || !IsEntangled());
+ if (!IsNeutered()) {
+ // Disentangle before teardown. The MessagePortDescriptor will blow up if it
+ // hasn't had its underlying handle returned to it before teardown.
+ Disentangle();
+ }
}
void MessagePort::postMessage(ScriptState* script_state,
@@ -121,9 +129,9 @@ void MessagePort::postMessage(ScriptState* script_state,
MessagePortChannel MessagePort::Disentangle() {
DCHECK(!IsNeutered());
- auto result = MessagePortChannel(connector_->PassMessagePipe());
+ port_.GiveDisentangledHandle(connector_->PassMessagePipe());
connector_ = nullptr;
- return result;
+ return MessagePortChannel(std::move(port_));
}
void MessagePort::start() {
@@ -145,19 +153,21 @@ void MessagePort::close() {
// A closed port should not be neutered, so rather than merely disconnecting
// from the mojo message pipe, also entangle with a new dangling message pipe.
if (!IsNeutered()) {
- connector_ = nullptr;
- Entangle(mojo::MessagePipe().handle0);
+ Disentangle().ReleaseHandle();
+ MessagePortDescriptorPair pipe;
+ Entangle(pipe.TakePort0());
}
closed_ = true;
}
-void MessagePort::Entangle(mojo::ScopedMessagePipeHandle handle) {
- // Only invoked to set our initial entanglement.
- DCHECK(handle.is_valid());
+void MessagePort::Entangle(MessagePortDescriptor port) {
+ DCHECK(port.IsValid());
DCHECK(!connector_);
- DCHECK(GetExecutionContext());
+
+ port_ = std::move(port);
connector_ = std::make_unique<mojo::Connector>(
- std::move(handle), mojo::Connector::SINGLE_THREADED_SEND, task_runner_);
+ port_.TakeHandleToEntangle(GetExecutionContext()),
+ mojo::Connector::SINGLE_THREADED_SEND, task_runner_);
connector_->PauseIncomingMethodCallProcessing();
connector_->set_incoming_receiver(this);
connector_->set_connection_error_handler(
diff --git a/chromium/third_party/blink/renderer/core/messaging/message_port.h b/chromium/third_party/blink/renderer/core/messaging/message_port.h
index d2480449994..0235fe07fb5 100644
--- a/chromium/third_party/blink/renderer/core/messaging/message_port.h
+++ b/chromium/third_party/blink/renderer/core/messaging/message_port.h
@@ -30,9 +30,11 @@
#include <memory>
#include "base/memory/scoped_refptr.h"
#include "base/single_thread_task_runner.h"
+#include "base/unguessable_token.h"
#include "mojo/public/cpp/bindings/connector.h"
#include "mojo/public/cpp/bindings/message.h"
#include "third_party/blink/public/common/messaging/message_port_channel.h"
+#include "third_party/blink/public/common/messaging/message_port_descriptor.h"
#include "third_party/blink/public/platform/web_vector.h"
#include "third_party/blink/renderer/bindings/core/v8/active_script_wrappable.h"
#include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h"
@@ -73,7 +75,7 @@ class CORE_EXPORT MessagePort : public EventTargetWithInlineData,
void start();
void close();
- void Entangle(mojo::ScopedMessagePipeHandle);
+ void Entangle(MessagePortDescriptor);
void Entangle(MessagePortChannel);
MessagePortChannel Disentangle();
@@ -143,6 +145,10 @@ class CORE_EXPORT MessagePort : public EventTargetWithInlineData,
bool closed_ = false;
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+
+ // The internal port owned by this class. The handle itself is moved into the
+ // |connector_| while entangled.
+ MessagePortDescriptor port_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.cc b/chromium/third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.cc
index cbef632e65e..9066cc0ccd5 100644
--- a/chromium/third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.cc
+++ b/chromium/third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.cc
@@ -15,6 +15,7 @@
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/fileapi/blob.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/html/canvas/canvas_async_blob_creator.h"
#include "third_party/blink/renderer/core/html/canvas/canvas_context_creation_attributes_core.h"
@@ -51,7 +52,7 @@ OffscreenCanvas::OffscreenCanvas(ExecutionContext* context, const IntSize& size)
if (context->IsDocument()) {
// If this OffscreenCanvas is being created in the context of a
// cross-origin iframe, it should prefer to use the low-power GPU.
- LocalFrame* frame = Document::From(context)->GetFrame();
+ LocalFrame* frame = To<LocalDOMWindow>(context)->GetFrame();
if (!(frame && frame->IsCrossOriginToMainFrame())) {
AllowHighPerformancePowerPreference();
}
@@ -105,8 +106,6 @@ void OffscreenCanvas::Dispose() {
context_->DetachHost();
context_ = nullptr;
}
-
- DeregisterFromAnimationFrameProvider();
}
void OffscreenCanvas::DeregisterFromAnimationFrameProvider() {
@@ -205,7 +204,7 @@ ImageBitmap* OffscreenCanvas::transferToImageBitmap(
ImageBitmap* image = context_->TransferToImageBitmap(script_state);
if (!image) {
- // Undocumented exception (not in spec)
+ // Undocumented exception (not in spec).
exception_state.ThrowDOMException(DOMExceptionCode::kUnknownError,
"ImageBitmap construction failed");
}
@@ -242,7 +241,6 @@ IntSize OffscreenCanvas::BitmapSourceSize() const {
ScriptPromise OffscreenCanvas::CreateImageBitmap(
ScriptState* script_state,
- EventTarget&,
base::Optional<IntRect> crop_rect,
const ImageBitmapOptions* options,
ExceptionState& exception_state) {
@@ -355,83 +353,77 @@ CanvasResourceDispatcher* OffscreenCanvas::GetOrCreateResourceDispatcher() {
}
CanvasResourceProvider* OffscreenCanvas::GetOrCreateResourceProvider() {
- if (!ResourceProvider()) {
- bool can_use_gpu = false;
- uint8_t presentation_mode =
- CanvasResourceProvider::kDefaultPresentationMode;
- if (Is3d()) {
- if (RuntimeEnabledFeatures::WebGLImageChromiumEnabled()) {
- presentation_mode |=
- CanvasResourceProvider::kAllowImageChromiumPresentationMode;
- }
- can_use_gpu = SharedGpuContext::IsGpuCompositingEnabled();
- } else {
- if (RuntimeEnabledFeatures::Canvas2dImageChromiumEnabled()) {
- presentation_mode |=
- CanvasResourceProvider::kAllowImageChromiumPresentationMode;
- }
- if (SharedGpuContext::IsGpuCompositingEnabled() &&
- RuntimeEnabledFeatures::Accelerated2dCanvasEnabled()) {
- can_use_gpu = true;
- }
- }
+ if (ResourceProvider())
+ return ResourceProvider();
+
+ std::unique_ptr<CanvasResourceProvider> provider;
+ IntSize surface_size(width(), height());
+ const bool can_use_gpu =
+ SharedGpuContext::IsGpuCompositingEnabled() &&
+ (Is3d() || RuntimeEnabledFeatures::Accelerated2dCanvasEnabled());
+ const bool composited_mode =
+ (Is3d() ? RuntimeEnabledFeatures::WebGLImageChromiumEnabled()
+ : RuntimeEnabledFeatures::Canvas2dImageChromiumEnabled());
+
+ // If this context has a placeholder, the resource needs to be optimized for
+ // displaying on screen. In the case we are hardware compositing, we also
+ // try to enable the usage of the image as scanout buffer (overlay).
+ uint32_t shared_image_usage_flags = 0u;
+ if (HasPlaceholderCanvas()) {
+ shared_image_usage_flags |= gpu::SHARED_IMAGE_USAGE_DISPLAY;
+ if (composited_mode)
+ shared_image_usage_flags |= gpu::SHARED_IMAGE_USAGE_SCANOUT;
+ }
- IntSize surface_size(width(), height());
- base::WeakPtr<CanvasResourceDispatcher> dispatcher_weakptr =
- HasPlaceholderCanvas() ? GetOrCreateResourceDispatcher()->GetWeakPtr()
- : nullptr;
- std::unique_ptr<CanvasResourceProvider> provider;
- // kAcceleratedCompositedResourceUsage and kSoftwareCompositedResourceUsage
- // still need to use the Create method for CanvasResourceProvider.
- // The former kAcceleratedResourceUsage and kSoftwareResourceUsage have been
- // replaced by two different constructors (one of sharedImage witt the
- // fallback to bitmap, and the other one to bitmap)
- // This is still WIP and more changes will come in upcoming CLs.
- if (can_use_gpu && HasPlaceholderCanvas()) {
- provider = CanvasResourceProvider::Create(
- surface_size,
- CanvasResourceProvider::ResourceUsage::
- kAcceleratedCompositedResourceUsage,
- SharedGpuContext::ContextProviderWrapper(), 0, FilterQuality(),
- context_->ColorParams(), presentation_mode,
- std::move(dispatcher_weakptr), false /*is_origin_top_left*/);
- } else if (!can_use_gpu && HasPlaceholderCanvas()) {
- provider = CanvasResourceProvider::Create(
- surface_size,
- CanvasResourceProvider::ResourceUsage::
- kSoftwareCompositedResourceUsage,
- SharedGpuContext::ContextProviderWrapper(), 0, FilterQuality(),
- context_->ColorParams(), presentation_mode,
- std::move(dispatcher_weakptr), false /*is_origin_top_left=*/);
- } else if (can_use_gpu) {
- provider = CanvasResourceProvider::CreateSharedImageProvider(
- surface_size, SharedGpuContext::ContextProviderWrapper(),
- FilterQuality(), context_->ColorParams(),
- false /*is_origin_top_left*/,
- CanvasResourceProvider::RasterMode::kGPU,
- 0u /*shared_image_usage_flags*/);
-
- } // else will try the BitmapProvider
-
- if (!provider) {
- provider = CanvasResourceProvider::CreateBitmapProvider(
- surface_size, FilterQuality(), context_->ColorParams());
- }
+ if (can_use_gpu) {
+ provider = CanvasResourceProvider::CreateSharedImageProvider(
+ surface_size, SharedGpuContext::ContextProviderWrapper(),
+ FilterQuality(), context_->ColorParams(), false /*is_origin_top_left*/,
+ CanvasResourceProvider::RasterMode::kGPU, shared_image_usage_flags);
+ } else if (HasPlaceholderCanvas() && composited_mode) {
+ // Only try a SoftwareComposited SharedImage if the context has Placeholder
+ // canvas and the composited mode is enabled.
+ provider = CanvasResourceProvider::CreateSharedImageProvider(
+ surface_size, SharedGpuContext::ContextProviderWrapper(),
+ FilterQuality(), context_->ColorParams(), false /*is_origin_top_left*/,
+ CanvasResourceProvider::RasterMode::kCPU, shared_image_usage_flags);
+ }
- ReplaceResourceProvider(std::move(provider));
+ if (!provider && HasPlaceholderCanvas()) {
+ // If this context has a Placerholder - which means that we have to display
+ // this resource - and the SharedImage Provider creation above failed, we
+ // try a SharedBitmap Provider before falling back to a Bitmap Provider.
+ base::WeakPtr<CanvasResourceDispatcher> dispatcher_weakptr =
+ GetOrCreateResourceDispatcher()->GetWeakPtr();
+ provider = CanvasResourceProvider::CreateSharedBitmapProvider(
+ surface_size, SharedGpuContext::ContextProviderWrapper(),
+ FilterQuality(), context_->ColorParams(),
+ std::move(dispatcher_weakptr));
+ }
- if (ResourceProvider() && ResourceProvider()->IsValid()) {
- base::UmaHistogramBoolean("Blink.Canvas.ResourceProviderIsAccelerated",
- ResourceProvider()->IsAccelerated());
- base::UmaHistogramEnumeration("Blink.Canvas.ResourceProviderType",
- ResourceProvider()->GetType());
- ResourceProvider()->Clear();
- DidDraw();
+ if (!provider) {
+ // If any of the above Create was able to create a valid provider, a
+ // BitmapProvider will be created here.
+ provider = CanvasResourceProvider::CreateBitmapProvider(
+ surface_size, FilterQuality(), context_->ColorParams());
+ }
- if (needs_matrix_clip_restore_) {
- needs_matrix_clip_restore_ = false;
- context_->RestoreCanvasMatrixClipStack(ResourceProvider()->Canvas());
- }
+ ReplaceResourceProvider(std::move(provider));
+
+ if (ResourceProvider() && ResourceProvider()->IsValid()) {
+ // todo(crbug/1064363) Add a separate UMA for Offscreen Canvas usage and
+ // understand if the if (ResourceProvider() &&
+ // ResourceProvider()->IsValid()) is really needed.
+ base::UmaHistogramBoolean("Blink.Canvas.ResourceProviderIsAccelerated",
+ ResourceProvider()->IsAccelerated());
+ base::UmaHistogramEnumeration("Blink.Canvas.ResourceProviderType",
+ ResourceProvider()->GetType());
+ ResourceProvider()->Clear();
+ DidDraw();
+
+ if (needs_matrix_clip_restore_) {
+ needs_matrix_clip_restore_ = false;
+ context_->RestoreCanvasMatrixClipStack(ResourceProvider()->Canvas());
}
}
return ResourceProvider();
@@ -500,8 +492,8 @@ bool OffscreenCanvas::ShouldAccelerate2dContext() const {
}
FontSelector* OffscreenCanvas::GetFontSelector() {
- if (auto* document = Document::DynamicFrom(GetExecutionContext())) {
- return document->GetStyleEngine().GetFontSelector();
+ if (auto* window = DynamicTo<LocalDOMWindow>(GetExecutionContext())) {
+ return window->document()->GetStyleEngine().GetFontSelector();
}
return To<WorkerGlobalScope>(GetExecutionContext())->GetFontSelector();
}
diff --git a/chromium/third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.h b/chromium/third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.h
index 1f0b8a53b59..2d535354ff7 100644
--- a/chromium/third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.h
+++ b/chromium/third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.h
@@ -153,7 +153,6 @@ class CORE_EXPORT OffscreenCanvas final
// ImageBitmapSource implementation
IntSize BitmapSourceSize() const final;
ScriptPromise CreateImageBitmap(ScriptState*,
- EventTarget&,
base::Optional<IntRect>,
const ImageBitmapOptions*,
ExceptionState&) final;
diff --git a/chromium/third_party/blink/renderer/core/origin_trials/origin_trial_context.cc b/chromium/third_party/blink/renderer/core/origin_trials/origin_trial_context.cc
index 37f0b2c2cfb..3a3e37569db 100644
--- a/chromium/third_party/blink/renderer/core/origin_trials/origin_trial_context.cc
+++ b/chromium/third_party/blink/renderer/core/origin_trials/origin_trial_context.cc
@@ -6,6 +6,7 @@
#include "base/metrics/histogram_macros.h"
#include "base/time/time.h"
+#include "services/network/public/cpp/features.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/common/origin_trials/trial_token.h"
#include "third_party/blink/public/common/origin_trials/trial_token_validator.h"
@@ -238,10 +239,10 @@ void OriginTrialContext::ActivateNavigationFeaturesFromInitiator(
void OriginTrialContext::InitializePendingFeatures() {
if (!enabled_features_.size() && !navigation_activated_features_.size())
return;
- auto* document = Document::DynamicFrom(context_.Get());
- if (!document)
+ auto* window = DynamicTo<LocalDOMWindow>(context_.Get());
+ if (!window)
return;
- LocalFrame* frame = document->GetFrame();
+ LocalFrame* frame = window->GetFrame();
if (!frame)
return;
ScriptState* script_state = ToScriptStateForMainWorld(frame);
@@ -332,20 +333,33 @@ bool OriginTrialContext::CanEnableTrialFromName(const StringView& trial_name) {
!base::FeatureList::IsEnabled(features::kPortals)) {
return false;
}
+ if (trial_name == "AppCache" &&
+ !base::FeatureList::IsEnabled(features::kAppCache)) {
+ return false;
+ }
+ if (trial_name == "TrustTokens" &&
+ !base::FeatureList::IsEnabled(network::features::kTrustTokens)) {
+ return false;
+ }
return true;
}
bool OriginTrialContext::EnableTrialFromName(const String& trial_name,
base::Time expiry_time) {
+ if (!CanEnableTrialFromName(trial_name)) {
+ DVLOG(1) << "EnableTrialFromName: cannot enable trial " << trial_name;
+ return false;
+ }
+
bool did_enable_feature = false;
for (OriginTrialFeature feature :
origin_trials::FeaturesForTrial(trial_name)) {
- if (!origin_trials::FeatureEnabledForOS(feature))
- continue;
-
- if (!CanEnableTrialFromName(trial_name))
+ if (!origin_trials::FeatureEnabledForOS(feature)) {
+ DVLOG(1) << "EnableTrialFromName: feature " << static_cast<int>(feature)
+ << " is disabled on current OS.";
continue;
+ }
did_enable_feature = true;
enabled_features_.insert(feature);
@@ -379,28 +393,29 @@ bool OriginTrialContext::EnableTrialFromToken(const SecurityOrigin* origin,
bool valid = false;
StringUTF8Adaptor token_string(token);
- std::string trial_name_str;
- base::Time expiry_time;
- OriginTrialTokenStatus token_result = trial_token_validator_->ValidateToken(
- token_string.AsStringPiece(), origin->ToUrlOrigin(), base::Time::Now(),
- &trial_name_str, &expiry_time);
- if (token_result == OriginTrialTokenStatus::kSuccess) {
- String trial_name =
- String::FromUTF8(trial_name_str.data(), trial_name_str.size());
+ TrialTokenResult token_result = trial_token_validator_->ValidateToken(
+ token_string.AsStringPiece(), origin->ToUrlOrigin(), base::Time::Now());
+ DVLOG(1) << "EnableTrialFromToken: token_result = "
+ << static_cast<int>(token_result.status) << ", token = " << token;
+
+ if (token_result.status == OriginTrialTokenStatus::kSuccess) {
+ String trial_name = String::FromUTF8(token_result.feature_name.data(),
+ token_result.feature_name.size());
if (origin_trials::IsTrialValid(trial_name)) {
// Origin trials are only enabled for secure origins. The only exception
// is for deprecation trials.
if (is_secure ||
origin_trials::IsTrialEnabledForInsecureContext(trial_name)) {
- valid = EnableTrialFromName(trial_name, expiry_time);
+ valid = EnableTrialFromName(trial_name, token_result.expiry_time);
} else {
// Insecure origin and trial is restricted to secure origins.
- token_result = OriginTrialTokenStatus::kInsecure;
+ DVLOG(1) << "EnableTrialFromToken: not secure";
+ token_result.status = OriginTrialTokenStatus::kInsecure;
}
}
}
- RecordTokenValidationResultHistogram(token_result);
+ RecordTokenValidationResultHistogram(token_result.status);
return valid;
}
diff --git a/chromium/third_party/blink/renderer/core/origin_trials/origin_trial_context_test.cc b/chromium/third_party/blink/renderer/core/origin_trials/origin_trial_context_test.cc
index 64061494a4b..bfa33fb28be 100644
--- a/chromium/third_party/blink/renderer/core/origin_trials/origin_trial_context_test.cc
+++ b/chromium/third_party/blink/renderer/core/origin_trials/origin_trial_context_test.cc
@@ -46,31 +46,25 @@ class MockTokenValidator : public TrialTokenValidator {
~MockTokenValidator() override = default;
// blink::WebTrialTokenValidator implementation
- OriginTrialTokenStatus ValidateToken(base::StringPiece token,
- const url::Origin& origin,
- base::Time current_time,
- std::string* feature_name,
- base::Time* expiry_time) const override {
+ TrialTokenResult ValidateToken(base::StringPiece token,
+ const url::Origin& origin,
+ base::Time current_time) const override {
call_count_++;
- *feature_name = feature_;
- *expiry_time = expiry_;
return response_;
}
// Useful methods for controlling the validator
- void SetResponse(OriginTrialTokenStatus response,
+ void SetResponse(OriginTrialTokenStatus status,
const std::string& feature,
base::Time expiry = base::Time()) {
- response_ = response;
- feature_ = feature;
- expiry_ = expiry;
+ response_.status = status;
+ response_.feature_name = feature;
+ response_.expiry_time = expiry;
}
int CallCount() { return call_count_; }
private:
- OriginTrialTokenStatus response_;
- std::string feature_;
- base::Time expiry_;
+ TrialTokenResult response_;
mutable int call_count_;
diff --git a/chromium/third_party/blink/renderer/core/origin_trials/origin_trials.h b/chromium/third_party/blink/renderer/core/origin_trials/origin_trials.h
index a2973300261..9d9b69d9c24 100644
--- a/chromium/third_party/blink/renderer/core/origin_trials/origin_trials.h
+++ b/chromium/third_party/blink/renderer/core/origin_trials/origin_trials.h
@@ -28,6 +28,10 @@ CORE_EXPORT bool IsTrialValid(const StringView& trial_name);
// Return true if |trial_name| can be enabled in an insecure context.
CORE_EXPORT bool IsTrialEnabledForInsecureContext(const StringView& trial_name);
+// Return true if |trial_name| can be enabled from third party origins.
+CORE_EXPORT bool IsTrialEnabledForThirdPartyOrigins(
+ const StringView& trial_name);
+
// Returns the trial type of the given |feature|.
CORE_EXPORT OriginTrialType GetTrialType(OriginTrialFeature feature);
diff --git a/chromium/third_party/blink/renderer/core/origin_trials/origin_trials_test.cc b/chromium/third_party/blink/renderer/core/origin_trials/origin_trials_test.cc
new file mode 100644
index 00000000000..bcba30e3f50
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/origin_trials/origin_trials_test.cc
@@ -0,0 +1,40 @@
+// 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/core/origin_trials/origin_trials.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
+
+namespace blink {
+namespace {
+
+const char kFrobulateTrialName[] = "Frobulate";
+const char kFrobulateDeprecationTrialName[] = "FrobulateDeprecation";
+const char kFrobulateThirdPartyTrialName[] = "FrobulateThirdParty";
+
+} // namespace
+
+TEST(OriginTrialTest, TrialsValid) {
+ EXPECT_TRUE(origin_trials::IsTrialValid(kFrobulateTrialName));
+ EXPECT_TRUE(origin_trials::IsTrialValid(kFrobulateThirdPartyTrialName));
+}
+
+TEST(OriginTrialTest, TrialEnabledForInsecureContext) {
+ EXPECT_FALSE(
+ origin_trials::IsTrialEnabledForInsecureContext(kFrobulateTrialName));
+ EXPECT_TRUE(origin_trials::IsTrialEnabledForInsecureContext(
+ kFrobulateDeprecationTrialName));
+ EXPECT_FALSE(origin_trials::IsTrialEnabledForInsecureContext(
+ kFrobulateThirdPartyTrialName));
+}
+
+TEST(OriginTrialTest, TrialsEnabledForThirdPartyOrigins) {
+ EXPECT_FALSE(
+ origin_trials::IsTrialEnabledForThirdPartyOrigins(kFrobulateTrialName));
+ EXPECT_TRUE(origin_trials::IsTrialEnabledForThirdPartyOrigins(
+ kFrobulateThirdPartyTrialName));
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/page/BUILD.gn b/chromium/third_party/blink/renderer/core/page/BUILD.gn
index b5c6f949729..42581ab6109 100644
--- a/chromium/third_party/blink/renderer/core/page/BUILD.gn
+++ b/chromium/third_party/blink/renderer/core/page/BUILD.gn
@@ -36,6 +36,8 @@ blink_core_sources("page") {
"frame_tree.h",
"link_highlight.cc",
"link_highlight.h",
+ "named_pages_mapper.cc",
+ "named_pages_mapper.h",
"page.cc",
"page.h",
"page_animator.cc",
@@ -47,8 +49,6 @@ blink_core_sources("page") {
"page_popup_client.h",
"page_popup_controller.cc",
"page_popup_controller.h",
- "page_popup_supplement.cc",
- "page_popup_supplement.h",
"page_visibility_observer.cc",
"page_visibility_observer.h",
"page_widget_delegate.cc",
diff --git a/chromium/third_party/blink/renderer/core/page/autoscroll_controller.cc b/chromium/third_party/blink/renderer/core/page/autoscroll_controller.cc
index aee12d467d5..03fef21a0df 100644
--- a/chromium/third_party/blink/renderer/core/page/autoscroll_controller.cc
+++ b/chromium/third_party/blink/renderer/core/page/autoscroll_controller.cc
@@ -323,7 +323,7 @@ void AutoscrollController::StopMiddleClickAutoscroll(LocalFrame* frame) {
page_->GetChromeClient().AutoscrollEnd(frame);
autoscroll_type_ = kNoAutoscroll;
page_->GetChromeClient().SetCursorOverridden(false);
- frame->LocalFrameRoot().GetEventHandler().ScheduleCursorUpdate();
+ frame->LocalFrameRoot().GetEventHandler().UpdateCursor();
autoscroll_layout_object_ = nullptr;
}
diff --git a/chromium/third_party/blink/renderer/core/page/autoscroll_controller_test.cc b/chromium/third_party/blink/renderer/core/page/autoscroll_controller_test.cc
index db8e230026a..247613a72a8 100644
--- a/chromium/third_party/blink/renderer/core/page/autoscroll_controller_test.cc
+++ b/chromium/third_party/blink/renderer/core/page/autoscroll_controller_test.cc
@@ -59,7 +59,7 @@ TEST_F(AutoscrollControllerTest,
DCHECK(scrollable);
DCHECK(scrollable->GetLayoutObject());
- WebMouseEvent event(WebInputEvent::kMouseDown, gfx::PointF(5, 5),
+ WebMouseEvent event(WebInputEvent::Type::kMouseDown, gfx::PointF(5, 5),
gfx::PointF(5, 5), WebPointerProperties::Button::kLeft, 0,
WebInputEvent::Modifiers::kLeftButtonDown,
base::TimeTicks::Now());
@@ -111,7 +111,7 @@ TEST_F(AutoscrollControllerTest, ContinueAutoscrollAfterMouseLeaveEvent) {
EXPECT_TRUE(controller.IsAutoscrolling());
- WebMouseEvent mouse_leave_event(WebInputEvent::kMouseLeave,
+ WebMouseEvent mouse_leave_event(WebInputEvent::Type::kMouseLeave,
WebInputEvent::kNoModifiers,
base::TimeTicks::Now());
mouse_leave_event.SetFrameScale(1);
@@ -153,7 +153,7 @@ TEST_F(AutoscrollControllerTest, StopAutoscrollOnResize) {
// possible
WebView().MainFrameWidget()->Resize(WebSize(840, 640));
- WebMouseEvent mouse_move_event(WebInputEvent::kMouseMove,
+ WebMouseEvent mouse_move_event(WebInputEvent::Type::kMouseMove,
WebInputEvent::kNoModifiers,
base::TimeTicks::Now());
@@ -166,7 +166,7 @@ TEST_F(AutoscrollControllerTest, StopAutoscrollOnResize) {
// again
WebView().MainFrameWidget()->Resize(WebSize(800, 600));
- WebMouseEvent mouse_move_event2(WebInputEvent::kMouseMove,
+ WebMouseEvent mouse_move_event2(WebInputEvent::Type::kMouseMove,
WebInputEvent::kNoModifiers,
base::TimeTicks::Now());
diff --git a/chromium/third_party/blink/renderer/core/page/chrome_client.cc b/chromium/third_party/blink/renderer/core/page/chrome_client.cc
index a7c3341161e..89d0c40a289 100644
--- a/chromium/third_party/blink/renderer/core/page/chrome_client.cc
+++ b/chromium/third_party/blink/renderer/core/page/chrome_client.cc
@@ -126,7 +126,7 @@ Page* ChromeClient::CreateWindow(
const FrameLoadRequest& r,
const AtomicString& frame_name,
const WebWindowFeatures& features,
- mojom::blink::WebSandboxFlags sandbox_flags,
+ network::mojom::blink::WebSandboxFlags sandbox_flags,
const FeaturePolicy::FeatureState& opener_feature_state,
const SessionStorageNamespaceId& session_storage_namespace_id) {
if (!CanOpenUIElementIfDuringPageDismissal(
@@ -278,7 +278,7 @@ bool ChromeClient::Print(LocalFrame* frame) {
}
if (frame->GetDocument()->IsSandboxed(
- mojom::blink::WebSandboxFlags::kModals)) {
+ network::mojom::blink::WebSandboxFlags::kModals)) {
UseCounter::Count(frame->GetDocument(),
WebFeature::kDialogInSandboxedContext);
frame->Console().AddMessage(MakeGarbageCollected<ConsoleMessage>(
diff --git a/chromium/third_party/blink/renderer/core/page/chrome_client.h b/chromium/third_party/blink/renderer/core/page/chrome_client.h
index e027493c721..8d4391d7d98 100644
--- a/chromium/third_party/blink/renderer/core/page/chrome_client.h
+++ b/chromium/third_party/blink/renderer/core/page/chrome_client.h
@@ -44,7 +44,6 @@
#include "third_party/blink/public/web/web_widget_client.h"
#include "third_party/blink/renderer/core/accessibility/ax_object_cache.h"
#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/core/frame/sandbox_flags.h"
#include "third_party/blink/renderer/core/html/forms/external_date_time_chooser.h"
#include "third_party/blink/renderer/core/html/forms/popup_menu.h"
#include "third_party/blink/renderer/core/layout/geometry/physical_offset.h"
@@ -201,7 +200,7 @@ class CORE_EXPORT ChromeClient : public GarbageCollected<ChromeClient> {
const FrameLoadRequest&,
const AtomicString& frame_name,
const WebWindowFeatures&,
- mojom::blink::WebSandboxFlags,
+ network::mojom::blink::WebSandboxFlags,
const FeaturePolicy::FeatureState&,
const SessionStorageNamespaceId&);
virtual void Show(NavigationPolicy) = 0;
@@ -484,15 +483,6 @@ class CORE_EXPORT ChromeClient : public GarbageCollected<ChromeClient> {
WTF::CrossThreadOnceFunction<void(WebSwapResult, base::TimeTicks)>;
virtual void NotifySwapTime(LocalFrame& frame, ReportTimeCallback callback) {}
- virtual void FallbackCursorModeLockCursor(LocalFrame* frame,
- bool left,
- bool right,
- bool up,
- bool down) = 0;
-
- virtual void FallbackCursorModeSetCursorVisibility(LocalFrame* frame,
- bool visible) = 0;
-
// Enable or disable BeginMainFrameNotExpected signals from the compositor of
// the local root of |frame|. These signals would be consumed by the blink
// scheduler.
@@ -510,6 +500,12 @@ class CORE_EXPORT ChromeClient : public GarbageCollected<ChromeClient> {
virtual void DocumentDetached(Document&) {}
+ // Return the user's zoom factor which is different from the typical usage
+ // of "zoom factor" in blink (e.g., |LocalFrame::PageZoomFactor()|) which
+ // includes CSS zoom and the device scale factor (if use-zoom-for-dsf is
+ // enabled). This only includes the zoom initiated by the user (ctrl +/-).
+ virtual double UserZoomFactor() const { return 1; }
+
protected:
ChromeClient() = default;
@@ -528,7 +524,7 @@ class CORE_EXPORT ChromeClient : public GarbageCollected<ChromeClient> {
const FrameLoadRequest&,
const AtomicString& frame_name,
const WebWindowFeatures&,
- mojom::blink::WebSandboxFlags,
+ network::mojom::blink::WebSandboxFlags,
const FeaturePolicy::FeatureState&,
const SessionStorageNamespaceId&) = 0;
diff --git a/chromium/third_party/blink/renderer/core/page/chrome_client_impl.cc b/chromium/third_party/blink/renderer/core/page/chrome_client_impl.cc
index 1b430137301..e4267ec821f 100644
--- a/chromium/third_party/blink/renderer/core/page/chrome_client_impl.cc
+++ b/chromium/third_party/blink/renderer/core/page/chrome_client_impl.cc
@@ -39,10 +39,10 @@
#include "build/build_config.h"
#include "cc/animation/animation_host.h"
#include "cc/layers/picture_layer.h"
+#include "third_party/blink/public/common/page/page_zoom.h"
#include "third_party/blink/public/mojom/input/focus_type.mojom-blink.h"
#include "third_party/blink/public/platform/web_float_rect.h"
#include "third_party/blink/public/platform/web_rect.h"
-#include "third_party/blink/public/platform/web_text_autosizer_page_info.h"
#include "third_party/blink/public/platform/web_url_request.h"
#include "third_party/blink/public/web/blink.h"
#include "third_party/blink/public/web/web_autofill_client.h"
@@ -251,7 +251,7 @@ Page* ChromeClientImpl::CreateWindowDelegate(
const FrameLoadRequest& r,
const AtomicString& name,
const WebWindowFeatures& features,
- mojom::blink::WebSandboxFlags sandbox_flags,
+ network::mojom::blink::WebSandboxFlags sandbox_flags,
const FeaturePolicy::FeatureState& opener_feature_state,
const SessionStorageNamespaceId& session_storage_namespace_id) {
if (!web_view_->Client())
@@ -268,8 +268,7 @@ Page* ChromeClientImpl::CreateWindowDelegate(
WebLocalFrameImpl::FromFrame(frame),
WrappedResourceRequest(r.GetResourceRequest()), features, frame_name,
static_cast<WebNavigationPolicy>(r.GetNavigationPolicy()),
- static_cast<mojom::blink::WebSandboxFlags>(sandbox_flags),
- opener_feature_state, session_storage_namespace_id));
+ sandbox_flags, opener_feature_state, session_storage_namespace_id));
if (!new_view)
return nullptr;
return new_view->GetPage();
@@ -436,8 +435,17 @@ IntRect ChromeClientImpl::ViewportToScreen(
if (client) {
client->ConvertViewportToWindow(&screen_rect);
WebRect view_rect = client->ViewRect();
- screen_rect.x += view_rect.x;
- screen_rect.y += view_rect.y;
+
+ base::CheckedNumeric<int> screen_rect_x = screen_rect.x;
+ base::CheckedNumeric<int> screen_rect_y = screen_rect.y;
+
+ screen_rect_x += view_rect.x;
+ screen_rect_y += view_rect.y;
+
+ screen_rect.x =
+ screen_rect_x.ValueOrDefault(std::numeric_limits<int>::max());
+ screen_rect.y =
+ screen_rect_y.ValueOrDefault(std::numeric_limits<int>::max());
}
return screen_rect;
@@ -728,21 +736,24 @@ void ChromeClientImpl::SetCursorOverridden(bool overridden) {
void ChromeClientImpl::AutoscrollStart(const gfx::PointF& viewport_point,
LocalFrame* local_frame) {
// TODO(dcheng): Why is this null check necessary?
- if (FrameWidget* widget = local_frame->GetWidgetForLocalRoot())
- widget->Client()->AutoscrollStart(viewport_point);
+ if (WebFrameWidgetBase* widget =
+ WebLocalFrameImpl::FromFrame(local_frame)->LocalRootFrameWidget())
+ widget->AutoscrollStart(viewport_point);
}
void ChromeClientImpl::AutoscrollFling(const gfx::Vector2dF& velocity,
LocalFrame* local_frame) {
// TODO(dcheng): Why is this null check necessary?
- if (FrameWidget* widget = local_frame->GetWidgetForLocalRoot())
- widget->Client()->AutoscrollFling(velocity);
+ if (WebFrameWidgetBase* widget =
+ WebLocalFrameImpl::FromFrame(local_frame)->LocalRootFrameWidget())
+ widget->AutoscrollFling(velocity);
}
void ChromeClientImpl::AutoscrollEnd(LocalFrame* local_frame) {
// TODO(dcheng): Why is this null check necessary?
- if (FrameWidget* widget = local_frame->GetWidgetForLocalRoot())
- widget->Client()->AutoscrollEnd();
+ if (WebFrameWidgetBase* widget =
+ WebLocalFrameImpl::FromFrame(local_frame)->LocalRootFrameWidget())
+ widget->AutoscrollEnd();
}
String ChromeClientImpl::AcceptLanguages() {
@@ -906,27 +917,6 @@ void ChromeClientImpl::NotifySwapTime(LocalFrame& frame,
base::NullCallback(), ConvertToBaseOnceCallback(std::move(callback)));
}
-void ChromeClientImpl::FallbackCursorModeLockCursor(LocalFrame* frame,
- bool left,
- bool right,
- bool up,
- bool down) {
- FrameWidget* widget = frame->GetWidgetForLocalRoot();
- if (!widget)
- return;
- if (WebWidgetClient* client = widget->Client())
- client->FallbackCursorModeLockCursor(left, right, up, down);
-}
-
-void ChromeClientImpl::FallbackCursorModeSetCursorVisibility(LocalFrame* frame,
- bool visible) {
- FrameWidget* widget = frame->GetWidgetForLocalRoot();
- if (!widget)
- return;
- if (WebWidgetClient* client = widget->Client())
- client->FallbackCursorModeSetCursorVisibility(visible);
-}
-
void ChromeClientImpl::RequestBeginMainFrameNotExpected(LocalFrame& frame,
bool request) {
frame.GetWidgetForLocalRoot()->RequestBeginMainFrameNotExpected(request);
@@ -966,21 +956,6 @@ void ChromeClientImpl::SetEventListenerProperties(
}
widget->SetEventListenerProperties(event_class, properties);
-
- WebWidgetClient* client = widget->Client();
- if (event_class == cc::EventListenerClass::kTouchStartOrMove ||
- event_class == cc::EventListenerClass::kTouchEndOrCancel) {
- client->SetHasTouchEventHandlers(
- widget->EventListenerProperties(
- cc::EventListenerClass::kTouchStartOrMove) !=
- cc::EventListenerProperties::kNone ||
- widget->EventListenerProperties(
- cc::EventListenerClass::kTouchEndOrCancel) !=
- cc::EventListenerProperties::kNone);
- } else if (event_class == cc::EventListenerClass::kPointerRawUpdate) {
- client->SetHasPointerRawUpdateEventHandlers(
- properties != cc::EventListenerProperties::kNone);
- }
}
cc::EventListenerProperties ChromeClientImpl::EventListenerProperties(
@@ -1244,7 +1219,7 @@ WebAutofillClient* ChromeClientImpl::AutofillClientFromFrame(
void ChromeClientImpl::DidUpdateTextAutosizerPageInfo(
const WebTextAutosizerPageInfo& page_info) {
- web_view_->Client()->DidUpdateTextAutosizerPageInfo(page_info);
+ web_view_->TextAutosizerPageInfoChanged(page_info);
}
void ChromeClientImpl::DocumentDetached(Document& document) {
@@ -1254,4 +1229,8 @@ void ChromeClientImpl::DocumentDetached(Document& document) {
}
}
+double ChromeClientImpl::UserZoomFactor() const {
+ return PageZoomLevelToZoomFactor(web_view_->ZoomLevel());
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/page/chrome_client_impl.h b/chromium/third_party/blink/renderer/core/page/chrome_client_impl.h
index ec816f101ca..85cb78cf795 100644
--- a/chromium/third_party/blink/renderer/core/page/chrome_client_impl.h
+++ b/chromium/third_party/blink/renderer/core/page/chrome_client_impl.h
@@ -87,7 +87,7 @@ class CORE_EXPORT ChromeClientImpl final : public ChromeClient {
const FrameLoadRequest&,
const AtomicString& name,
const WebWindowFeatures&,
- mojom::blink::WebSandboxFlags,
+ network::mojom::blink::WebSandboxFlags,
const FeaturePolicy::FeatureState&,
const SessionStorageNamespaceId&) override;
void Show(NavigationPolicy) override;
@@ -270,24 +270,18 @@ class CORE_EXPORT ChromeClientImpl final : public ChromeClient {
void NotifySwapTime(LocalFrame& frame, ReportTimeCallback callback) override;
- void FallbackCursorModeLockCursor(LocalFrame* frame,
- bool left,
- bool right,
- bool up,
- bool down) override;
-
- void FallbackCursorModeSetCursorVisibility(LocalFrame* frame,
- bool visible) override;
-
void RequestBeginMainFrameNotExpected(LocalFrame& frame,
bool request) override;
- int GetLayerTreeId(LocalFrame& frame) override;
+ void DidUpdateTextAutosizerPageInfo(
+ const WebTextAutosizerPageInfo& page_info) override;
- void DidUpdateTextAutosizerPageInfo(const WebTextAutosizerPageInfo&) override;
+ int GetLayerTreeId(LocalFrame& frame) override;
void DocumentDetached(Document&) override;
+ double UserZoomFactor() const override;
+
private:
bool IsChromeClientImpl() const override { return true; }
diff --git a/chromium/third_party/blink/renderer/core/page/chrome_client_impl_test.cc b/chromium/third_party/blink/renderer/core/page/chrome_client_impl_test.cc
index 5eedac92db9..efc5c45929e 100644
--- a/chromium/third_party/blink/renderer/core/page/chrome_client_impl_test.cc
+++ b/chromium/third_party/blink/renderer/core/page/chrome_client_impl_test.cc
@@ -31,6 +31,7 @@
#include "third_party/blink/renderer/core/page/chrome_client_impl.h"
#include "base/run_loop.h"
#include "cc/trees/layer_tree_host.h"
+#include "services/network/public/mojom/web_sandbox_flags.mojom-blink.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/feature_policy/feature_policy.h"
#include "third_party/blink/public/common/input/web_input_event.h"
@@ -63,7 +64,7 @@ class ViewCreatingClient : public frame_test_helpers::TestWebViewClient {
const WebWindowFeatures&,
const WebString& name,
WebNavigationPolicy,
- mojom::blink::WebSandboxFlags,
+ network::mojom::blink::WebSandboxFlags,
const FeaturePolicy::FeatureState&,
const SessionStorageNamespaceId&) override {
return web_view_helper_.InitializeWithOpener(opener);
@@ -97,7 +98,7 @@ TEST_F(CreateWindowTest, CreateWindowFromPausedPage) {
WebWindowFeatures features;
EXPECT_EQ(nullptr, chrome_client_impl_->CreateWindow(
frame, request, "", features,
- mojom::blink::WebSandboxFlags::kNone,
+ network::mojom::blink::WebSandboxFlags::kNone,
FeaturePolicy::FeatureState(), ""));
}
diff --git a/chromium/third_party/blink/renderer/core/page/color_page_popup_controller.cc b/chromium/third_party/blink/renderer/core/page/color_page_popup_controller.cc
index 13d064d6b8a..1761920ee9c 100644
--- a/chromium/third_party/blink/renderer/core/page/color_page_popup_controller.cc
+++ b/chromium/third_party/blink/renderer/core/page/color_page_popup_controller.cc
@@ -12,9 +12,10 @@
namespace blink {
ColorPagePopupController::ColorPagePopupController(
+ Page& page,
PagePopup& popup,
ColorChooserPopupUIController* client)
- : PagePopupController(popup, client) {}
+ : PagePopupController(page, popup, client) {}
void ColorPagePopupController::openEyeDropper() {
if (popup_client_) {
diff --git a/chromium/third_party/blink/renderer/core/page/color_page_popup_controller.h b/chromium/third_party/blink/renderer/core/page/color_page_popup_controller.h
index 369d5e8f732..27cdbbcde2c 100644
--- a/chromium/third_party/blink/renderer/core/page/color_page_popup_controller.h
+++ b/chromium/third_party/blink/renderer/core/page/color_page_popup_controller.h
@@ -10,13 +10,14 @@
namespace blink {
class ColorChooserPopupUIController;
+class Page;
class PagePopup;
class ColorPagePopupController final : public PagePopupController {
DEFINE_WRAPPERTYPEINFO();
public:
- ColorPagePopupController(PagePopup&, ColorChooserPopupUIController*);
+ ColorPagePopupController(Page&, PagePopup&, ColorChooserPopupUIController*);
void openEyeDropper();
};
diff --git a/chromium/third_party/blink/renderer/core/page/context_menu_controller_test.cc b/chromium/third_party/blink/renderer/core/page/context_menu_controller_test.cc
index 31f1dfab525..00395b45856 100644
--- a/chromium/third_party/blink/renderer/core/page/context_menu_controller_test.cc
+++ b/chromium/third_party/blink/renderer/core/page/context_menu_controller_test.cc
@@ -563,11 +563,11 @@ TEST_F(ContextMenuControllerTest, ShowNonLocatedContextMenuEvent) {
// Select the 'Sample' of |input|.
DOMRect* rect = input_element->getBoundingClientRect();
WebGestureEvent gesture_event(
- WebInputEvent::kGestureLongPress, WebInputEvent::kNoModifiers,
+ WebInputEvent::Type::kGestureLongPress, WebInputEvent::kNoModifiers,
base::TimeTicks::Now(), WebGestureDevice::kTouchscreen);
gesture_event.SetPositionInWidget(gfx::PointF(rect->left(), rect->top()));
GetWebView()->MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(gesture_event));
+ WebCoalescedInputEvent(gesture_event, ui::LatencyInfo()));
WebContextMenuData context_menu_data =
GetWebFrameClient().GetContextMenuData();
@@ -608,11 +608,11 @@ TEST_F(ContextMenuControllerTest, SelectionRectClipped) {
// Select the 'Sample' of |textarea|.
DOMRect* rect = editable_element->getBoundingClientRect();
WebGestureEvent gesture_event(
- WebInputEvent::kGestureLongPress, WebInputEvent::kNoModifiers,
+ WebInputEvent::Type::kGestureLongPress, WebInputEvent::kNoModifiers,
base::TimeTicks::Now(), WebGestureDevice::kTouchscreen);
gesture_event.SetPositionInWidget(gfx::PointF(rect->left(), rect->top()));
GetWebView()->MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(gesture_event));
+ WebCoalescedInputEvent(gesture_event, ui::LatencyInfo()));
WebContextMenuData context_menu_data =
GetWebFrameClient().GetContextMenuData();
diff --git a/chromium/third_party/blink/renderer/core/page/create_window.cc b/chromium/third_party/blink/renderer/core/page/create_window.cc
index 79b3084588f..4c24bcbf3d1 100644
--- a/chromium/third_party/blink/renderer/core/page/create_window.cc
+++ b/chromium/third_party/blink/renderer/core/page/create_window.cc
@@ -41,6 +41,7 @@
#include "third_party/blink/renderer/core/frame/ad_tracker.h"
#include "third_party/blink/renderer/core/frame/csp/content_security_policy.h"
#include "third_party/blink/renderer/core/frame/frame_client.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/local_frame_client.h"
#include "third_party/blink/renderer/core/inspector/console_message.h"
@@ -242,13 +243,12 @@ Frame* CreateNewWindow(LocalFrame& opener_frame,
const KURL& url = request.GetResourceRequest().Url();
if (url.ProtocolIsJavaScript() &&
- opener_frame.GetDocument()->GetContentSecurityPolicy() &&
- !ContentSecurityPolicy::ShouldBypassMainWorld(
- opener_frame.GetDocument()->ToExecutionContext())) {
+ opener_frame.DomWindow()->GetContentSecurityPolicy() &&
+ !ContentSecurityPolicy::ShouldBypassMainWorld(opener_frame.DomWindow())) {
String script_source = DecodeURLEscapeSequences(
url.GetString(), DecodeURLMode::kUTF8OrIsomorphic);
- if (!opener_frame.GetDocument()->GetContentSecurityPolicy()->AllowInline(
+ if (!opener_frame.DomWindow()->GetContentSecurityPolicy()->AllowInline(
ContentSecurityPolicy::InlineType::kNavigation,
nullptr /* element */, script_source, String() /* nonce */,
opener_frame.GetDocument()->Url(), OrdinalNumber())) {
@@ -272,7 +272,7 @@ Frame* CreateNewWindow(LocalFrame& opener_frame,
// Sandboxed frames cannot open new auxiliary browsing contexts.
if (opener_frame.GetDocument()->IsSandboxed(
- mojom::blink::WebSandboxFlags::kPopups)) {
+ network::mojom::blink::WebSandboxFlags::kPopups)) {
// FIXME: This message should be moved off the console once a solution to
// https://bugs.webkit.org/show_bug.cgi?id=103274 exists.
opener_frame.GetDocument()->AddConsoleMessage(
@@ -286,12 +286,13 @@ Frame* CreateNewWindow(LocalFrame& opener_frame,
}
bool propagate_sandbox = opener_frame.GetDocument()->IsSandboxed(
- mojom::blink::WebSandboxFlags::kPropagatesToAuxiliaryBrowsingContexts);
- const SandboxFlags sandbox_flags =
+ network::mojom::blink::WebSandboxFlags::
+ kPropagatesToAuxiliaryBrowsingContexts);
+ network::mojom::blink::WebSandboxFlags sandbox_flags =
propagate_sandbox ? opener_frame.GetDocument()->GetSandboxFlags()
- : mojom::blink::WebSandboxFlags::kNone;
+ : network::mojom::blink::WebSandboxFlags::kNone;
bool not_sandboxed = opener_frame.GetDocument()->GetSandboxFlags() ==
- mojom::blink::WebSandboxFlags::kNone;
+ network::mojom::blink::WebSandboxFlags::kNone;
FeaturePolicy::FeatureState opener_feature_state =
(not_sandboxed || propagate_sandbox) ? opener_frame.GetSecurityContext()
->GetFeaturePolicy()
diff --git a/chromium/third_party/blink/renderer/core/page/drag_controller.cc b/chromium/third_party/blink/renderer/core/page/drag_controller.cc
index 8d49321e25e..0673abb855e 100644
--- a/chromium/third_party/blink/renderer/core/page/drag_controller.cc
+++ b/chromium/third_party/blink/renderer/core/page/drag_controller.cc
@@ -122,7 +122,7 @@ static bool DragTypeIsValid(DragSourceAction action) {
static WebMouseEvent CreateMouseEvent(DragData* drag_data) {
WebMouseEvent result(
- WebInputEvent::kMouseMove, drag_data->ClientPosition(),
+ WebInputEvent::Type::kMouseMove, drag_data->ClientPosition(),
drag_data->GlobalPosition(), WebPointerProperties::Button::kLeft, 0,
static_cast<WebInputEvent::Modifiers>(drag_data->GetModifiers()),
base::TimeTicks::Now());
@@ -301,6 +301,11 @@ void DragController::PerformDrag(DragData* drag_data, LocalFrame& local_root) {
resource_request.SetRequestorOrigin(SecurityOrigin::CreateUniqueOpaque());
FrameLoadRequest request(nullptr, resource_request);
+
+ // Open the dropped URL in a new tab to avoid potential data-loss in the
+ // current tab. See https://crbug.com/451659.
+ request.SetNavigationPolicy(
+ NavigationPolicy::kNavigationPolicyNewForegroundTab);
page_->MainFrame()->Navigate(request, WebFrameLoadType::kStandard);
}
@@ -996,7 +1001,7 @@ bool DragController::PopulateDragDataTransfer(LocalFrame* src,
// Observe context related to source to allow dropping drag_state_ when the
// Document goes away.
- SetExecutionContext(src->GetDocument()->ToExecutionContext());
+ SetExecutionContext(src->DomWindow());
return true;
}
@@ -1301,7 +1306,7 @@ void DragController::DoSystemDrag(DragImage* image,
bool for_link) {
did_initiate_drag_ = true;
drag_initiator_ = frame->GetDocument();
- SetExecutionContext(drag_initiator_->ToExecutionContext());
+ SetExecutionContext(frame->DomWindow());
// TODO(pdr): |drag_location| and |event_pos| should be passed in as
// FloatPoints and we should calculate these adjusted values in floating
diff --git a/chromium/third_party/blink/renderer/core/page/drag_controller_test.cc b/chromium/third_party/blink/renderer/core/page/drag_controller_test.cc
index 0339a64e275..ae265dbedf1 100644
--- a/chromium/third_party/blink/renderer/core/page/drag_controller_test.cc
+++ b/chromium/third_party/blink/renderer/core/page/drag_controller_test.cc
@@ -407,7 +407,7 @@ TEST_F(DragControllerTest, DragImageOffsetWithPageScaleFactor) {
GetFrame().GetPage()->SetPageScaleFactor(page_scale_factor);
GetFrame().Selection().SelectAll();
- WebMouseEvent mouse_event(WebInputEvent::kMouseDown,
+ WebMouseEvent mouse_event(WebInputEvent::Type::kMouseDown,
WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests());
mouse_event.button = WebMouseEvent::Button::kRight;
@@ -452,7 +452,7 @@ TEST_F(DragControllerTest, DragLinkWithPageScaleFactor) {
GetFrame().GetPage()->SetPageScaleFactor(page_scale_factor);
GetFrame().Selection().SelectAll();
- WebMouseEvent mouse_event(WebInputEvent::kMouseDown,
+ WebMouseEvent mouse_event(WebInputEvent::Type::kMouseDown,
WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests());
mouse_event.button = WebMouseEvent::Button::kRight;
diff --git a/chromium/third_party/blink/renderer/core/page/focus_controller.cc b/chromium/third_party/blink/renderer/core/page/focus_controller.cc
index 225ff4339c3..dc65fa82354 100644
--- a/chromium/third_party/blink/renderer/core/page/focus_controller.cc
+++ b/chromium/third_party/blink/renderer/core/page/focus_controller.cc
@@ -961,6 +961,8 @@ bool FocusController::AdvanceFocus(
mojom::blink::FocusType type,
bool initial_focus,
InputDeviceCapabilities* source_capabilities) {
+ // TODO (liviutinta) remove TRACE after fixing crbug.com/1063548
+ TRACE_EVENT0("input", "FocusController::AdvanceFocus");
switch (type) {
case mojom::blink::FocusType::kForward:
case mojom::blink::FocusType::kBackward: {
@@ -1016,6 +1018,8 @@ bool FocusController::AdvanceFocusInDocumentOrder(
mojom::blink::FocusType type,
bool initial_focus,
InputDeviceCapabilities* source_capabilities) {
+ // TODO (liviutinta) remove TRACE after fixing crbug.com/1063548
+ TRACE_EVENT0("input", "FocusController::AdvanceFocusInDocumentOrder");
DCHECK(frame);
Document* document = frame->GetDocument();
document->UpdateDistributionForLegacyDistributedNodes();
@@ -1063,8 +1067,14 @@ bool FocusController::AdvanceFocusInDocumentOrder(
element = FindFocusableElementDescendingDownIntoFrameDocument(type, element,
owner_map);
- if (!element)
+ if (!element) {
+ // TODO (liviutinta) remove TRACE after fixing crbug.com/1063548
+ TRACE_EVENT_INSTANT1(
+ "input", "FocusController::AdvanceFocusInDocumentOrder",
+ TRACE_EVENT_SCOPE_THREAD, "reason_for_no_focus_element",
+ "no_recursive_focusable_element");
return false;
+ }
}
if (element == document->FocusedElement()) {
@@ -1093,8 +1103,14 @@ bool FocusController::AdvanceFocusInDocumentOrder(
!element->IsKeyboardFocusable())) {
// FIXME: We should not focus frames that have no scrollbars, as focusing
// them isn't useful to the user.
- if (!owner->ContentFrame())
+ if (!owner->ContentFrame()) {
+ // TODO (liviutinta) remove TRACE after fixing crbug.com/1063548
+ TRACE_EVENT_INSTANT1(
+ "input", "FocusController::AdvanceFocusInDocumentOrder",
+ TRACE_EVENT_SCOPE_THREAD, "reason_for_no_focus_element",
+ "portal blocks focus");
return false;
+ }
document->ClearFocusedElement();
@@ -1335,7 +1351,12 @@ void FocusController::RegisterFocusChangedObserver(
}
void FocusController::NotifyFocusChangedObservers() const {
- for (const auto& it : focus_changed_observers_)
+ // Since this eventually dispatches an event to the page, the page could add
+ // new observer, which would invalidate our iterators; so iterate over a copy
+ // of the observer list.
+ HeapHashSet<WeakMember<FocusChangedObserver>> observers =
+ focus_changed_observers_;
+ for (const auto& it : observers)
it->FocusedFrameChanged();
}
diff --git a/chromium/third_party/blink/renderer/core/page/named_pages_mapper.cc b/chromium/third_party/blink/renderer/core/page/named_pages_mapper.cc
new file mode 100644
index 00000000000..7a000869f81
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/page/named_pages_mapper.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/core/page/named_pages_mapper.h"
+
+namespace blink {
+
+void NamedPagesMapper::AddNamedPage(const AtomicString& page_name,
+ int page_index) {
+ DCHECK_GE(entries_.size(), 1u);
+
+ // The last entry should have no last page set.
+ DCHECK_EQ(entries_.back().last_page_index, -1);
+
+ if (page_index > 0) {
+ auto prev_it = entries_.rbegin();
+ for (auto it = prev_it + 1; it != entries_.rend(); prev_it = it++) {
+ if (it->last_page_index < page_index)
+ break;
+ }
+
+ entries_.Shrink(entries_.rend() - prev_it);
+
+ // Terminate the previous entry (now that we know its last page index)
+ // before adding the new entry.
+ entries_.back().last_page_index = page_index - 1;
+ } else {
+ DCHECK_EQ(page_index, 0);
+ entries_.Shrink(0);
+ }
+ entries_.emplace_back(page_name);
+}
+
+const AtomicString& NamedPagesMapper::NamedPageAtIndex(int page_index) const {
+ for (const Entry& entry : entries_) {
+ if (page_index <= entry.last_page_index)
+ return entry.page_name;
+ }
+ return entries_.back().page_name;
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/page/named_pages_mapper.h b/chromium/third_party/blink/renderer/core/page/named_pages_mapper.h
new file mode 100644
index 00000000000..ec244e81006
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/page/named_pages_mapper.h
@@ -0,0 +1,56 @@
+// 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_CORE_PAGE_NAMED_PAGES_MAPPER_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_PAGE_NAMED_PAGES_MAPPER_H_
+
+#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
+#include "third_party/blink/renderer/platform/wtf/vector.h"
+
+namespace blink {
+
+// Mapper from page number to page name [1]. To be populated during paginated
+// layout, and consulted when sending pages to the printing / PDF system. This
+// can be used to provide page-specific properties, such as margins, size and
+// orientation.
+//
+// A page name is represented by a string. Page names are case-sensitive. The
+// initial 'page' value 'auto' is represented by an empty string.
+//
+// [1] https://www.w3.org/TR/css-page-3/#using-named-pages
+class CORE_EXPORT NamedPagesMapper {
+ public:
+ // We start by inserting an unnamed ('auto') entry with indefinite page
+ // count. In documents with no named pages at all, this is all we'll
+ // get. Otherwise, subsequent calls to AddNamedPage() will terminate (or even
+ // overwrite, if we add a named page at page index 0) the unnamed page run.
+ NamedPagesMapper() { entries_.emplace_back(AtomicString()); }
+
+ // Add an entry for a given page name. If the specified page index is lower
+ // than the number of pages we already have, the entries after this will be
+ // deleted.
+ void AddNamedPage(const AtomicString& page_name, int page_index);
+
+ const AtomicString& LastPageName() const { return entries_.back().page_name; }
+ const AtomicString& NamedPageAtIndex(int page_index) const;
+
+ private:
+ // An entry of contiguous pages with the same name.
+ struct Entry {
+ explicit Entry(const AtomicString& page_name) : page_name(page_name) {}
+
+ AtomicString page_name;
+
+ // The last page that this entry applies for. -1 means that it applies to
+ // all remaining pages. -1 is only allowed in the last entry.
+ int last_page_index = -1;
+ };
+
+ Vector<Entry, 1> entries_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_PAGE_NAMED_PAGES_MAPPER_H_
diff --git a/chromium/third_party/blink/renderer/core/page/named_pages_mapper_test.cc b/chromium/third_party/blink/renderer/core/page/named_pages_mapper_test.cc
new file mode 100644
index 00000000000..566eebf9d65
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/page/named_pages_mapper_test.cc
@@ -0,0 +1,125 @@
+// 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/core/page/named_pages_mapper.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace blink {
+namespace {
+
+TEST(NamedPagesMapperTest, Test) {
+ NamedPagesMapper mapper;
+ EXPECT_EQ(mapper.LastPageName(), AtomicString());
+ EXPECT_EQ(mapper.NamedPageAtIndex(0), AtomicString());
+ EXPECT_EQ(mapper.NamedPageAtIndex(100), AtomicString());
+
+ mapper.AddNamedPage("foo", 7);
+ EXPECT_EQ(mapper.LastPageName(), "foo");
+ EXPECT_EQ(mapper.NamedPageAtIndex(7), "foo");
+ EXPECT_EQ(mapper.NamedPageAtIndex(6), AtomicString());
+ EXPECT_EQ(mapper.NamedPageAtIndex(100), "foo");
+
+ mapper.AddNamedPage("bar", 8);
+ EXPECT_EQ(mapper.LastPageName(), "bar");
+ EXPECT_EQ(mapper.NamedPageAtIndex(8), "bar");
+ EXPECT_EQ(mapper.NamedPageAtIndex(7), "foo");
+ EXPECT_EQ(mapper.NamedPageAtIndex(6), AtomicString());
+ EXPECT_EQ(mapper.NamedPageAtIndex(100), "bar");
+
+ mapper.AddNamedPage("foo", 10);
+ EXPECT_EQ(mapper.LastPageName(), "foo");
+ EXPECT_EQ(mapper.NamedPageAtIndex(10), "foo");
+ EXPECT_EQ(mapper.NamedPageAtIndex(9), "bar");
+ EXPECT_EQ(mapper.NamedPageAtIndex(8), "bar");
+ EXPECT_EQ(mapper.NamedPageAtIndex(7), "foo");
+ EXPECT_EQ(mapper.NamedPageAtIndex(6), AtomicString());
+ EXPECT_EQ(mapper.NamedPageAtIndex(100), "foo");
+
+ mapper.AddNamedPage(AtomicString(), 11);
+ EXPECT_EQ(mapper.LastPageName(), AtomicString());
+ EXPECT_EQ(mapper.NamedPageAtIndex(11), AtomicString());
+ EXPECT_EQ(mapper.NamedPageAtIndex(10), "foo");
+ EXPECT_EQ(mapper.NamedPageAtIndex(9), "bar");
+ EXPECT_EQ(mapper.NamedPageAtIndex(8), "bar");
+ EXPECT_EQ(mapper.NamedPageAtIndex(7), "foo");
+ EXPECT_EQ(mapper.NamedPageAtIndex(6), AtomicString());
+ EXPECT_EQ(mapper.NamedPageAtIndex(100), AtomicString());
+
+ mapper.AddNamedPage("FOO", 13);
+ EXPECT_EQ(mapper.LastPageName(), "FOO");
+ EXPECT_EQ(mapper.NamedPageAtIndex(13), "FOO");
+ EXPECT_EQ(mapper.NamedPageAtIndex(12), AtomicString());
+ EXPECT_EQ(mapper.NamedPageAtIndex(11), AtomicString());
+ EXPECT_EQ(mapper.NamedPageAtIndex(10), "foo");
+ EXPECT_EQ(mapper.NamedPageAtIndex(9), "bar");
+ EXPECT_EQ(mapper.NamedPageAtIndex(8), "bar");
+ EXPECT_EQ(mapper.NamedPageAtIndex(7), "foo");
+ EXPECT_EQ(mapper.NamedPageAtIndex(6), AtomicString());
+ EXPECT_EQ(mapper.NamedPageAtIndex(100), "FOO");
+
+ // Go back to page 9. This will clear everything after.
+ mapper.AddNamedPage("surprise", 9);
+ EXPECT_EQ(mapper.LastPageName(), "surprise");
+ EXPECT_EQ(mapper.NamedPageAtIndex(13), "surprise");
+ EXPECT_EQ(mapper.NamedPageAtIndex(12), "surprise");
+ EXPECT_EQ(mapper.NamedPageAtIndex(11), "surprise");
+ EXPECT_EQ(mapper.NamedPageAtIndex(10), "surprise");
+ EXPECT_EQ(mapper.NamedPageAtIndex(9), "surprise");
+ EXPECT_EQ(mapper.NamedPageAtIndex(8), "bar");
+ EXPECT_EQ(mapper.NamedPageAtIndex(7), "foo");
+ EXPECT_EQ(mapper.NamedPageAtIndex(6), AtomicString());
+ EXPECT_EQ(mapper.NamedPageAtIndex(100), "surprise");
+
+ mapper.AddNamedPage("lol", 13);
+ EXPECT_EQ(mapper.LastPageName(), "lol");
+ EXPECT_EQ(mapper.NamedPageAtIndex(13), "lol");
+ EXPECT_EQ(mapper.NamedPageAtIndex(12), "surprise");
+ EXPECT_EQ(mapper.NamedPageAtIndex(11), "surprise");
+ EXPECT_EQ(mapper.NamedPageAtIndex(10), "surprise");
+ EXPECT_EQ(mapper.NamedPageAtIndex(9), "surprise");
+ EXPECT_EQ(mapper.NamedPageAtIndex(8), "bar");
+ EXPECT_EQ(mapper.NamedPageAtIndex(7), "foo");
+ EXPECT_EQ(mapper.NamedPageAtIndex(6), AtomicString());
+ EXPECT_EQ(mapper.NamedPageAtIndex(100), "lol");
+
+ mapper.AddNamedPage("page2", 2);
+ EXPECT_EQ(mapper.LastPageName(), "page2");
+ EXPECT_EQ(mapper.NamedPageAtIndex(0), AtomicString());
+ EXPECT_EQ(mapper.NamedPageAtIndex(1), AtomicString());
+ EXPECT_EQ(mapper.NamedPageAtIndex(2), "page2");
+ EXPECT_EQ(mapper.NamedPageAtIndex(100), "page2");
+
+ mapper.AddNamedPage("page1", 1);
+ EXPECT_EQ(mapper.LastPageName(), "page1");
+ EXPECT_EQ(mapper.NamedPageAtIndex(0), AtomicString());
+ EXPECT_EQ(mapper.NamedPageAtIndex(1), "page1");
+ EXPECT_EQ(mapper.NamedPageAtIndex(2), "page1");
+ EXPECT_EQ(mapper.NamedPageAtIndex(100), "page1");
+}
+
+TEST(NamedPagesMapperTest, FirstPageIsNamed) {
+ NamedPagesMapper mapper;
+ mapper.AddNamedPage("named", 0);
+ EXPECT_EQ(mapper.LastPageName(), "named");
+ EXPECT_EQ(mapper.NamedPageAtIndex(0), "named");
+ EXPECT_EQ(mapper.NamedPageAtIndex(100), "named");
+
+ mapper.AddNamedPage("overwrite", 0);
+ EXPECT_EQ(mapper.NamedPageAtIndex(0), "overwrite");
+ EXPECT_EQ(mapper.NamedPageAtIndex(100), "overwrite");
+
+ mapper.AddNamedPage("foo", 1);
+ EXPECT_EQ(mapper.NamedPageAtIndex(0), "overwrite");
+ EXPECT_EQ(mapper.NamedPageAtIndex(1), "foo");
+ EXPECT_EQ(mapper.NamedPageAtIndex(100), "foo");
+
+ mapper.AddNamedPage("xxx", 0);
+ EXPECT_EQ(mapper.NamedPageAtIndex(0), "xxx");
+ EXPECT_EQ(mapper.NamedPageAtIndex(1), "xxx");
+ EXPECT_EQ(mapper.NamedPageAtIndex(100), "xxx");
+}
+
+} // anonymous namespace
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/page/page.cc b/chromium/third_party/blink/renderer/core/page/page.cc
index 50e76a0e0a6..608f9d8f2b4 100644
--- a/chromium/third_party/blink/renderer/core/page/page.cc
+++ b/chromium/third_party/blink/renderer/core/page/page.cc
@@ -54,7 +54,6 @@
#include "third_party/blink/renderer/core/html/media/html_media_element.h"
#include "third_party/blink/renderer/core/inspector/console_message.h"
#include "third_party/blink/renderer/core/inspector/console_message_storage.h"
-#include "third_party/blink/renderer/core/inspector/inspector_issue.h"
#include "third_party/blink/renderer/core/inspector/inspector_issue_storage.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
#include "third_party/blink/renderer/core/layout/text_autosizer.h"
@@ -90,7 +89,7 @@
namespace blink {
-// Wrapper function defined in WebKit.h
+// Function defined in third_party/blink/public/web/blink.h.
void ResetPluginCache(bool reload_pages) {
// At this point we already know that the browser has refreshed its list, so
// it is not necessary to force it to be regenerated.
@@ -202,7 +201,7 @@ Page::Page(PageClients& page_clients)
tab_key_cycles_through_elements_(true),
paused_(false),
device_scale_factor_(1),
- visibility_state_(PageVisibilityState::kVisible),
+ visibility_state_(mojom::blink::PageVisibilityState::kVisible),
is_ordinary_(false),
page_lifecycle_state_(kDefaultPageLifecycleState),
is_cursor_visible_(true),
@@ -511,8 +510,9 @@ void Page::VisitedStateChanged(LinkHash link_hash) {
}
}
-void Page::SetVisibilityState(PageVisibilityState visibility_state,
- bool is_initial_state) {
+void Page::SetVisibilityState(
+ mojom::blink::PageVisibilityState visibility_state,
+ bool is_initial_state) {
if (visibility_state_ == visibility_state)
return;
visibility_state_ = visibility_state;
@@ -526,18 +526,18 @@ void Page::SetVisibilityState(PageVisibilityState visibility_state,
});
if (main_frame_) {
- if (visibility_state_ == PageVisibilityState::kVisible)
+ if (visibility_state_ == mojom::blink::PageVisibilityState::kVisible)
RestoreSVGImageAnimations();
main_frame_->DidChangeVisibilityState();
}
}
-PageVisibilityState Page::GetVisibilityState() const {
+mojom::blink::PageVisibilityState Page::GetVisibilityState() const {
return visibility_state_;
}
bool Page::IsPageVisible() const {
- return visibility_state_ == PageVisibilityState::kVisible;
+ return visibility_state_ == mojom::blink::PageVisibilityState::kVisible;
}
void Page::SetLifecycleState(PageLifecycleState state) {
@@ -854,6 +854,7 @@ void Page::UpdateAcceleratedCompositingSettings() {
void Page::DidCommitLoad(LocalFrame* frame) {
if (main_frame_ == frame) {
GetConsoleMessageStorage().Clear();
+ GetInspectorIssueStorage().Clear();
// TODO(loonybear): Most of this doesn't appear to take into account that
// each SVGImage gets it's own Page instance.
GetDeprecation().ClearSuppression();
diff --git a/chromium/third_party/blink/renderer/core/page/page.h b/chromium/third_party/blink/renderer/core/page/page.h
index 1074204dbfb..181c13e9e6e 100644
--- a/chromium/third_party/blink/renderer/core/page/page.h
+++ b/chromium/third_party/blink/renderer/core/page/page.h
@@ -26,7 +26,8 @@
#include <memory>
#include "base/macros.h"
-#include "third_party/blink/public/common/page/page_visibility_state.h"
+#include "third_party/blink/public/mojom/devtools/inspector_issue.mojom-blink-forward.h"
+#include "third_party/blink/public/mojom/page/page_visibility_state.mojom-blink.h"
#include "third_party/blink/public/platform/scheduler/web_scoped_virtual_time_pauser.h"
#include "third_party/blink/public/platform/web_text_autosizer_page_info.h"
#include "third_party/blink/public/web/web_window_features.h"
@@ -264,9 +265,9 @@ class CORE_EXPORT Page final : public GarbageCollected<Page>,
static void AllVisitedStateChanged(bool invalidate_visited_link_hashes);
static void VisitedStateChanged(LinkHash visited_hash);
- void SetVisibilityState(PageVisibilityState visibility_state,
+ void SetVisibilityState(mojom::blink::PageVisibilityState visibility_state,
bool is_initial_state);
- PageVisibilityState GetVisibilityState() const;
+ mojom::blink::PageVisibilityState GetVisibilityState() const;
bool IsPageVisible() const;
PageLifecycleState LifecycleState() const;
@@ -428,7 +429,7 @@ class CORE_EXPORT Page final : public GarbageCollected<Page>,
float device_scale_factor_;
- PageVisibilityState visibility_state_;
+ mojom::blink::PageVisibilityState visibility_state_;
bool is_ordinary_;
diff --git a/chromium/third_party/blink/renderer/core/page/page_animator.cc b/chromium/third_party/blink/renderer/core/page/page_animator.cc
index ec13847be9d..e05f3c22d1f 100644
--- a/chromium/third_party/blink/renderer/core/page/page_animator.cc
+++ b/chromium/third_party/blink/renderer/core/page/page_animator.cc
@@ -57,9 +57,10 @@ void PageAnimator::ServiceScriptedAnimations(
for (auto& document : documents) {
ScopedFrameBlamer frame_blamer(document->GetFrame());
TRACE_EVENT0("blink,rail", "PageAnimator::serviceScriptedAnimations");
- document->GetDocumentAnimations().UpdateAnimationTimingForAnimationFrame();
if (document->View()) {
if (document->View()->ShouldThrottleRendering()) {
+ document->GetDocumentAnimations()
+ .UpdateAnimationTimingForAnimationFrame();
document->SetCurrentFrameIsThrottled(true);
continue;
}
@@ -90,6 +91,7 @@ void PageAnimator::ServiceScriptedAnimations(
document->GetFrame()->AnimateSnapFling(monotonic_animation_start_time);
SVGDocumentExtensions::ServiceOnAnimationFrame(*document);
}
+ document->GetDocumentAnimations().UpdateAnimationTimingForAnimationFrame();
// TODO(skyostil): This function should not run for documents without views.
DocumentLifecycle::DisallowThrottlingScope no_throttling_scope(
document->Lifecycle());
diff --git a/chromium/third_party/blink/renderer/core/page/page_popup.h b/chromium/third_party/blink/renderer/core/page/page_popup.h
index 552efe67419..d6acf42d44a 100644
--- a/chromium/third_party/blink/renderer/core/page/page_popup.h
+++ b/chromium/third_party/blink/renderer/core/page/page_popup.h
@@ -45,6 +45,7 @@ class PagePopup {
virtual AXObject* RootAXObject() = 0;
virtual void SetWindowRect(const IntRect&) = 0;
virtual void PostMessageToPopup(const String& message) = 0;
+ virtual void Update() = 0;
protected:
virtual ~PagePopup() = default;
diff --git a/chromium/third_party/blink/renderer/core/page/page_popup_client.cc b/chromium/third_party/blink/renderer/core/page/page_popup_client.cc
index da21fc48bbc..3f7596b0e3b 100644
--- a/chromium/third_party/blink/renderer/core/page/page_popup_client.cc
+++ b/chromium/third_party/blink/renderer/core/page/page_popup_client.cc
@@ -35,6 +35,7 @@
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/page/chrome_client.h"
#include "third_party/blink/renderer/core/page/page_popup_controller.h"
+#include "third_party/blink/renderer/platform/text/platform_locale.h"
#include "third_party/blink/renderer/platform/wtf/text/character_names.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
@@ -157,14 +158,21 @@ void PagePopupClient::AddProperty(const char* name,
addLiteral("},\n", data);
}
+void PagePopupClient::AddLocalizedProperty(const char* name,
+ int resource_id,
+ SharedBuffer* data) {
+ AddProperty(name, GetLocale().QueryString(resource_id), data);
+}
+
CSSFontSelector* PagePopupClient::CreateCSSFontSelector(
Document& popup_document) {
return MakeGarbageCollected<CSSFontSelector>(&popup_document);
}
PagePopupController* PagePopupClient::CreatePagePopupController(
+ Page& page,
PagePopup& popup) {
- return MakeGarbageCollected<PagePopupController>(popup, this);
+ return MakeGarbageCollected<PagePopupController>(page, popup, this);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/page/page_popup_client.h b/chromium/third_party/blink/renderer/core/page/page_popup_client.h
index 7f36805face..9b59fdd23a8 100644
--- a/chromium/third_party/blink/renderer/core/page/page_popup_client.h
+++ b/chromium/third_party/blink/renderer/core/page/page_popup_client.h
@@ -44,6 +44,7 @@ class ChromeClient;
class Document;
class Element;
class Locale;
+class Page;
class PagePopup;
class PagePopupController;
@@ -62,7 +63,7 @@ class CORE_EXPORT PagePopupClient {
virtual CSSFontSelector* CreateCSSFontSelector(Document& popup_document);
- virtual PagePopupController* CreatePagePopupController(PagePopup&);
+ virtual PagePopupController* CreatePagePopupController(Page&, PagePopup&);
// Returns effective zoom factor of ownerElement, or the page zoom factor if
// the effective zoom factor is not available.
@@ -89,6 +90,9 @@ class CORE_EXPORT PagePopupClient {
// This is called whenever a PagePopup was closed.
virtual void DidClosePopup() = 0;
+ // This is called when popup content or its owner's position changed.
+ virtual void Update(bool force_update) {}
+
virtual ~PagePopupClient() = default;
// Helper functions to be used in PagePopupClient::writeDocument().
@@ -103,6 +107,7 @@ class CORE_EXPORT PagePopupClient {
const Vector<String>& values,
SharedBuffer*);
static void AddProperty(const char* name, const IntRect&, SharedBuffer*);
+ void AddLocalizedProperty(const char* name, int resource_id, SharedBuffer*);
};
inline void PagePopupClient::AddString(const String& str, SharedBuffer* data) {
diff --git a/chromium/third_party/blink/renderer/core/page/page_popup_controller.cc b/chromium/third_party/blink/renderer/core/page/page_popup_controller.cc
index 82bc0cbb1e8..5985d67b1b7 100644
--- a/chromium/third_party/blink/renderer/core/page/page_popup_controller.cc
+++ b/chromium/third_party/blink/renderer/core/page/page_popup_controller.cc
@@ -32,17 +32,25 @@
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/strings/grit/blink_strings.h"
+#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/core/page/page_popup.h"
#include "third_party/blink/renderer/core/page/page_popup_client.h"
-#include "third_party/blink/renderer/core/page/page_popup_supplement.h"
#include "third_party/blink/renderer/platform/text/platform_locale.h"
namespace blink {
-PagePopupController::PagePopupController(PagePopup& popup,
+const char PagePopupController::kSupplementName[] = "PagePopupController";
+
+PagePopupController* PagePopupController::From(Page& page) {
+ return Supplement<Page>::From<PagePopupController>(page);
+}
+
+PagePopupController::PagePopupController(Page& page,
+ PagePopup& popup,
PagePopupClient* client)
: popup_(popup), popup_client_(client) {
DCHECK(client);
+ ProvideTo(page, this);
}
void PagePopupController::setValueAndClosePopup(int num_value,
@@ -106,6 +114,11 @@ void PagePopupController::setWindowRect(int x, int y, int width, int height) {
popup_.SetWindowRect(IntRect(x, y, width, height));
}
+void PagePopupController::Trace(Visitor* visitor) {
+ ScriptWrappable::Trace(visitor);
+ Supplement<Page>::Trace(visitor);
+}
+
// static
CSSFontSelector* PagePopupController::CreateCSSFontSelector(
Document& popup_document) {
@@ -113,7 +126,7 @@ CSSFontSelector* PagePopupController::CreateCSSFontSelector(
DCHECK(frame);
DCHECK(frame->PagePopupOwner());
- auto* controller = PagePopupSupplement::From(*frame).GetPagePopupController();
+ auto* controller = PagePopupController::From(*frame->GetPage());
DCHECK(controller->popup_client_);
return controller->popup_client_->CreateCSSFontSelector(popup_document);
diff --git a/chromium/third_party/blink/renderer/core/page/page_popup_controller.h b/chromium/third_party/blink/renderer/core/page/page_popup_controller.h
index a08566a2dc4..2e256d7f5de 100644
--- a/chromium/third_party/blink/renderer/core/page/page_popup_controller.h
+++ b/chromium/third_party/blink/renderer/core/page/page_popup_controller.h
@@ -33,20 +33,26 @@
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
+#include "third_party/blink/renderer/platform/supplementable.h"
#include "third_party/blink/renderer/platform/wtf/forward.h"
namespace blink {
class CSSFontSelector;
class Document;
+class Page;
class PagePopup;
class PagePopupClient;
-class PagePopupController : public ScriptWrappable {
+class PagePopupController : public ScriptWrappable, public Supplement<Page> {
DEFINE_WRAPPERTYPEINFO();
+ USING_GARBAGE_COLLECTED_MIXIN(PagePopupController);
public:
- PagePopupController(PagePopup&, PagePopupClient*);
+ static const char kSupplementName[];
+ PagePopupController(Page&, PagePopup&, PagePopupClient*);
+
+ static PagePopupController* From(Page&);
void setValueAndClosePopup(int num_value, const String& string_value);
void setValue(const String&);
@@ -62,6 +68,8 @@ class PagePopupController : public ScriptWrappable {
static CSSFontSelector* CreateCSSFontSelector(Document& popup_document);
+ void Trace(Visitor*) override;
+
private:
PagePopup& popup_;
diff --git a/chromium/third_party/blink/renderer/core/page/page_popup_supplement.cc b/chromium/third_party/blink/renderer/core/page/page_popup_supplement.cc
deleted file mode 100644
index e0f3a51af5a..00000000000
--- a/chromium/third_party/blink/renderer/core/page/page_popup_supplement.cc
+++ /dev/null
@@ -1,81 +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/core/page/page_popup_supplement.h"
-
-#include "third_party/blink/renderer/core/page/page_popup_client.h"
-#include "third_party/blink/renderer/core/page/page_popup_controller.h"
-
-namespace blink {
-
-PagePopupSupplement::PagePopupSupplement(LocalFrame& frame,
- PagePopup& popup,
- PagePopupClient* popup_client)
- : Supplement<LocalFrame>(frame),
- controller_(popup_client->CreatePagePopupController(popup)) {
- DCHECK(popup_client);
-}
-
-const char PagePopupSupplement::kSupplementName[] = "PagePopupSupplement";
-
-PagePopupSupplement& PagePopupSupplement::From(LocalFrame& frame) {
- PagePopupSupplement* supplement =
- Supplement<LocalFrame>::From<PagePopupSupplement>(&frame);
- DCHECK(supplement);
- return *supplement;
-}
-
-PagePopupController* PagePopupSupplement::GetPagePopupController() const {
- return controller_;
-}
-
-void PagePopupSupplement::Dispose() {
- controller_->ClearPagePopupClient();
-}
-
-void PagePopupSupplement::Install(LocalFrame& frame,
- PagePopup& popup,
- PagePopupClient* popup_client) {
- DCHECK(popup_client);
- ProvideTo(frame, MakeGarbageCollected<PagePopupSupplement>(frame, popup,
- popup_client));
-}
-
-void PagePopupSupplement::Uninstall(LocalFrame& frame) {
- PagePopupSupplement::From(frame).Dispose();
- frame.RemoveSupplement<PagePopupSupplement>();
-}
-
-void PagePopupSupplement::Trace(Visitor* visitor) {
- visitor->Trace(controller_);
- Supplement<LocalFrame>::Trace(visitor);
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/page/page_popup_supplement.h b/chromium/third_party/blink/renderer/core/page/page_popup_supplement.h
deleted file mode 100644
index 4dafb45f1c6..00000000000
--- a/chromium/third_party/blink/renderer/core/page/page_popup_supplement.h
+++ /dev/null
@@ -1,70 +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_CORE_PAGE_PAGE_POPUP_SUPPLEMENT_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_PAGE_PAGE_POPUP_SUPPLEMENT_H_
-
-#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/core/frame/local_frame.h"
-#include "third_party/blink/renderer/platform/heap/handle.h"
-#include "third_party/blink/renderer/platform/supplementable.h"
-
-namespace blink {
-
-class PagePopup;
-class PagePopupClient;
-class PagePopupController;
-
-class CORE_EXPORT PagePopupSupplement final
- : public GarbageCollected<PagePopupSupplement>,
- public Supplement<LocalFrame> {
- USING_GARBAGE_COLLECTED_MIXIN(PagePopupSupplement);
-
- public:
- static const char kSupplementName[];
-
- static PagePopupSupplement& From(LocalFrame&);
- static void Install(LocalFrame&, PagePopup&, PagePopupClient*);
- static void Uninstall(LocalFrame&);
-
- PagePopupController* GetPagePopupController() const;
-
- PagePopupSupplement(LocalFrame&, PagePopup&, PagePopupClient*);
-
- void Trace(Visitor*) override;
-
- private:
- void Dispose();
-
- Member<PagePopupController> controller_;
-};
-
-} // namespace blink
-#endif
diff --git a/chromium/third_party/blink/renderer/core/page/page_widget_delegate.cc b/chromium/third_party/blink/renderer/core/page/page_widget_delegate.cc
index 4c9a4a84ee6..a392e4f45b2 100644
--- a/chromium/third_party/blink/renderer/core/page/page_widget_delegate.cc
+++ b/chromium/third_party/blink/renderer/core/page/page_widget_delegate.cc
@@ -120,66 +120,66 @@ WebInputEventResult PageWidgetDelegate::HandleInputEvent(
// interested in whether keyboard events are processed).
// FIXME: Why do we return HandleSuppressed when there is no root or
// the root is detached?
- case WebInputEvent::kMouseMove:
+ case WebInputEvent::Type::kMouseMove:
if (!root || !root->View())
return WebInputEventResult::kHandledSuppressed;
handler.HandleMouseMove(*root, static_cast<const WebMouseEvent&>(event),
coalesced_event.GetCoalescedEventsPointers(),
coalesced_event.GetPredictedEventsPointers());
return WebInputEventResult::kHandledSystem;
- case WebInputEvent::kMouseLeave:
+ case WebInputEvent::Type::kMouseLeave:
if (!root || !root->View())
return WebInputEventResult::kHandledSuppressed;
handler.HandleMouseLeave(*root, static_cast<const WebMouseEvent&>(event));
return WebInputEventResult::kHandledSystem;
- case WebInputEvent::kMouseDown:
+ case WebInputEvent::Type::kMouseDown:
if (!root || !root->View())
return WebInputEventResult::kHandledSuppressed;
handler.HandleMouseDown(*root, static_cast<const WebMouseEvent&>(event));
return WebInputEventResult::kHandledSystem;
- case WebInputEvent::kMouseUp:
+ case WebInputEvent::Type::kMouseUp:
if (!root || !root->View())
return WebInputEventResult::kHandledSuppressed;
return handler.HandleMouseUp(*root,
static_cast<const WebMouseEvent&>(event));
- case WebInputEvent::kMouseWheel:
+ case WebInputEvent::Type::kMouseWheel:
if (!root || !root->View())
return WebInputEventResult::kNotHandled;
return handler.HandleMouseWheel(
*root, static_cast<const WebMouseWheelEvent&>(event));
- case WebInputEvent::kRawKeyDown:
- case WebInputEvent::kKeyDown:
- case WebInputEvent::kKeyUp:
+ case WebInputEvent::Type::kRawKeyDown:
+ case WebInputEvent::Type::kKeyDown:
+ case WebInputEvent::Type::kKeyUp:
return handler.HandleKeyEvent(
static_cast<const WebKeyboardEvent&>(event));
- case WebInputEvent::kChar:
+ case WebInputEvent::Type::kChar:
return handler.HandleCharEvent(
static_cast<const WebKeyboardEvent&>(event));
- case WebInputEvent::kGestureScrollBegin:
- case WebInputEvent::kGestureScrollEnd:
- case WebInputEvent::kGestureScrollUpdate:
- case WebInputEvent::kGestureFlingStart:
- case WebInputEvent::kGestureFlingCancel:
- case WebInputEvent::kGestureTap:
- case WebInputEvent::kGestureTapUnconfirmed:
- case WebInputEvent::kGestureTapDown:
- case WebInputEvent::kGestureShowPress:
- case WebInputEvent::kGestureTapCancel:
- case WebInputEvent::kGestureDoubleTap:
- case WebInputEvent::kGestureTwoFingerTap:
- case WebInputEvent::kGestureLongPress:
- case WebInputEvent::kGestureLongTap:
+ case WebInputEvent::Type::kGestureScrollBegin:
+ case WebInputEvent::Type::kGestureScrollEnd:
+ case WebInputEvent::Type::kGestureScrollUpdate:
+ case WebInputEvent::Type::kGestureFlingStart:
+ case WebInputEvent::Type::kGestureFlingCancel:
+ case WebInputEvent::Type::kGestureTap:
+ case WebInputEvent::Type::kGestureTapUnconfirmed:
+ case WebInputEvent::Type::kGestureTapDown:
+ case WebInputEvent::Type::kGestureShowPress:
+ case WebInputEvent::Type::kGestureTapCancel:
+ case WebInputEvent::Type::kGestureDoubleTap:
+ case WebInputEvent::Type::kGestureTwoFingerTap:
+ case WebInputEvent::Type::kGestureLongPress:
+ case WebInputEvent::Type::kGestureLongTap:
return handler.HandleGestureEvent(
static_cast<const WebGestureEvent&>(event));
- case WebInputEvent::kPointerDown:
- case WebInputEvent::kPointerUp:
- case WebInputEvent::kPointerMove:
- case WebInputEvent::kPointerRawUpdate:
- case WebInputEvent::kPointerCancel:
- case WebInputEvent::kPointerCausedUaAction:
+ case WebInputEvent::Type::kPointerDown:
+ case WebInputEvent::Type::kPointerUp:
+ case WebInputEvent::Type::kPointerMove:
+ case WebInputEvent::Type::kPointerRawUpdate:
+ case WebInputEvent::Type::kPointerCancel:
+ case WebInputEvent::Type::kPointerCausedUaAction:
if (!root || !root->View())
return WebInputEventResult::kNotHandled;
return handler.HandlePointerEvent(
@@ -187,20 +187,20 @@ WebInputEventResult PageWidgetDelegate::HandleInputEvent(
coalesced_event.GetCoalescedEventsPointers(),
coalesced_event.GetPredictedEventsPointers());
- case WebInputEvent::kTouchStart:
- case WebInputEvent::kTouchMove:
- case WebInputEvent::kTouchEnd:
- case WebInputEvent::kTouchCancel:
- case WebInputEvent::kTouchScrollStarted:
+ case WebInputEvent::Type::kTouchStart:
+ case WebInputEvent::Type::kTouchMove:
+ case WebInputEvent::Type::kTouchEnd:
+ case WebInputEvent::Type::kTouchCancel:
+ case WebInputEvent::Type::kTouchScrollStarted:
NOTREACHED();
return WebInputEventResult::kNotHandled;
- case WebInputEvent::kGesturePinchBegin:
+ case WebInputEvent::Type::kGesturePinchBegin:
// Gesture pinch events are handled entirely on the compositor.
DLOG(INFO) << "Gesture pinch ignored by main thread.";
FALLTHROUGH;
- case WebInputEvent::kGesturePinchEnd:
- case WebInputEvent::kGesturePinchUpdate:
+ case WebInputEvent::Type::kGesturePinchEnd:
+ case WebInputEvent::Type::kGesturePinchUpdate:
return WebInputEventResult::kNotHandled;
default:
return WebInputEventResult::kNotHandled;
@@ -213,8 +213,8 @@ WebInputEventResult PageWidgetDelegate::HandleInputEvent(
void PageWidgetEventHandler::HandleMouseMove(
LocalFrame& main_frame,
const WebMouseEvent& event,
- const WebVector<const WebInputEvent*>& coalesced_events,
- const WebVector<const WebInputEvent*>& predicted_events) {
+ const std::vector<std::unique_ptr<WebInputEvent>>& coalesced_events,
+ const std::vector<std::unique_ptr<WebInputEvent>>& predicted_events) {
WebMouseEvent transformed_event =
TransformWebMouseEvent(main_frame.View(), event);
main_frame.GetEventHandler().HandleMouseMoveEvent(
@@ -257,8 +257,8 @@ WebInputEventResult PageWidgetEventHandler::HandleMouseWheel(
WebInputEventResult PageWidgetEventHandler::HandlePointerEvent(
LocalFrame& main_frame,
const WebPointerEvent& event,
- const WebVector<const WebInputEvent*>& coalesced_events,
- const WebVector<const WebInputEvent*>& predicted_events) {
+ const std::vector<std::unique_ptr<WebInputEvent>>& coalesced_events,
+ const std::vector<std::unique_ptr<WebInputEvent>>& predicted_events) {
WebPointerEvent transformed_event =
TransformWebPointerEvent(main_frame.View(), event);
return main_frame.GetEventHandler().HandlePointerEvent(
diff --git a/chromium/third_party/blink/renderer/core/page/page_widget_delegate.h b/chromium/third_party/blink/renderer/core/page/page_widget_delegate.h
index bfe965ffaa8..d93ad4304cd 100644
--- a/chromium/third_party/blink/renderer/core/page/page_widget_delegate.h
+++ b/chromium/third_party/blink/renderer/core/page/page_widget_delegate.h
@@ -31,7 +31,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_PAGE_PAGE_WIDGET_DELEGATE_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_PAGE_PAGE_WIDGET_DELEGATE_H_
-#include "third_party/blink/public/platform/web_coalesced_input_event.h"
+#include "third_party/blink/public/common/input/web_coalesced_input_event.h"
#include "third_party/blink/public/web/web_widget.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
@@ -48,10 +48,11 @@ class WebPointerEvent;
class CORE_EXPORT PageWidgetEventHandler {
public:
- virtual void HandleMouseMove(LocalFrame& main_frame,
- const WebMouseEvent&,
- const WebVector<const WebInputEvent*>&,
- const WebVector<const WebInputEvent*>&);
+ virtual void HandleMouseMove(
+ LocalFrame& main_frame,
+ const WebMouseEvent&,
+ const std::vector<std::unique_ptr<WebInputEvent>>&,
+ const std::vector<std::unique_ptr<WebInputEvent>>&);
virtual void HandleMouseLeave(LocalFrame& main_frame, const WebMouseEvent&);
virtual void HandleMouseDown(LocalFrame& main_frame, const WebMouseEvent&);
virtual WebInputEventResult HandleMouseUp(LocalFrame& main_frame,
@@ -64,9 +65,9 @@ class CORE_EXPORT PageWidgetEventHandler {
virtual WebInputEventResult HandlePointerEvent(
LocalFrame& main_frame,
const WebPointerEvent&,
- const WebVector<const WebInputEvent*>&,
- const WebVector<const WebInputEvent*>&);
- virtual ~PageWidgetEventHandler() {}
+ const std::vector<std::unique_ptr<WebInputEvent>>&,
+ const std::vector<std::unique_ptr<WebInputEvent>>&);
+ virtual ~PageWidgetEventHandler() = default;
};
// Common implementation of WebViewImpl and WebPagePopupImpl.
diff --git a/chromium/third_party/blink/renderer/core/page/plugin_script_forbidden_scope.cc b/chromium/third_party/blink/renderer/core/page/plugin_script_forbidden_scope.cc
index 45afc53015d..c9ef4a0cd1c 100644
--- a/chromium/third_party/blink/renderer/core/page/plugin_script_forbidden_scope.cc
+++ b/chromium/third_party/blink/renderer/core/page/plugin_script_forbidden_scope.cc
@@ -4,7 +4,7 @@
#include "third_party/blink/renderer/core/page/plugin_script_forbidden_scope.h"
-#include "base/logging.h"
+#include "base/check.h"
#include "third_party/blink/renderer/platform/wtf/wtf.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/page/pointer_lock_controller.cc b/chromium/third_party/blink/renderer/core/page/pointer_lock_controller.cc
index 8b72cb38083..11281892726 100644
--- a/chromium/third_party/blink/renderer/core/page/pointer_lock_controller.cc
+++ b/chromium/third_party/blink/renderer/core/page/pointer_lock_controller.cc
@@ -25,6 +25,7 @@
#include "third_party/blink/renderer/core/page/pointer_lock_controller.h"
+#include "services/network/public/mojom/web_sandbox_flags.mojom-blink.h"
#include "third_party/blink/public/common/input/web_mouse_event.h"
#include "third_party/blink/public/mojom/input/pointer_lock_result.mojom-blink.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
@@ -71,7 +72,7 @@ ScriptPromise PointerLockController::RequestPointerLock(
}
if (target->GetDocument().IsSandboxed(
- mojom::blink::WebSandboxFlags::kPointerLock)) {
+ network::mojom::blink::WebSandboxFlags::kPointerLock)) {
// FIXME: This message should be moved off the console once a solution to
// https://bugs.webkit.org/show_bug.cgi?id=103274 exists.
target->GetDocument().AddConsoleMessage(
@@ -106,7 +107,8 @@ ScriptPromise PointerLockController::RequestPointerLock(
target->GetDocument().GetFrame(),
WTF::Bind(&PointerLockController::ChangeLockRequestCallback,
WrapWeakPersistent(this), WrapWeakPersistent(target),
- WrapPersistent(resolver)),
+ WrapPersistent(resolver),
+ unadjusted_movement_requested),
unadjusted_movement_requested)) {
EnqueueEvent(event_type_names::kPointerlockerror, target);
exception_state.ThrowDOMException(
@@ -123,12 +125,11 @@ ScriptPromise PointerLockController::RequestPointerLock(
} else if (page_->GetChromeClient().RequestPointerLock(
target->GetDocument().GetFrame(),
WTF::Bind(&PointerLockController::LockRequestCallback,
- WrapWeakPersistent(this), WrapPersistent(resolver)),
+ WrapWeakPersistent(this), WrapPersistent(resolver),
+ unadjusted_movement_requested),
unadjusted_movement_requested)) {
lock_pending_ = true;
element_ = target;
- current_unadjusted_movement_setting_ =
- options ? options->unadjustedMovement() : false;
} else {
EnqueueEvent(event_type_names::kPointerlockerror, target);
exception_state.ThrowDOMException(DOMExceptionCode::kInUseAttributeError,
@@ -141,17 +142,20 @@ ScriptPromise PointerLockController::RequestPointerLock(
void PointerLockController::ChangeLockRequestCallback(
Element* target,
ScriptPromiseResolver* resolver,
+ bool unadjusted_movement_requested,
mojom::blink::PointerLockResult result) {
if (result == mojom::blink::PointerLockResult::kSuccess)
element_ = target;
- LockRequestCallback(resolver, result);
+ LockRequestCallback(resolver, unadjusted_movement_requested, result);
}
void PointerLockController::LockRequestCallback(
ScriptPromiseResolver* resolver,
+ bool unadjusted_movement_requested,
mojom::blink::PointerLockResult result) {
if (result == mojom::blink::PointerLockResult::kSuccess) {
+ current_unadjusted_movement_setting_ = unadjusted_movement_requested;
resolver->Resolve();
return;
}
diff --git a/chromium/third_party/blink/renderer/core/page/pointer_lock_controller.h b/chromium/third_party/blink/renderer/core/page/pointer_lock_controller.h
index fd8aeaafcfd..0e5cb12c531 100644
--- a/chromium/third_party/blink/renderer/core/page/pointer_lock_controller.h
+++ b/chromium/third_party/blink/renderer/core/page/pointer_lock_controller.h
@@ -82,8 +82,10 @@ class CORE_EXPORT PointerLockController final
void EnqueueEvent(const AtomicString& type, Document*);
void ChangeLockRequestCallback(Element* target,
ScriptPromiseResolver* resolver,
+ bool unadjusted_movement_requested,
mojom::blink::PointerLockResult result);
void LockRequestCallback(ScriptPromiseResolver* resolver,
+ bool unadjusted_movement_requested,
mojom::blink::PointerLockResult result);
DOMException* ConvertResultToException(
mojom::blink::PointerLockResult result);
diff --git a/chromium/third_party/blink/renderer/core/page/print_context.cc b/chromium/third_party/blink/renderer/core/page/print_context.cc
index f7f90dba8a4..6db481721e1 100644
--- a/chromium/third_party/blink/renderer/core/page/print_context.cc
+++ b/chromium/third_party/blink/renderer/core/page/print_context.cc
@@ -22,6 +22,7 @@
#include <utility>
+#include "third_party/blink/public/web/web_print_page_description.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
@@ -286,15 +287,20 @@ String PrintContext::PageSizeAndMarginsInPixels(LocalFrame* frame,
int margin_right,
int margin_bottom,
int margin_left) {
- DoubleSize page_size(width, height);
- frame->GetDocument()->PageSizeAndMarginsInPixels(page_number, page_size,
- margin_top, margin_right,
- margin_bottom, margin_left);
-
- return "(" + String::Number(floor(page_size.Width())) + ", " +
- String::Number(floor(page_size.Height())) + ") " +
- String::Number(margin_top) + ' ' + String::Number(margin_right) + ' ' +
- String::Number(margin_bottom) + ' ' + String::Number(margin_left);
+ WebPrintPageDescription description;
+ description.size = WebDoubleSize(width, height);
+ description.margin_top = margin_top;
+ description.margin_right = margin_right;
+ description.margin_bottom = margin_bottom;
+ description.margin_left = margin_left;
+ frame->GetDocument()->GetPageDescription(page_number, &description);
+
+ return "(" + String::Number(floor(description.size.Width())) + ", " +
+ String::Number(floor(description.size.Height())) + ") " +
+ String::Number(description.margin_top) + ' ' +
+ String::Number(description.margin_right) + ' ' +
+ String::Number(description.margin_bottom) + ' ' +
+ String::Number(description.margin_left);
}
// static
diff --git a/chromium/third_party/blink/renderer/core/page/print_context.h b/chromium/third_party/blink/renderer/core/page/print_context.h
index 9bcde62284b..c58518d79c3 100644
--- a/chromium/third_party/blink/renderer/core/page/print_context.h
+++ b/chromium/third_party/blink/renderer/core/page/print_context.h
@@ -132,7 +132,7 @@ class CORE_EXPORT PrintContext : public GarbageCollected<PrintContext> {
bool linked_destinations_valid_;
};
-class ScopedPrintContext {
+class CORE_EXPORT ScopedPrintContext {
STACK_ALLOCATED();
public:
diff --git a/chromium/third_party/blink/renderer/core/page/scrolling/DEPS b/chromium/third_party/blink/renderer/core/page/scrolling/DEPS
index ad855a9b1a9..c9d5c528674 100644
--- a/chromium/third_party/blink/renderer/core/page/scrolling/DEPS
+++ b/chromium/third_party/blink/renderer/core/page/scrolling/DEPS
@@ -1,9 +1,3 @@
-include_rules = [
- "+cc/layers/painted_overlay_scrollbar_layer.h",
- "+cc/layers/painted_scrollbar_layer.h",
- "+cc/layers/solid_color_scrollbar_layer.h",
-]
-
specific_include_rules = {
"scrolling_test.cc": [
"+third_party/blink/renderer/core/exported/web_plugin_container_impl.h"
diff --git a/chromium/third_party/blink/renderer/core/page/scrolling/element_fragment_anchor.cc b/chromium/third_party/blink/renderer/core/page/scrolling/element_fragment_anchor.cc
index 6106f6d7784..66e45f475a4 100644
--- a/chromium/third_party/blink/renderer/core/page/scrolling/element_fragment_anchor.cc
+++ b/chromium/third_party/blink/renderer/core/page/scrolling/element_fragment_anchor.cc
@@ -9,6 +9,7 @@
#include "third_party/blink/renderer/core/display_lock/display_lock_context.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/element.h"
+#include "third_party/blink/renderer/core/dom/events/event.h"
#include "third_party/blink/renderer/core/dom/node.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/svg/svg_svg_element.h"
@@ -76,7 +77,6 @@ ElementFragmentAnchor* ElementFragmentAnchor::TryCreate(const KURL& url,
if (target) {
target->ActivateDisplayLockIfNeeded(
DisplayLockActivationReason::kFragmentNavigation);
- target->DispatchActivateInvisibleEventIfNeeded();
}
if (doc.IsSVGDocument() && (!frame.IsMainFrame() || !target))
@@ -89,6 +89,9 @@ ElementFragmentAnchor* ElementFragmentAnchor::TryCreate(const KURL& url,
if (!should_scroll)
return nullptr;
+ if (RuntimeEnabledFeatures::BeforeMatchEventEnabled())
+ anchor_node->DispatchEvent(*Event::Create(event_type_names::kBeforematch));
+
return MakeGarbageCollected<ElementFragmentAnchor>(*anchor_node, frame);
}
diff --git a/chromium/third_party/blink/renderer/core/page/scrolling/main_thread_scrolling_reasons_test.cc b/chromium/third_party/blink/renderer/core/page/scrolling/main_thread_scrolling_reasons_test.cc
index c0148282498..d8c85d609f0 100644
--- a/chromium/third_party/blink/renderer/core/page/scrolling/main_thread_scrolling_reasons_test.cc
+++ b/chromium/third_party/blink/renderer/core/page/scrolling/main_thread_scrolling_reasons_test.cc
@@ -26,6 +26,14 @@
namespace blink {
+#define EXPECT_MAIN_THREAD_SCROLLING_REASON(expected, actual) \
+ EXPECT_EQ(expected, actual) \
+ << " expected: " << cc::MainThreadScrollingReason::AsText(expected) \
+ << " actual: " << cc::MainThreadScrollingReason::AsText(actual)
+
+#define EXPECT_NO_MAIN_THREAD_SCROLLING_REASON(actual) \
+ EXPECT_EQ(cc::MainThreadScrollingReason::kNotScrollingOnMain, actual)
+
class MainThreadScrollingReasonsTest : public testing::Test {
public:
MainThreadScrollingReasonsTest() : base_url_("http://www.test.com/") {
@@ -134,9 +142,9 @@ TEST_F(MainThreadScrollingReasonsTest,
inner_frame_view->LayoutViewport()->LayerForScrolling();
ASSERT_TRUE(cc_scroll_layer);
ASSERT_TRUE(IsScrollable(cc_scroll_layer));
- ASSERT_TRUE(
- GetMainThreadScrollingReasons(cc_scroll_layer) &
- cc::MainThreadScrollingReason::kHasBackgroundAttachmentFixedObjects);
+ EXPECT_MAIN_THREAD_SCROLLING_REASON(
+ cc::MainThreadScrollingReason::kHasBackgroundAttachmentFixedObjects,
+ GetMainThreadScrollingReasons(cc_scroll_layer));
// Remove fixed background-attachment should make the iframe
// scroll on cc.
@@ -154,9 +162,8 @@ TEST_F(MainThreadScrollingReasonsTest,
layout_object->GetFrameView()->LayoutViewport()->LayerForScrolling();
ASSERT_TRUE(cc_scroll_layer);
ASSERT_TRUE(IsScrollable(cc_scroll_layer));
- ASSERT_FALSE(
- GetMainThreadScrollingReasons(cc_scroll_layer) &
- cc::MainThreadScrollingReason::kHasBackgroundAttachmentFixedObjects);
+ EXPECT_NO_MAIN_THREAD_SCROLLING_REASON(
+ GetMainThreadScrollingReasons(cc_scroll_layer));
// Force main frame to scroll on main thread. All its descendants
// should scroll on main thread as well.
@@ -175,9 +182,9 @@ TEST_F(MainThreadScrollingReasonsTest,
layout_object->GetFrameView()->LayoutViewport()->LayerForScrolling();
ASSERT_TRUE(cc_scroll_layer);
ASSERT_TRUE(IsScrollable(cc_scroll_layer));
- ASSERT_TRUE(
- GetMainThreadScrollingReasons(cc_scroll_layer) &
- cc::MainThreadScrollingReason::kHasBackgroundAttachmentFixedObjects);
+ EXPECT_MAIN_THREAD_SCROLLING_REASON(
+ cc::MainThreadScrollingReason::kHasBackgroundAttachmentFixedObjects,
+ GetMainThreadScrollingReasons(cc_scroll_layer));
}
// Upon resizing the content size, the main thread scrolling reason
@@ -202,9 +209,9 @@ TEST_F(MainThreadScrollingReasonsTest,
ASSERT_NO_EXCEPTION);
ForceFullCompositingUpdate();
- EXPECT_TRUE(
- GetViewMainThreadScrollingReasons() &
- cc::MainThreadScrollingReason::kHasBackgroundAttachmentFixedObjects);
+ EXPECT_MAIN_THREAD_SCROLLING_REASON(
+ cc::MainThreadScrollingReason::kHasBackgroundAttachmentFixedObjects,
+ GetViewMainThreadScrollingReasons());
// The main thread scrolling reason should be reset upon the following change.
element->setAttribute("style", "", ASSERT_NO_EXCEPTION);
@@ -291,7 +298,6 @@ TEST_F(MainThreadScrollingReasonsTest,
class NonCompositedMainThreadScrollingReasonsTest
: public MainThreadScrollingReasonsTest {
static const uint32_t kLCDTextRelatedReasons =
- cc::MainThreadScrollingReason::kHasOpacityAndLCDText |
cc::MainThreadScrollingReason::kHasTransformAndLCDText |
cc::MainThreadScrollingReason::kBackgroundNotOpaqueInRectAndLCDText |
cc::MainThreadScrollingReason::kIsNotStackingContextAndLCDText;
@@ -301,20 +307,27 @@ class NonCompositedMainThreadScrollingReasonsTest
RegisterMockedHttpURLLoad("two_scrollable_area.html");
NavigateTo(base_url_ + "two_scrollable_area.html");
}
- void TestNonCompositedReasons(const String& target, const uint32_t reason) {
+
+ void TestNonCompositedReasons(const AtomicString& style_class,
+ const uint32_t reason) {
GetWebView()->GetSettings()->SetPreferCompositingToLCDTextEnabled(false);
Document* document = GetFrame()->GetDocument();
Element* container = document->getElementById("scroller1");
- container->setAttribute("class", target.Utf8().c_str(),
- ASSERT_NO_EXCEPTION);
ForceFullCompositingUpdate();
PaintLayerScrollableArea* scrollable_area =
ToLayoutBoxModelObject(container->GetLayoutObject())
->GetScrollableArea();
ASSERT_TRUE(scrollable_area);
- EXPECT_TRUE(scrollable_area->GetNonCompositedMainThreadScrollingReasons() &
- reason);
+ EXPECT_NO_MAIN_THREAD_SCROLLING_REASON(
+ scrollable_area->GetNonCompositedMainThreadScrollingReasons());
+
+ container->classList().Add(style_class);
+ ForceFullCompositingUpdate();
+
+ ASSERT_TRUE(scrollable_area);
+ EXPECT_MAIN_THREAD_SCROLLING_REASON(
+ reason, scrollable_area->GetNonCompositedMainThreadScrollingReasons());
Element* container2 = document->getElementById("scroller2");
PaintLayerScrollableArea* scrollable_area2 =
@@ -322,45 +335,48 @@ class NonCompositedMainThreadScrollingReasonsTest
->GetScrollableArea();
ASSERT_TRUE(scrollable_area2);
// Different scrollable area should remain unaffected.
- EXPECT_FALSE(
- scrollable_area2->GetNonCompositedMainThreadScrollingReasons() &
- reason);
+ EXPECT_NO_MAIN_THREAD_SCROLLING_REASON(
+ scrollable_area2->GetNonCompositedMainThreadScrollingReasons());
LocalFrameView* frame_view = GetFrame()->View();
ASSERT_TRUE(frame_view);
- EXPECT_FALSE(frame_view->GetMainThreadScrollingReasons() & reason);
+ EXPECT_NO_MAIN_THREAD_SCROLLING_REASON(
+ frame_view->GetMainThreadScrollingReasons());
+
+ // Remove class from the scroller 1 would lead to scroll on impl.
- // Remove attribute from the scroller 1 would lead to scroll on impl.
- container->removeAttribute("class");
+ container->classList().Remove(style_class);
ForceFullCompositingUpdate();
- EXPECT_FALSE(scrollable_area->GetNonCompositedMainThreadScrollingReasons() &
- reason);
- EXPECT_FALSE(frame_view->GetMainThreadScrollingReasons() & reason);
+ EXPECT_NO_MAIN_THREAD_SCROLLING_REASON(
+ scrollable_area->GetNonCompositedMainThreadScrollingReasons());
+ EXPECT_NO_MAIN_THREAD_SCROLLING_REASON(
+ frame_view->GetMainThreadScrollingReasons());
// Add target attribute would again lead to scroll on main thread
- container->setAttribute("class", target.Utf8().c_str(),
- ASSERT_NO_EXCEPTION);
+ container->classList().Add(style_class);
ForceFullCompositingUpdate();
- EXPECT_TRUE(scrollable_area->GetNonCompositedMainThreadScrollingReasons() &
- reason);
- EXPECT_FALSE(frame_view->GetMainThreadScrollingReasons() & reason);
+ EXPECT_MAIN_THREAD_SCROLLING_REASON(
+ reason, scrollable_area->GetNonCompositedMainThreadScrollingReasons());
+ EXPECT_NO_MAIN_THREAD_SCROLLING_REASON(
+ frame_view->GetMainThreadScrollingReasons());
if ((reason & kLCDTextRelatedReasons) &&
!(reason & ~kLCDTextRelatedReasons)) {
GetWebView()->GetSettings()->SetPreferCompositingToLCDTextEnabled(true);
ForceFullCompositingUpdate();
- EXPECT_FALSE(
+ EXPECT_NO_MAIN_THREAD_SCROLLING_REASON(
scrollable_area->GetNonCompositedMainThreadScrollingReasons());
- EXPECT_FALSE(frame_view->GetMainThreadScrollingReasons());
+ EXPECT_NO_MAIN_THREAD_SCROLLING_REASON(
+ frame_view->GetMainThreadScrollingReasons());
}
}
};
TEST_F(NonCompositedMainThreadScrollingReasonsTest, TransparentTest) {
- TestNonCompositedReasons(
- "transparent", cc::MainThreadScrollingReason::kHasOpacityAndLCDText);
+ TestNonCompositedReasons("transparent",
+ cc::MainThreadScrollingReason::kNotScrollingOnMain);
}
TEST_F(NonCompositedMainThreadScrollingReasonsTest, TransformTest) {
@@ -374,9 +390,17 @@ TEST_F(NonCompositedMainThreadScrollingReasonsTest, BackgroundNotOpaqueTest) {
cc::MainThreadScrollingReason::kBackgroundNotOpaqueInRectAndLCDText);
}
+TEST_F(NonCompositedMainThreadScrollingReasonsTest,
+ CantPaintScrollingBackgroundTest) {
+ TestNonCompositedReasons(
+ "cant-paint-scrolling-background",
+ cc::MainThreadScrollingReason::kCantPaintScrollingBackground);
+}
+
TEST_F(NonCompositedMainThreadScrollingReasonsTest, ClipTest) {
TestNonCompositedReasons(
- "clip", cc::MainThreadScrollingReason::kHasClipRelatedProperty);
+ "clip", cc::MainThreadScrollingReason::kHasClipRelatedProperty |
+ cc::MainThreadScrollingReason::kCantPaintScrollingBackground);
}
TEST_F(NonCompositedMainThreadScrollingReasonsTest, ClipPathTest) {
@@ -385,83 +409,59 @@ TEST_F(NonCompositedMainThreadScrollingReasonsTest, ClipPathTest) {
Document* document = GetFrame()->GetDocument();
// Test ancestor with ClipPath
Element* element = document->body();
- element->setAttribute(html_names::kStyleAttr,
- "clip-path:circle(115px at 20px 20px);");
+ element->classList().Add("clip-path");
Element* container = document->getElementById("scroller1");
ASSERT_TRUE(container);
ForceFullCompositingUpdate();
PaintLayerScrollableArea* scrollable_area =
ToLayoutBoxModelObject(container->GetLayoutObject())->GetScrollableArea();
- EXPECT_TRUE(scrollable_area->GetNonCompositedMainThreadScrollingReasons() &
- clip_reason);
-
- EXPECT_FALSE(GetViewMainThreadScrollingReasons() & clip_reason);
+ EXPECT_MAIN_THREAD_SCROLLING_REASON(
+ clip_reason,
+ scrollable_area->GetNonCompositedMainThreadScrollingReasons());
+ EXPECT_NO_MAIN_THREAD_SCROLLING_REASON(GetViewMainThreadScrollingReasons());
// Remove clip path from ancestor.
- element->removeAttribute(html_names::kStyleAttr);
+ element->classList().Remove("clip-path");
ForceFullCompositingUpdate();
- EXPECT_FALSE(scrollable_area->GetNonCompositedMainThreadScrollingReasons() &
- clip_reason);
- EXPECT_FALSE(GetViewMainThreadScrollingReasons() & clip_reason);
+ EXPECT_NO_MAIN_THREAD_SCROLLING_REASON(
+ scrollable_area->GetNonCompositedMainThreadScrollingReasons());
+ EXPECT_NO_MAIN_THREAD_SCROLLING_REASON(GetViewMainThreadScrollingReasons());
// Test descendant with ClipPath
element = document->getElementById("content1");
ASSERT_TRUE(element);
- element->setAttribute(html_names::kStyleAttr,
- "clip-path:circle(115px at 20px 20px);");
+ element->classList().Add("clip-path");
ForceFullCompositingUpdate();
- EXPECT_TRUE(scrollable_area->GetNonCompositedMainThreadScrollingReasons() &
- clip_reason);
- EXPECT_FALSE(GetViewMainThreadScrollingReasons() & clip_reason);
+ EXPECT_MAIN_THREAD_SCROLLING_REASON(
+ clip_reason,
+ scrollable_area->GetNonCompositedMainThreadScrollingReasons());
+ EXPECT_NO_MAIN_THREAD_SCROLLING_REASON(GetViewMainThreadScrollingReasons());
// Remove clip path from descendant.
- element->removeAttribute(html_names::kStyleAttr);
+ element->classList().Remove("clip-path");
ForceFullCompositingUpdate();
- EXPECT_FALSE(scrollable_area->GetNonCompositedMainThreadScrollingReasons() &
- clip_reason);
- EXPECT_FALSE(GetViewMainThreadScrollingReasons() & clip_reason);
+ EXPECT_NO_MAIN_THREAD_SCROLLING_REASON(
+ scrollable_area->GetNonCompositedMainThreadScrollingReasons());
+ EXPECT_NO_MAIN_THREAD_SCROLLING_REASON(GetViewMainThreadScrollingReasons());
}
-TEST_F(NonCompositedMainThreadScrollingReasonsTest, LCDTextEnabledTest) {
- TestNonCompositedReasons(
- "transparent", cc::MainThreadScrollingReason::kHasOpacityAndLCDText);
+TEST_F(NonCompositedMainThreadScrollingReasonsTest, BoxShadowTest) {
+ TestNonCompositedReasons("box-shadow",
+ cc::MainThreadScrollingReason::kNotScrollingOnMain);
}
-TEST_F(NonCompositedMainThreadScrollingReasonsTest, BoxShadowTest) {
+TEST_F(NonCompositedMainThreadScrollingReasonsTest, InsetBoxShadowTest) {
TestNonCompositedReasons(
- "box-shadow",
- cc::MainThreadScrollingReason::kHasBoxShadowFromNonRootLayer);
+ "inset-box-shadow",
+ cc::MainThreadScrollingReason::kCantPaintScrollingBackground);
}
TEST_F(NonCompositedMainThreadScrollingReasonsTest, StackingContextTest) {
- GetWebView()->GetSettings()->SetPreferCompositingToLCDTextEnabled(false);
-
- Document* document = GetFrame()->GetDocument();
- Element* container = document->getElementById("scroller1");
- ASSERT_TRUE(container);
-
- ForceFullCompositingUpdate();
-
- // If a scroller contains all its children, it's not a stacking context.
- PaintLayerScrollableArea* scrollable_area =
- ToLayoutBoxModelObject(container->GetLayoutObject())->GetScrollableArea();
- ASSERT_TRUE(scrollable_area);
- EXPECT_TRUE(scrollable_area->GetNonCompositedMainThreadScrollingReasons() &
- cc::MainThreadScrollingReason::kIsNotStackingContextAndLCDText);
-
- GetWebView()->GetSettings()->SetPreferCompositingToLCDTextEnabled(true);
- ForceFullCompositingUpdate();
- EXPECT_FALSE(scrollable_area->GetNonCompositedMainThreadScrollingReasons() &
- cc::MainThreadScrollingReason::kIsNotStackingContextAndLCDText);
- GetWebView()->GetSettings()->SetPreferCompositingToLCDTextEnabled(false);
-
- // Adding "contain: paint" to force a stacking context leads to promotion.
- container->setAttribute("style", "contain: paint", ASSERT_NO_EXCEPTION);
- ForceFullCompositingUpdate();
-
- EXPECT_FALSE(scrollable_area->GetNonCompositedMainThreadScrollingReasons());
+ TestNonCompositedReasons(
+ "non-stacking-context",
+ cc::MainThreadScrollingReason::kIsNotStackingContextAndLCDText);
}
TEST_F(NonCompositedMainThreadScrollingReasonsTest,
@@ -481,7 +481,8 @@ TEST_F(NonCompositedMainThreadScrollingReasonsTest,
PaintLayerScrollableArea* scrollable_area =
ToLayoutBoxModelObject(container->GetLayoutObject())->GetScrollableArea();
ASSERT_TRUE(scrollable_area);
- EXPECT_FALSE(scrollable_area->GetNonCompositedMainThreadScrollingReasons());
+ EXPECT_NO_MAIN_THREAD_SCROLLING_REASON(
+ scrollable_area->GetNonCompositedMainThreadScrollingReasons());
Element* container2 = document->getElementById("scroller2");
ASSERT_TRUE(container2);
diff --git a/chromium/third_party/blink/renderer/core/page/scrolling/root_scroller_test.cc b/chromium/third_party/blink/renderer/core/page/scrolling/root_scroller_test.cc
index 4f8f3b4d58a..04f670c9f17 100644
--- a/chromium/third_party/blink/renderer/core/page/scrolling/root_scroller_test.cc
+++ b/chromium/third_party/blink/renderer/core/page/scrolling/root_scroller_test.cc
@@ -3,8 +3,8 @@
// found in the LICENSE file.
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/input/web_coalesced_input_event.h"
#include "third_party/blink/public/common/page/page_zoom.h"
-#include "third_party/blink/public/platform/web_coalesced_input_event.h"
#include "third_party/blink/public/platform/web_url_loader_mock_factory.h"
#include "third_party/blink/public/web/web_console_message.h"
#include "third_party/blink/public/web/web_hit_test_result.h"
@@ -166,14 +166,14 @@ class RootScrollerTest : public testing::Test,
WebGestureEvent event(type, WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests(), device);
event.SetPositionInWidget(gfx::PointF(100, 100));
- if (type == WebInputEvent::kGestureScrollUpdate) {
+ if (type == WebInputEvent::Type::kGestureScrollUpdate) {
event.data.scroll_update.delta_x = delta_x;
event.data.scroll_update.delta_y = delta_y;
- } else if (type == WebInputEvent::kGestureScrollBegin) {
+ } else if (type == WebInputEvent::Type::kGestureScrollBegin) {
event.data.scroll_begin.delta_x_hint = delta_x;
event.data.scroll_begin.delta_y_hint = delta_y;
}
- return WebCoalescedInputEvent(event);
+ return WebCoalescedInputEvent(event, ui::LatencyInfo());
}
WebViewImpl* InitializeInternal(
@@ -260,7 +260,7 @@ TEST_F(RootScrollerTest, TestSetRootScroller) {
double maximum_scroll = 550;
GetWebView()->MainFrameWidget()->HandleInputEvent(
- GenerateTouchGestureEvent(WebInputEvent::kGestureScrollBegin));
+ GenerateTouchGestureEvent(WebInputEvent::Type::kGestureScrollBegin));
{
// Scrolling over the #container DIV should cause the browser controls to
@@ -268,7 +268,7 @@ TEST_F(RootScrollerTest, TestSetRootScroller) {
EXPECT_FLOAT_EQ(1, GetBrowserControls().TopShownRatio());
EXPECT_FLOAT_EQ(1, GetBrowserControls().BottomShownRatio());
GetWebView()->MainFrameWidget()->HandleInputEvent(
- GenerateTouchGestureEvent(WebInputEvent::kGestureScrollUpdate, 0,
+ GenerateTouchGestureEvent(WebInputEvent::Type::kGestureScrollUpdate, 0,
-GetBrowserControls().TopHeight()));
EXPECT_FLOAT_EQ(0, GetBrowserControls().TopShownRatio());
EXPECT_FLOAT_EQ(0, GetBrowserControls().BottomShownRatio());
@@ -277,7 +277,7 @@ TEST_F(RootScrollerTest, TestSetRootScroller) {
{
// Make sure we're actually scrolling the DIV and not the LocalFrameView.
GetWebView()->MainFrameWidget()->HandleInputEvent(GenerateTouchGestureEvent(
- WebInputEvent::kGestureScrollUpdate, 0, -100));
+ WebInputEvent::Type::kGestureScrollUpdate, 0, -100));
EXPECT_FLOAT_EQ(100, container->scrollTop());
EXPECT_FLOAT_EQ(
0, MainFrameView()->LayoutViewport()->GetScrollOffset().Height());
@@ -290,7 +290,7 @@ TEST_F(RootScrollerTest, TestSetRootScroller) {
DidOverscroll(gfx::Vector2dF(0, 50), gfx::Vector2dF(0, 50),
gfx::PointF(100, 100), gfx::Vector2dF()));
GetWebView()->MainFrameWidget()->HandleInputEvent(GenerateTouchGestureEvent(
- WebInputEvent::kGestureScrollUpdate, 0, -500));
+ WebInputEvent::Type::kGestureScrollUpdate, 0, -500));
EXPECT_FLOAT_EQ(maximum_scroll, container->scrollTop());
EXPECT_FLOAT_EQ(
0, MainFrameView()->LayoutViewport()->GetScrollOffset().Height());
@@ -302,8 +302,8 @@ TEST_F(RootScrollerTest, TestSetRootScroller) {
EXPECT_CALL(client,
DidOverscroll(gfx::Vector2dF(0, 20), gfx::Vector2dF(0, 70),
gfx::PointF(100, 100), gfx::Vector2dF()));
- GetWebView()->MainFrameWidget()->HandleInputEvent(
- GenerateTouchGestureEvent(WebInputEvent::kGestureScrollUpdate, 0, -20));
+ GetWebView()->MainFrameWidget()->HandleInputEvent(GenerateTouchGestureEvent(
+ WebInputEvent::Type::kGestureScrollUpdate, 0, -20));
EXPECT_FLOAT_EQ(maximum_scroll, container->scrollTop());
EXPECT_FLOAT_EQ(
0, MainFrameView()->LayoutViewport()->GetScrollOffset().Height());
@@ -311,42 +311,42 @@ TEST_F(RootScrollerTest, TestSetRootScroller) {
}
GetWebView()->MainFrameWidget()->HandleInputEvent(
- GenerateTouchGestureEvent(WebInputEvent::kGestureScrollEnd));
+ GenerateTouchGestureEvent(WebInputEvent::Type::kGestureScrollEnd));
{
// Make sure a new gesture scroll still won't scroll the frameview and
// overscrolls.
GetWebView()->MainFrameWidget()->HandleInputEvent(
- GenerateTouchGestureEvent(WebInputEvent::kGestureScrollBegin));
+ GenerateTouchGestureEvent(WebInputEvent::Type::kGestureScrollBegin));
EXPECT_CALL(client,
DidOverscroll(gfx::Vector2dF(0, 30), gfx::Vector2dF(0, 30),
gfx::PointF(100, 100), gfx::Vector2dF()));
- GetWebView()->MainFrameWidget()->HandleInputEvent(
- GenerateTouchGestureEvent(WebInputEvent::kGestureScrollUpdate, 0, -30));
+ GetWebView()->MainFrameWidget()->HandleInputEvent(GenerateTouchGestureEvent(
+ WebInputEvent::Type::kGestureScrollUpdate, 0, -30));
EXPECT_FLOAT_EQ(maximum_scroll, container->scrollTop());
EXPECT_FLOAT_EQ(
0, MainFrameView()->LayoutViewport()->GetScrollOffset().Height());
Mock::VerifyAndClearExpectations(&client);
GetWebView()->MainFrameWidget()->HandleInputEvent(
- GenerateTouchGestureEvent(WebInputEvent::kGestureScrollEnd));
+ GenerateTouchGestureEvent(WebInputEvent::Type::kGestureScrollEnd));
}
{
// Scrolling up should show the browser controls.
GetWebView()->MainFrameWidget()->HandleInputEvent(
- GenerateTouchGestureEvent(WebInputEvent::kGestureScrollBegin));
+ GenerateTouchGestureEvent(WebInputEvent::Type::kGestureScrollBegin));
EXPECT_FLOAT_EQ(0, GetBrowserControls().TopShownRatio());
EXPECT_FLOAT_EQ(0, GetBrowserControls().BottomShownRatio());
- GetWebView()->MainFrameWidget()->HandleInputEvent(
- GenerateTouchGestureEvent(WebInputEvent::kGestureScrollUpdate, 0, 30));
+ GetWebView()->MainFrameWidget()->HandleInputEvent(GenerateTouchGestureEvent(
+ WebInputEvent::Type::kGestureScrollUpdate, 0, 30));
EXPECT_FLOAT_EQ(0.6, GetBrowserControls().TopShownRatio());
EXPECT_FLOAT_EQ(0.6, GetBrowserControls().BottomShownRatio());
GetWebView()->MainFrameWidget()->HandleInputEvent(
- GenerateTouchGestureEvent(WebInputEvent::kGestureScrollEnd));
+ GenerateTouchGestureEvent(WebInputEvent::Type::kGestureScrollEnd));
}
// Reset manually to avoid lifetime issues with custom WebViewClient.
@@ -803,12 +803,12 @@ TEST_F(RootScrollerTest, RemoteMainFrame) {
// Try scrolling in the iframe.
{
- widget->HandleInputEvent(
- GenerateWheelGestureEvent(WebInputEvent::kGestureScrollBegin, 0, -100));
widget->HandleInputEvent(GenerateWheelGestureEvent(
- WebInputEvent::kGestureScrollUpdate, 0, -100));
+ WebInputEvent::Type::kGestureScrollBegin, 0, -100));
+ widget->HandleInputEvent(GenerateWheelGestureEvent(
+ WebInputEvent::Type::kGestureScrollUpdate, 0, -100));
widget->HandleInputEvent(
- GenerateWheelGestureEvent(WebInputEvent::kGestureScrollEnd));
+ GenerateWheelGestureEvent(WebInputEvent::Type::kGestureScrollEnd));
EXPECT_EQ(100, container->scrollTop());
}
@@ -820,12 +820,12 @@ TEST_F(RootScrollerTest, RemoteMainFrame) {
// Try scrolling in the iframe now that it has a root scroller set.
{
- widget->HandleInputEvent(
- GenerateWheelGestureEvent(WebInputEvent::kGestureScrollBegin, 0, -100));
widget->HandleInputEvent(GenerateWheelGestureEvent(
- WebInputEvent::kGestureScrollUpdate, 0, -100));
+ WebInputEvent::Type::kGestureScrollBegin, 0, -100));
+ widget->HandleInputEvent(GenerateWheelGestureEvent(
+ WebInputEvent::Type::kGestureScrollUpdate, 0, -100));
widget->HandleInputEvent(
- GenerateWheelGestureEvent(WebInputEvent::kGestureScrollEnd));
+ GenerateWheelGestureEvent(WebInputEvent::Type::kGestureScrollEnd));
// TODO(bokan): This doesn't work right now because we notice in
// Element::nativeApplyScroll that the container is the
@@ -1015,22 +1015,22 @@ TEST_F(RootScrollerTest, TopControlsAdjustmentAppliedToRootScroller) {
ASSERT_EQ(1000 - 400, container_scroller->MaximumScrollOffset().Height());
GetWebView()->MainFrameWidget()->HandleInputEvent(
- GenerateTouchGestureEvent(WebInputEvent::kGestureScrollBegin));
+ GenerateTouchGestureEvent(WebInputEvent::Type::kGestureScrollBegin));
ASSERT_EQ(1, GetBrowserControls().TopShownRatio());
ASSERT_EQ(1, GetBrowserControls().BottomShownRatio());
GetWebView()->MainFrameWidget()->HandleInputEvent(
- GenerateTouchGestureEvent(WebInputEvent::kGestureScrollUpdate, 0,
+ GenerateTouchGestureEvent(WebInputEvent::Type::kGestureScrollUpdate, 0,
-GetBrowserControls().TopHeight()));
ASSERT_EQ(0, GetBrowserControls().TopShownRatio());
ASSERT_EQ(0, GetBrowserControls().BottomShownRatio());
EXPECT_EQ(1000 - 450, container_scroller->MaximumScrollOffset().Height());
- GetWebView()->MainFrameWidget()->HandleInputEvent(
- GenerateTouchGestureEvent(WebInputEvent::kGestureScrollUpdate, 0, -3000));
+ GetWebView()->MainFrameWidget()->HandleInputEvent(GenerateTouchGestureEvent(
+ WebInputEvent::Type::kGestureScrollUpdate, 0, -3000));
EXPECT_EQ(1000 - 450, container_scroller->GetScrollOffset().Height());
GetWebView()->MainFrameWidget()->HandleInputEvent(
- GenerateTouchGestureEvent(WebInputEvent::kGestureScrollEnd));
+ GenerateTouchGestureEvent(WebInputEvent::Type::kGestureScrollEnd));
GetWebView()->ResizeWithBrowserControls(IntSize(400, 450), 50, 50, false);
EXPECT_EQ(1000 - 450, container_scroller->MaximumScrollOffset().Height());
}
@@ -1063,11 +1063,11 @@ TEST_F(RootScrollerTest, RotationAnchoring) {
GetWebView()->SetPageScaleFactor(2);
GetWebView()->MainFrameWidget()->HandleInputEvent(
- GenerateTouchGestureEvent(WebInputEvent::kGestureScrollBegin));
+ GenerateTouchGestureEvent(WebInputEvent::Type::kGestureScrollBegin));
GetWebView()->MainFrameWidget()->HandleInputEvent(GenerateTouchGestureEvent(
- WebInputEvent::kGestureScrollUpdate, -scroll_x, -scroll_y));
+ WebInputEvent::Type::kGestureScrollUpdate, -scroll_x, -scroll_y));
GetWebView()->MainFrameWidget()->HandleInputEvent(
- GenerateTouchGestureEvent(WebInputEvent::kGestureScrollEnd));
+ GenerateTouchGestureEvent(WebInputEvent::Type::kGestureScrollEnd));
// The visual viewport should be 1.5 screens scrolled so that the target
// occupies the bottom quadrant of the layout viewport.
@@ -1303,7 +1303,7 @@ TEST_F(RootScrollerSimTest, NonLifecycleLayoutDoesntCauseReselection) {
ASSERT_EQ(container,
GetDocument().GetRootScrollerController().EffectiveRootScroller());
- container->style()->setProperty(GetDocument().ToExecutionContext(), "width",
+ container->style()->setProperty(GetDocument().GetExecutionContext(), "width",
"95%", String(), ASSERT_NO_EXCEPTION);
ASSERT_TRUE(Compositor().NeedsBeginFrame());
@@ -1623,14 +1623,14 @@ TEST_F(ImplicitRootScrollerSimTest, ImplicitRootScroller) {
String& style_val = std::get<1>(test_case);
Node* expected_root_scroller = std::get<2>(test_case);
- container->style()->setProperty(GetDocument().ToExecutionContext(), style,
+ container->style()->setProperty(GetDocument().GetExecutionContext(), style,
style_val, String(), ASSERT_NO_EXCEPTION);
Compositor().BeginFrame();
ASSERT_EQ(expected_root_scroller,
GetDocument().GetRootScrollerController().EffectiveRootScroller())
<< "Failed to set rootScroller after setting " << std::get<0>(test_case)
<< ": " << std::get<1>(test_case);
- container->style()->setProperty(GetDocument().ToExecutionContext(),
+ container->style()->setProperty(GetDocument().GetExecutionContext(),
std::get<0>(test_case), String(), String(),
ASSERT_NO_EXCEPTION);
Compositor().BeginFrame();
@@ -1651,7 +1651,7 @@ TEST_F(ImplicitRootScrollerSimTest, ImplicitRootScroller) {
String& style_val = std::get<1>(test_case);
Node* expected_root_scroller = &GetDocument();
- container->style()->setProperty(GetDocument().ToExecutionContext(), style,
+ container->style()->setProperty(GetDocument().GetExecutionContext(), style,
style_val, String(), ASSERT_NO_EXCEPTION);
Compositor().BeginFrame();
ASSERT_EQ(expected_root_scroller,
@@ -1659,7 +1659,7 @@ TEST_F(ImplicitRootScrollerSimTest, ImplicitRootScroller) {
<< "Failed to set rootScroller after setting " << std::get<0>(test_case)
<< ": " << std::get<1>(test_case);
- container->style()->setProperty(GetDocument().ToExecutionContext(),
+ container->style()->setProperty(GetDocument().GetExecutionContext(),
std::get<0>(test_case), String(), String(),
ASSERT_NO_EXCEPTION);
Compositor().BeginFrame();
@@ -1705,9 +1705,9 @@ TEST_F(ImplicitRootScrollerSimTest, ImplicitRootScrollerAddOverflow) {
<< "Shouldn't promote 'container' since it has no overflow.";
Element* spacer = GetDocument().getElementById("spacer");
- spacer->style()->setProperty(GetDocument().ToExecutionContext(), "height",
+ spacer->style()->setProperty(GetDocument().GetExecutionContext(), "height",
"2000px", String(), ASSERT_NO_EXCEPTION);
- spacer->style()->setProperty(GetDocument().ToExecutionContext(), "width",
+ spacer->style()->setProperty(GetDocument().GetExecutionContext(), "width",
"2000px", String(), ASSERT_NO_EXCEPTION);
Compositor().BeginFrame();
Element* container = GetDocument().getElementById("container");
@@ -1817,9 +1817,9 @@ TEST_F(ImplicitRootScrollerSimTest,
GetDocument().GetRootScrollerController().EffectiveRootScroller());
Element* overflow = GetDocument().getElementById("overflow");
- overflow->style()->setProperty(GetDocument().ToExecutionContext(), "height",
+ overflow->style()->setProperty(GetDocument().GetExecutionContext(), "height",
"10px", String(), ASSERT_NO_EXCEPTION);
- overflow->style()->setProperty(GetDocument().ToExecutionContext(), "width",
+ overflow->style()->setProperty(GetDocument().GetExecutionContext(), "width",
"10px", String(), ASSERT_NO_EXCEPTION);
Compositor().BeginFrame();
EXPECT_EQ(&GetDocument(),
@@ -1870,21 +1870,22 @@ TEST_F(ImplicitRootScrollerSimTest, ImplicitRootScrollerVisibilityCondition) {
ASSERT_EQ(container,
GetDocument().GetRootScrollerController().EffectiveRootScroller());
- container->style()->setProperty(GetDocument().ToExecutionContext(), "opacity",
- "0.5", String(), ASSERT_NO_EXCEPTION);
+ container->style()->setProperty(GetDocument().GetExecutionContext(),
+ "opacity", "0.5", String(),
+ ASSERT_NO_EXCEPTION);
Compositor().BeginFrame();
EXPECT_EQ(&GetDocument(),
GetDocument().GetRootScrollerController().EffectiveRootScroller())
<< "Adding opacity to 'container' causes it to be demoted.";
- container->style()->setProperty(GetDocument().ToExecutionContext(), "opacity",
- "", String(), ASSERT_NO_EXCEPTION);
+ container->style()->setProperty(GetDocument().GetExecutionContext(),
+ "opacity", "", String(), ASSERT_NO_EXCEPTION);
Compositor().BeginFrame();
EXPECT_EQ(container,
GetDocument().GetRootScrollerController().EffectiveRootScroller())
<< "Removing opacity from 'container' causes it to be promoted.";
- container->style()->setProperty(GetDocument().ToExecutionContext(),
+ container->style()->setProperty(GetDocument().GetExecutionContext(),
"visibility", "hidden", String(),
ASSERT_NO_EXCEPTION);
Compositor().BeginFrame();
@@ -1892,7 +1893,7 @@ TEST_F(ImplicitRootScrollerSimTest, ImplicitRootScrollerVisibilityCondition) {
GetDocument().GetRootScrollerController().EffectiveRootScroller())
<< "visibility:hidden causes 'container' to be demoted.";
- container->style()->setProperty(GetDocument().ToExecutionContext(),
+ container->style()->setProperty(GetDocument().GetExecutionContext(),
"visibility", "collapse", String(),
ASSERT_NO_EXCEPTION);
Compositor().BeginFrame();
@@ -1900,7 +1901,7 @@ TEST_F(ImplicitRootScrollerSimTest, ImplicitRootScrollerVisibilityCondition) {
GetDocument().GetRootScrollerController().EffectiveRootScroller())
<< "visibility:collapse doesn't cause 'container' to be promoted.";
- container->style()->setProperty(GetDocument().ToExecutionContext(),
+ container->style()->setProperty(GetDocument().GetExecutionContext(),
"visibility", "visible", String(),
ASSERT_NO_EXCEPTION);
Compositor().BeginFrame();
@@ -1944,7 +1945,7 @@ TEST_F(ImplicitRootScrollerSimTest, ImplicitRootScrollerIframe) {
ASSERT_EQ(container,
GetDocument().GetRootScrollerController().EffectiveRootScroller());
- container->style()->setProperty(GetDocument().ToExecutionContext(), "height",
+ container->style()->setProperty(GetDocument().GetExecutionContext(), "height",
"95%", String(), ASSERT_NO_EXCEPTION);
Compositor().BeginFrame();
@@ -1986,7 +1987,7 @@ TEST_F(ImplicitRootScrollerSimTest, UseCounterNegative) {
EXPECT_FALSE(
GetDocument().IsUseCounted(WebFeature::kActivatedImplicitRootScroller));
- container->style()->setProperty(GetDocument().ToExecutionContext(), "height",
+ container->style()->setProperty(GetDocument().GetExecutionContext(), "height",
"150%", String(), ASSERT_NO_EXCEPTION);
Compositor().BeginFrame();
@@ -2034,7 +2035,7 @@ TEST_F(ImplicitRootScrollerSimTest, UseCounterPositive) {
EXPECT_TRUE(
GetDocument().IsUseCounted(WebFeature::kActivatedImplicitRootScroller));
- container->style()->setProperty(GetDocument().ToExecutionContext(), "height",
+ container->style()->setProperty(GetDocument().GetExecutionContext(), "height",
"150%", String(), ASSERT_NO_EXCEPTION);
Compositor().BeginFrame();
@@ -2085,7 +2086,7 @@ TEST_F(ImplicitRootScrollerSimTest, UseCounterPositiveAfterLoad) {
EXPECT_FALSE(
GetDocument().IsUseCounted(WebFeature::kActivatedImplicitRootScroller));
- container->style()->setProperty(GetDocument().ToExecutionContext(), "height",
+ container->style()->setProperty(GetDocument().GetExecutionContext(), "height",
"100%", String(), ASSERT_NO_EXCEPTION);
Compositor().BeginFrame();
@@ -2187,8 +2188,9 @@ TEST_F(ImplicitRootScrollerSimTest, DontPromoteWhenMultipleAreValid) {
// Now make the second one invalid, that should cause the first to be
// promoted.
Element* container2 = GetDocument().getElementById("container2");
- container2->style()->setProperty(GetDocument().ToExecutionContext(), "height",
- "95%", String(), ASSERT_NO_EXCEPTION);
+ container2->style()->setProperty(GetDocument().GetExecutionContext(),
+ "height", "95%", String(),
+ ASSERT_NO_EXCEPTION);
Compositor().BeginFrame();
Element* container = GetDocument().getElementById("container");
@@ -2449,7 +2451,7 @@ TEST_F(ImplicitRootScrollerSimTest,
// Set the height explicitly to a new value in-between. The root scroller
// should be demoted.
- container->style()->setProperty(GetDocument().ToExecutionContext(), "height",
+ container->style()->setProperty(GetDocument().GetExecutionContext(), "height",
"601px", String(), ASSERT_NO_EXCEPTION);
Compositor().BeginFrame();
EXPECT_EQ(GetDocument(),
@@ -2457,7 +2459,7 @@ TEST_F(ImplicitRootScrollerSimTest,
// Reset back to valid and hide the top controls. Zoom to 2x. Ensure we're
// still considered valid.
- container->style()->setProperty(GetDocument().ToExecutionContext(), "height",
+ container->style()->setProperty(GetDocument().GetExecutionContext(), "height",
"", String(), ASSERT_NO_EXCEPTION);
Compositor().BeginFrame();
EXPECT_EQ(container,
@@ -2519,14 +2521,14 @@ TEST_F(ImplicitRootScrollerSimTest, ContinuallyReevaluateImplicitPromotion) {
GetDocument().GetRootScrollerController().EffectiveRootScroller());
// The container now has overflow but still doesn't scroll.
- spacer->style()->setProperty(GetDocument().ToExecutionContext(), "height",
+ spacer->style()->setProperty(GetDocument().GetExecutionContext(), "height",
"2000px", String(), ASSERT_NO_EXCEPTION);
Compositor().BeginFrame();
EXPECT_EQ(GetDocument(),
GetDocument().GetRootScrollerController().EffectiveRootScroller());
// The container is now scrollable and should be promoted.
- container->style()->setProperty(GetDocument().ToExecutionContext(),
+ container->style()->setProperty(GetDocument().GetExecutionContext(),
"overflow", "auto", String(),
ASSERT_NO_EXCEPTION);
Compositor().BeginFrame();
@@ -2534,7 +2536,7 @@ TEST_F(ImplicitRootScrollerSimTest, ContinuallyReevaluateImplicitPromotion) {
GetDocument().GetRootScrollerController().EffectiveRootScroller());
// The container is now not viewport-filling so it should be demoted.
- container->style()->setProperty(GetDocument().ToExecutionContext(),
+ container->style()->setProperty(GetDocument().GetExecutionContext(),
"transform", "translateX(-50px)", String(),
ASSERT_NO_EXCEPTION);
Compositor().BeginFrame();
@@ -2542,7 +2544,7 @@ TEST_F(ImplicitRootScrollerSimTest, ContinuallyReevaluateImplicitPromotion) {
GetDocument().GetRootScrollerController().EffectiveRootScroller());
// The container is viewport-filling again so it should be promoted.
- parent->style()->setProperty(GetDocument().ToExecutionContext(), "transform",
+ parent->style()->setProperty(GetDocument().GetExecutionContext(), "transform",
"translateX(50px)", String(),
ASSERT_NO_EXCEPTION);
Compositor().BeginFrame();
@@ -2550,7 +2552,7 @@ TEST_F(ImplicitRootScrollerSimTest, ContinuallyReevaluateImplicitPromotion) {
GetDocument().GetRootScrollerController().EffectiveRootScroller());
// No longer scrollable so demote.
- container->style()->setProperty(GetDocument().ToExecutionContext(),
+ container->style()->setProperty(GetDocument().GetExecutionContext(),
"overflow", "hidden", String(),
ASSERT_NO_EXCEPTION);
Compositor().BeginFrame();
@@ -2601,7 +2603,7 @@ TEST_F(ImplicitRootScrollerSimTest, IframeScrollingAffectsPromotion) {
// Allows scrolling now so promote.
inner_html_element->style()->setProperty(
- container->contentDocument()->ToExecutionContext(), "overflow", "auto",
+ To<LocalDOMWindow>(container->contentWindow()), "overflow", "auto",
String(), ASSERT_NO_EXCEPTION);
Compositor().BeginFrame();
EXPECT_EQ(container,
@@ -2609,7 +2611,7 @@ TEST_F(ImplicitRootScrollerSimTest, IframeScrollingAffectsPromotion) {
// Demote again.
inner_html_element->style()->setProperty(
- container->contentDocument()->ToExecutionContext(), "overflow", "hidden",
+ To<LocalDOMWindow>(container->contentWindow()), "overflow", "hidden",
String(), ASSERT_NO_EXCEPTION);
Compositor().BeginFrame();
EXPECT_EQ(GetDocument(),
@@ -2912,7 +2914,7 @@ TEST_F(ImplicitRootScrollerSimTest, OverflowInMainDocumentRestrictsImplicit) {
<< "iframe shouldn't be promoted due to overflow in the main document.";
Element* spacer = GetDocument().getElementById("spacer");
- spacer->style()->setProperty(GetDocument().ToExecutionContext(), "height",
+ spacer->style()->setProperty(GetDocument().GetExecutionContext(), "height",
"100%", String(), ASSERT_NO_EXCEPTION);
Compositor().BeginFrame();
@@ -2975,7 +2977,7 @@ TEST_F(ImplicitRootScrollerSimTest, OverflowHiddenDoesntRestrictImplicit) {
<< "iframe should be promoted since document's overflow is hidden.";
Element* html = GetDocument().documentElement();
- html->style()->setProperty(GetDocument().ToExecutionContext(), "overflow",
+ html->style()->setProperty(GetDocument().GetExecutionContext(), "overflow",
"auto", String(), ASSERT_NO_EXCEPTION);
Compositor().BeginFrame();
@@ -2983,7 +2985,7 @@ TEST_F(ImplicitRootScrollerSimTest, OverflowHiddenDoesntRestrictImplicit) {
GetDocument().GetRootScrollerController().EffectiveRootScroller())
<< "iframe should now be demoted since main document scrolls overflow.";
- html->style()->setProperty(GetDocument().ToExecutionContext(), "overflow",
+ html->style()->setProperty(GetDocument().GetExecutionContext(), "overflow",
"visible", String(), ASSERT_NO_EXCEPTION);
Compositor().BeginFrame();
@@ -3068,7 +3070,7 @@ TEST_F(ImplicitRootScrollerSimTest, ClippingAncestorPreventsPromotion) {
GetDocument().GetRootScrollerController().EffectiveRootScroller())
<< "iframe should start off promoted.";
- ancestor->style()->setProperty(GetDocument().ToExecutionContext(), style,
+ ancestor->style()->setProperty(GetDocument().GetExecutionContext(), style,
style_val, String(), ASSERT_NO_EXCEPTION);
Compositor().BeginFrame();
@@ -3077,7 +3079,7 @@ TEST_F(ImplicitRootScrollerSimTest, ClippingAncestorPreventsPromotion) {
<< "iframe should be demoted since ancestor has " << style << ": "
<< style_val;
- ancestor->style()->setProperty(GetDocument().ToExecutionContext(), style,
+ ancestor->style()->setProperty(GetDocument().GetExecutionContext(), style,
String(), String(), ASSERT_NO_EXCEPTION);
Compositor().BeginFrame();
ASSERT_EQ(iframe,
diff --git a/chromium/third_party/blink/renderer/core/page/scrolling/scroll_metrics_test.cc b/chromium/third_party/blink/renderer/core/page/scrolling/scroll_metrics_test.cc
index dc00e7d8401..c3fa3decc25 100644
--- a/chromium/third_party/blink/renderer/core/page/scrolling/scroll_metrics_test.cc
+++ b/chromium/third_party/blink/renderer/core/page/scrolling/scroll_metrics_test.cc
@@ -57,7 +57,7 @@ class ScrollBeginEventBuilder : public WebGestureEvent {
ScrollBeginEventBuilder(FloatPoint position,
FloatPoint delta,
WebGestureDevice device)
- : WebGestureEvent(WebInputEvent::kGestureScrollBegin,
+ : WebGestureEvent(WebInputEvent::Type::kGestureScrollBegin,
WebInputEvent::kNoModifiers,
base::TimeTicks::Now(),
device) {
@@ -71,7 +71,7 @@ class ScrollBeginEventBuilder : public WebGestureEvent {
class ScrollUpdateEventBuilder : public WebGestureEvent {
public:
ScrollUpdateEventBuilder() : WebGestureEvent() {
- type_ = WebInputEvent::kGestureScrollUpdate;
+ type_ = WebInputEvent::Type::kGestureScrollUpdate;
data.scroll_update.delta_x = 0.0f;
data.scroll_update.delta_y = 1.0f;
data.scroll_update.velocity_x = 0;
@@ -83,7 +83,7 @@ class ScrollUpdateEventBuilder : public WebGestureEvent {
class ScrollEndEventBuilder : public WebGestureEvent {
public:
ScrollEndEventBuilder() : WebGestureEvent() {
- type_ = WebInputEvent::kGestureScrollEnd;
+ type_ = WebInputEvent::Type::kGestureScrollEnd;
frame_scale_ = 1;
}
};
@@ -129,10 +129,10 @@ TEST_F(NonCompositedMainThreadScrollingReasonRecordTest,
SetUpHtml(R"HTML(
<style>
.box { overflow:scroll; width: 100px; height: 100px; }
- .translucent { opacity: 0.5; }
+ .transform { transform: translateX(0.5px); }
.spacer { height: 1000px; }
</style>
- <div id='box' class='translucent box'>
+ <div id='box' class='transform box'>
<div class='spacer'></div>
</div>
)HTML");
@@ -144,17 +144,17 @@ TEST_F(NonCompositedMainThreadScrollingReasonRecordTest,
// Test touch scroll.
Scroll(box, WebGestureDevice::kTouchscreen);
- EXPECT_TOUCH_BUCKET(kHasOpacityAndLCDText, 1);
+ EXPECT_TOUCH_BUCKET(kHasTransformAndLCDText, 1);
EXPECT_TOUCH_BUCKET(kBackgroundNotOpaqueInRectAndLCDText, 1);
Scroll(box, WebGestureDevice::kTouchscreen);
- EXPECT_TOUCH_BUCKET(kHasOpacityAndLCDText, 2);
+ EXPECT_TOUCH_BUCKET(kHasTransformAndLCDText, 2);
EXPECT_TOUCH_BUCKET(kBackgroundNotOpaqueInRectAndLCDText, 2);
EXPECT_TOUCH_TOTAL(4);
// Test wheel scroll.
Scroll(box, WebGestureDevice::kTouchpad);
- EXPECT_WHEEL_BUCKET(kHasOpacityAndLCDText, 1);
+ EXPECT_WHEEL_BUCKET(kHasTransformAndLCDText, 1);
EXPECT_WHEEL_BUCKET(kBackgroundNotOpaqueInRectAndLCDText, 1);
EXPECT_WHEEL_TOTAL(2);
}
@@ -164,11 +164,11 @@ TEST_F(NonCompositedMainThreadScrollingReasonRecordTest,
SetUpHtml(R"HTML(
<style>
.box { overflow:scroll; width: 100px; height: 100px; }
- .translucent { opacity: 0.5; }
+ .transform { transform: scale(0.8); }
.composited { will-change: transform; }
.spacer { height: 1000px; }
</style>
- <div id='box' class='translucent box'>
+ <div id='box' class='transform box'>
<div class='spacer'></div>
</div>
)HTML");
@@ -181,17 +181,17 @@ TEST_F(NonCompositedMainThreadScrollingReasonRecordTest,
HistogramTester histogram_tester;
Scroll(box, WebGestureDevice::kTouchpad);
- EXPECT_WHEEL_BUCKET(kHasOpacityAndLCDText, 1);
+ EXPECT_WHEEL_BUCKET(kHasTransformAndLCDText, 1);
EXPECT_WHEEL_BUCKET(kBackgroundNotOpaqueInRectAndLCDText, 1);
EXPECT_WHEEL_TOTAL(2);
- box->setAttribute("class", "composited translucent box");
+ box->setAttribute("class", "composited transform box");
UpdateAllLifecyclePhases();
Scroll(box, WebGestureDevice::kTouchpad);
EXPECT_FALSE(ToLayoutBox(box->GetLayoutObject())
->GetScrollableArea()
->GetNonCompositedMainThreadScrollingReasons());
- EXPECT_WHEEL_BUCKET(kHasOpacityAndLCDText, 1);
+ EXPECT_WHEEL_BUCKET(kHasTransformAndLCDText, 1);
EXPECT_WHEEL_BUCKET(kBackgroundNotOpaqueInRectAndLCDText, 1);
EXPECT_WHEEL_TOTAL(2);
}
@@ -200,11 +200,11 @@ TEST_F(NonCompositedMainThreadScrollingReasonRecordTest,
NotScrollableAreaTest) {
SetUpHtml(R"HTML(
<style>.box { overflow:scroll; width: 100px; height: 100px; }
- .translucent { opacity: 0.5; }
+ .transform { transform: scale(0.8); }
.hidden { overflow: hidden; }
.spacer { height: 1000px; }
</style>
- <div id='box' class='translucent box'>
+ <div id='box' class='transform box'>
<div class='spacer'></div>
</div>
)HTML");
@@ -215,14 +215,14 @@ TEST_F(NonCompositedMainThreadScrollingReasonRecordTest,
HistogramTester histogram_tester;
Scroll(box, WebGestureDevice::kTouchpad);
- EXPECT_WHEEL_BUCKET(kHasOpacityAndLCDText, 1);
+ EXPECT_WHEEL_BUCKET(kHasTransformAndLCDText, 1);
EXPECT_WHEEL_BUCKET(kBackgroundNotOpaqueInRectAndLCDText, 1);
EXPECT_WHEEL_TOTAL(2);
- box->setAttribute("class", "hidden translucent box");
+ box->setAttribute("class", "hidden transform box");
UpdateAllLifecyclePhases();
Scroll(box, WebGestureDevice::kTouchpad);
- EXPECT_WHEEL_BUCKET(kHasOpacityAndLCDText, 1);
+ EXPECT_WHEEL_BUCKET(kHasTransformAndLCDText, 1);
EXPECT_WHEEL_BUCKET(kBackgroundNotOpaqueInRectAndLCDText, 1);
EXPECT_WHEEL_TOTAL(2);
}
@@ -232,13 +232,12 @@ TEST_F(NonCompositedMainThreadScrollingReasonRecordTest, NestedScrollersTest) {
<style>
.container { overflow:scroll; width: 200px; height: 200px; }
.box { overflow:scroll; width: 100px; height: 100px; }
- .translucent { opacity: 0.5; }
.transform { transform: scale(0.8); }
.spacer { height: 1000px; }
.composited { will-change: transform; }
</style>
<div id='container' class='container with-border-radius'>
- <div class='translucent box'>
+ <div class='box'>
<div id='inner' class='composited transform box'>
<div class='spacer'></div>
</div>
@@ -259,11 +258,10 @@ TEST_F(NonCompositedMainThreadScrollingReasonRecordTest, NestedScrollersTest) {
// Scrolling the inner box will gather reasons from the scrolling chain. The
// inner box itself has no reason because it's composited. Other scrollable
// areas from the chain have corresponding reasons.
- EXPECT_WHEEL_BUCKET(kHasOpacityAndLCDText, 1);
EXPECT_WHEEL_BUCKET(kBackgroundNotOpaqueInRectAndLCDText, 1);
EXPECT_WHEEL_BUCKET(kIsNotStackingContextAndLCDText, 1);
EXPECT_WHEEL_BUCKET(kHasTransformAndLCDText, 0);
- EXPECT_WHEEL_TOTAL(3);
+ EXPECT_WHEEL_TOTAL(2);
}
} // namespace
diff --git a/chromium/third_party/blink/renderer/core/page/scrolling/scroll_state.idl b/chromium/third_party/blink/renderer/core/page/scrolling/scroll_state.idl
index 515a5d6a634..83558525fee 100644
--- a/chromium/third_party/blink/renderer/core/page/scrolling/scroll_state.idl
+++ b/chromium/third_party/blink/renderer/core/page/scrolling/scroll_state.idl
@@ -5,7 +5,8 @@
// https://docs.google.com/document/d/1VnvAqeWFG9JFZfgG5evBqrLGDZYRE5w6G5jEDORekPY
[
- RuntimeEnabled = ScrollCustomization
+ Exposed=Window,
+ RuntimeEnabled=ScrollCustomization
] interface ScrollState
{
constructor(optional ScrollStateInit scrollStateInit = {});
diff --git a/chromium/third_party/blink/renderer/core/page/scrolling/scrolling_coordinator.cc b/chromium/third_party/blink/renderer/core/page/scrolling/scrolling_coordinator.cc
index 6140bf3849a..1b15feae5db 100644
--- a/chromium/third_party/blink/renderer/core/page/scrolling/scrolling_coordinator.cc
+++ b/chromium/third_party/blink/renderer/core/page/scrolling/scrolling_coordinator.cc
@@ -32,11 +32,8 @@
#include "cc/animation/animation_host.h"
#include "cc/input/main_thread_scrolling_reason.h"
#include "cc/input/scroll_snap_data.h"
-#include "cc/layers/painted_overlay_scrollbar_layer.h"
-#include "cc/layers/painted_scrollbar_layer.h"
#include "cc/layers/picture_layer.h"
#include "cc/layers/scrollbar_layer_base.h"
-#include "cc/layers/solid_color_scrollbar_layer.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
@@ -243,41 +240,8 @@ void ScrollingCoordinator::RemoveScrollbarLayer(
scrollbars.erase(scrollable_area);
}
-static scoped_refptr<cc::ScrollbarLayerBase> CreateScrollbarLayer(
- Scrollbar& scrollbar,
- float device_scale_factor) {
- ScrollbarTheme& theme = scrollbar.GetTheme();
- auto scrollbar_delegate = base::MakeRefCounted<ScrollbarLayerDelegate>(
- scrollbar, device_scale_factor);
- scoped_refptr<cc::ScrollbarLayerBase> scrollbar_layer;
- if (theme.UsesOverlayScrollbars() && theme.UsesNinePatchThumbResource()) {
- scrollbar_layer =
- cc::PaintedOverlayScrollbarLayer::Create(std::move(scrollbar_delegate));
- } else {
- scrollbar_layer =
- cc::PaintedScrollbarLayer::Create(std::move(scrollbar_delegate));
- }
- scrollbar_layer->SetElementId(scrollbar.GetElementId());
- return scrollbar_layer;
-}
-
-scoped_refptr<cc::ScrollbarLayerBase>
-ScrollingCoordinator::CreateSolidColorScrollbarLayer(
- ScrollbarOrientation orientation,
- int thumb_thickness,
- int track_start,
- bool is_left_side_vertical_scrollbar,
- cc::ElementId element_id) {
- cc::ScrollbarOrientation cc_orientation =
- orientation == kHorizontalScrollbar ? cc::HORIZONTAL : cc::VERTICAL;
- auto scrollbar_layer = cc::SolidColorScrollbarLayer::Create(
- cc_orientation, thumb_thickness, track_start,
- is_left_side_vertical_scrollbar);
- scrollbar_layer->SetElementId(element_id);
- return scrollbar_layer;
-}
-
-static void DetachScrollbarLayer(GraphicsLayer* scrollbar_graphics_layer) {
+static void DetachScrollbarLayerFromGraphicsLayer(
+ GraphicsLayer* scrollbar_graphics_layer) {
DCHECK(scrollbar_graphics_layer);
scrollbar_graphics_layer->SetContentsToCcLayer(nullptr, false);
@@ -291,7 +255,7 @@ static void SetupScrollbarLayer(GraphicsLayer* scrollbar_graphics_layer,
DCHECK(scrollbar_graphics_layer);
if (!scrolling_layer) {
- DetachScrollbarLayer(scrollbar_graphics_layer);
+ DetachScrollbarLayerFromGraphicsLayer(scrollbar_graphics_layer);
return;
}
@@ -303,14 +267,14 @@ static void SetupScrollbarLayer(GraphicsLayer* scrollbar_graphics_layer,
scrollbar_graphics_layer->SetHitTestable(false);
}
-void ScrollingCoordinator::AddScrollbarLayer(
+void ScrollingCoordinator::SetScrollbarLayer(
ScrollableArea* scrollable_area,
ScrollbarOrientation orientation,
- scoped_refptr<cc::ScrollbarLayerBase> scrollbar_layer_group) {
+ scoped_refptr<cc::ScrollbarLayerBase> scrollbar_layer) {
ScrollbarMap& scrollbars = orientation == kHorizontalScrollbar
? horizontal_scrollbars_
: vertical_scrollbars_;
- scrollbars.insert(scrollable_area, std::move(scrollbar_layer_group));
+ scrollbars.Set(scrollable_area, std::move(scrollbar_layer));
}
cc::ScrollbarLayerBase* ScrollingCoordinator::GetScrollbarLayer(
@@ -338,37 +302,24 @@ void ScrollingCoordinator::ScrollableAreaScrollbarLayerDidChange(
? *scrollable_area->HorizontalScrollbar()
: *scrollable_area->VerticalScrollbar();
if (scrollbar.IsCustomScrollbar()) {
- DetachScrollbarLayer(scrollbar_graphics_layer);
- scrollbar_graphics_layer->CcLayer()->SetIsScrollbar(true);
+ // |scrollbar_graphics_layer| and the cc::PictureLayer in it will be used
+ // for the custom scrollbar, without any special cc scrollbar layer.
+ DetachScrollbarLayerFromGraphicsLayer(scrollbar_graphics_layer);
return;
}
cc::ScrollbarLayerBase* scrollbar_layer =
GetScrollbarLayer(scrollable_area, orientation);
- if (!scrollbar_layer ||
- scrollbar_layer->is_left_side_vertical_scrollbar() !=
- scrollable_area->ShouldPlaceVerticalScrollbarOnLeft()) {
- scoped_refptr<cc::ScrollbarLayerBase> new_scrollbar_layer;
- if (scrollbar.IsSolidColor()) {
- DCHECK(scrollbar.IsOverlayScrollbar());
- new_scrollbar_layer = CreateSolidColorScrollbarLayer(
- orientation, scrollbar.GetTheme().ThumbThickness(scrollbar),
- scrollbar.GetTheme().TrackPosition(scrollbar),
- scrollable_area->ShouldPlaceVerticalScrollbarOnLeft(),
- scrollable_area->GetScrollbarElementId(orientation));
- } else {
- new_scrollbar_layer = CreateScrollbarLayer(
- scrollbar, page_->DeviceScaleFactorDeprecated());
- }
-
- scrollbar_layer = new_scrollbar_layer.get();
- AddScrollbarLayer(scrollable_area, orientation,
- std::move(new_scrollbar_layer));
- }
-
- cc::Layer* scroll_layer = scrollable_area->LayerForScrolling();
- SetupScrollbarLayer(scrollbar_graphics_layer, scrollbar_layer,
- scroll_layer);
+ auto scrollbar_delegate = base::MakeRefCounted<ScrollbarLayerDelegate>(
+ scrollbar, page_->DeviceScaleFactorDeprecated());
+ scoped_refptr<cc::ScrollbarLayerBase> new_scrollbar_layer =
+ cc::ScrollbarLayerBase::CreateOrReuse(std::move(scrollbar_delegate),
+ scrollbar_layer);
+ new_scrollbar_layer->SetElementId(scrollbar.GetElementId());
+ SetupScrollbarLayer(scrollbar_graphics_layer, new_scrollbar_layer.get(),
+ scrollable_area->LayerForScrolling());
+ SetScrollbarLayer(scrollable_area, orientation,
+ std::move(new_scrollbar_layer));
// Root layer non-overlay scrollbars should be marked opaque to disable
// blending.
diff --git a/chromium/third_party/blink/renderer/core/page/scrolling/scrolling_coordinator.h b/chromium/third_party/blink/renderer/core/page/scrolling/scrolling_coordinator.h
index 6f82275e0e8..260822a8a3b 100644
--- a/chromium/third_party/blink/renderer/core/page/scrolling/scrolling_coordinator.h
+++ b/chromium/third_party/blink/renderer/core/page/scrolling/scrolling_coordinator.h
@@ -91,13 +91,6 @@ class CORE_EXPORT ScrollingCoordinator final
// Should be called whenever the root layer for the given frame view changes.
void FrameViewRootLayerDidChange(LocalFrameView*);
- scoped_refptr<cc::ScrollbarLayerBase> CreateSolidColorScrollbarLayer(
- ScrollbarOrientation,
- int thumb_thickness,
- int track_start,
- bool is_left_side_vertical_scrollbar,
- cc::ElementId);
-
void WillDestroyScrollableArea(ScrollableArea*);
// Updates scroll offset in cc scroll tree immediately. We don't wait for
@@ -162,7 +155,7 @@ class CORE_EXPORT ScrollingCoordinator final
bool should_scroll_on_main_thread_dirty_;
private:
- void AddScrollbarLayer(ScrollableArea*,
+ void SetScrollbarLayer(ScrollableArea*,
ScrollbarOrientation,
scoped_refptr<cc::ScrollbarLayerBase>);
cc::ScrollbarLayerBase* GetScrollbarLayer(ScrollableArea*,
diff --git a/chromium/third_party/blink/renderer/core/page/scrolling/scrolling_test.cc b/chromium/third_party/blink/renderer/core/page/scrolling/scrolling_test.cc
index aad1e1eb78c..773db7a3d4b 100644
--- a/chromium/third_party/blink/renderer/core/page/scrolling/scrolling_test.cc
+++ b/chromium/third_party/blink/renderer/core/page/scrolling/scrolling_test.cc
@@ -23,12 +23,14 @@
*/
#include "build/build_config.h"
+#include "cc/input/main_thread_scrolling_reason.h"
#include "cc/layers/scrollbar_layer_base.h"
#include "cc/trees/property_tree.h"
#include "cc/trees/scroll_and_scale_set.h"
#include "cc/trees/scroll_node.h"
#include "cc/trees/sticky_position_constraint.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/public/platform/web_cache.h"
#include "third_party/blink/public/platform/web_rect.h"
#include "third_party/blink/public/platform/web_url_loader_mock_factory.h"
@@ -55,6 +57,8 @@
#include "third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.h"
#include "third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.h"
#include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
+#include "third_party/blink/renderer/core/testing/sim/sim_request.h"
+#include "third_party/blink/renderer/core/testing/sim/sim_test.h"
#include "third_party/blink/renderer/platform/geometry/int_point.h"
#include "third_party/blink/renderer/platform/geometry/int_rect.h"
#include "third_party/blink/renderer/platform/graphics/gpu/shared_gpu_context.h"
@@ -1666,6 +1670,425 @@ TEST_P(ScrollingTest, MainThreadScrollAndDeltaFromImplSide) {
EXPECT_EQ(gfx::ScrollOffset(0, 210), CurrentScrollOffset(element_id));
}
+class ScrollingSimTest : public SimTest, public PaintTestConfigurations {
+ public:
+ ScrollingSimTest() : scroll_unification_enabled_(true) {}
+
+ void SetUp() override {
+ SimTest::SetUp();
+ WebView().GetSettings()->SetPreferCompositingToLCDTextEnabled(true);
+ WebView().MainFrameWidgetBase()->Resize(IntSize(1000, 1000));
+ WebView().MainFrameWidgetBase()->UpdateAllLifecyclePhases(
+ DocumentUpdateReason::kTest);
+ }
+
+ void RunIdleTasks() {
+ auto* scheduler =
+ ThreadScheduler::Current()->GetWebMainThreadSchedulerForTest();
+ blink::scheduler::RunIdleTasksForTesting(scheduler,
+ base::BindOnce([]() {}));
+ test::RunPendingTasks();
+ }
+
+ const cc::Layer* RootCcLayer() { return GetDocument().View()->RootCcLayer(); }
+
+ const cc::ScrollNode* ScrollNodeForScrollableArea(
+ const ScrollableArea* scrollable_area) {
+ if (!scrollable_area)
+ return nullptr;
+ const auto* property_trees =
+ RootCcLayer()->layer_tree_host()->property_trees();
+ return property_trees->scroll_tree.Node(
+ property_trees->element_id_to_scroll_node_index.at(
+ scrollable_area->GetScrollElementId()));
+ }
+
+ protected:
+ RuntimeEnabledFeaturesTestHelpers::ScopedScrollUnification
+ scroll_unification_enabled_;
+};
+
+INSTANTIATE_PAINT_TEST_SUITE_P(ScrollingSimTest);
+
+// Tests that the compositor gets a scroll node for noncomposited scrollers by
+// loading a page with a scroller that has a clip path, and ensuring that
+// scroller generates a compositor scroll node with the proper noncomposited
+// reasons set. It then removes the clip property and ensures the compositor
+// node updates accordingly.
+TEST_P(ScrollingSimTest, ScrollNodeForNonCompositedScroller) {
+ SimRequest request("https://example.com/test.html", "text/html");
+ LoadURL("https://example.com/test.html");
+ request.Complete(R"HTML(
+ <!DOCTYPE html>
+ <style>
+ #noncomposited {
+ width: 200px;
+ height: 200px;
+ overflow: auto;
+ position: absolute;
+ top: 300px;
+ clip: rect(0px, 200px, 200px, 50px);
+ }
+ #spacer {
+ width: 100%;
+ height: 10000px;
+ }
+ </style>
+ <div id="noncomposited">
+ <div id="spacer"></div>
+ </div>
+ )HTML");
+ Compositor().BeginFrame();
+
+ Element* noncomposited_element =
+ MainFrame().GetFrame()->GetDocument()->getElementById("noncomposited");
+ auto* scrollable_area = noncomposited_element->GetScrollableArea();
+ ASSERT_EQ(cc::MainThreadScrollingReason::kHasClipRelatedProperty,
+ scrollable_area->GetNonCompositedMainThreadScrollingReasons());
+
+ const auto* scroll_node = ScrollNodeForScrollableArea(scrollable_area);
+ ASSERT_TRUE(scroll_node);
+
+ EXPECT_EQ(scroll_node->element_id, scrollable_area->GetScrollElementId());
+ EXPECT_FALSE(RootCcLayer()
+ ->layer_tree_host()
+ ->property_trees()
+ ->scroll_tree.IsComposited(*scroll_node));
+
+ // Now remove the clip property and ensure the compositor scroll node changes.
+ noncomposited_element->setAttribute(html_names::kStyleAttr, "clip: auto");
+ Compositor().BeginFrame();
+
+ EXPECT_EQ(0u, scrollable_area->GetNonCompositedMainThreadScrollingReasons());
+ EXPECT_EQ(scroll_node->element_id, scrollable_area->GetScrollElementId());
+ EXPECT_TRUE(RootCcLayer()
+ ->layer_tree_host()
+ ->property_trees()
+ ->scroll_tree.IsComposited(*scroll_node));
+}
+
+// Tests that the compositor retains the scroll node for a composited scroller
+// when it becomes noncomposited, and ensures the scroll node has its
+// IsComposited state updated accordingly.
+TEST_P(ScrollingSimTest, ScrollNodeForCompositedToNonCompositedScroller) {
+ SimRequest request("https://example.com/test.html", "text/html");
+ LoadURL("https://example.com/test.html");
+ request.Complete(R"HTML(
+ <!DOCTYPE html>
+ <style>
+ #composited {
+ width: 200px;
+ height: 200px;
+ overflow: auto;
+ position: absolute;
+ top: 300px;
+ }
+ #spacer {
+ width: 100%;
+ height: 10000px;
+ }
+ </style>
+ <div id="composited">
+ <div id="spacer"></div>
+ </div>
+ )HTML");
+ Compositor().BeginFrame();
+
+ Element* composited_element =
+ MainFrame().GetFrame()->GetDocument()->getElementById("composited");
+ auto* scrollable_area = composited_element->GetScrollableArea();
+ EXPECT_EQ(0u, scrollable_area->GetNonCompositedMainThreadScrollingReasons());
+
+ const auto* scroll_node = ScrollNodeForScrollableArea(scrollable_area);
+ ASSERT_TRUE(scroll_node);
+
+ EXPECT_EQ(scroll_node->element_id, scrollable_area->GetScrollElementId());
+ EXPECT_TRUE(RootCcLayer()
+ ->layer_tree_host()
+ ->property_trees()
+ ->scroll_tree.IsComposited(*scroll_node));
+
+ // Now add a clip property to make the node noncomposited and ensure the
+ // compositor scroll node updates accordingly.
+ composited_element->setAttribute(html_names::kStyleAttr,
+ "clip: rect(0px, 200px, 200px, 50px)");
+ Compositor().BeginFrame();
+
+ ASSERT_EQ(cc::MainThreadScrollingReason::kHasClipRelatedProperty,
+ scrollable_area->GetNonCompositedMainThreadScrollingReasons());
+ EXPECT_EQ(scroll_node->element_id, scrollable_area->GetScrollElementId());
+ EXPECT_FALSE(RootCcLayer()
+ ->layer_tree_host()
+ ->property_trees()
+ ->scroll_tree.IsComposited(*scroll_node));
+}
+
+// Tests that the compositor gets a scroll node for noncomposited scrollers
+// embedded in an iframe, by loading a document with an iframe that has a
+// scroller with a clip path, and ensuring that scroller generates a compositor
+// scroll node with the proper noncomposited reasons set.
+TEST_P(ScrollingSimTest, ScrollNodeForEmbeddedScrollers) {
+ SimRequest request("https://example.com/test.html", "text/html");
+ LoadURL("https://example.com/test.html");
+ request.Complete(R"HTML(
+ <!DOCTYPE html>
+ <style>
+ #iframe {
+ width: 300px;
+ height: 300px;
+ overflow: auto;
+ }
+ </style>
+ <iframe id="iframe" srcdoc="
+ <!DOCTYPE html>
+ <style>
+ #scroller {
+ width: 200px;
+ height: 200px;
+ overflow: auto;
+ position: absolute;
+ top: 50px;
+ clip: rect(0px, 200px, 200px, 50px);
+ }
+ #spacer {
+ width: 100%;
+ height: 10000px;
+ }
+ </style>
+ <div id='scroller'>
+ <div id='spacer'></div>
+ </div>
+ <div id='spacer'></div>">
+ </iframe>
+ )HTML");
+
+ // RunIdleTasks to load the srcdoc iframe.
+ RunIdleTasks();
+ Compositor().BeginFrame();
+
+ HTMLFrameOwnerElement* iframe =
+ To<HTMLFrameOwnerElement>(GetDocument().getElementById("iframe"));
+ auto* iframe_scrollable_area =
+ iframe->contentDocument()->View()->LayoutViewport();
+ const auto* iframe_scroll_node =
+ ScrollNodeForScrollableArea(iframe_scrollable_area);
+ ASSERT_TRUE(iframe_scroll_node);
+
+ // The iframe itself is a composited scroller.
+ EXPECT_EQ(
+ 0u, iframe_scrollable_area->GetNonCompositedMainThreadScrollingReasons());
+ EXPECT_EQ(iframe_scroll_node->element_id,
+ iframe_scrollable_area->GetScrollElementId());
+ EXPECT_TRUE(RootCcLayer()
+ ->layer_tree_host()
+ ->property_trees()
+ ->scroll_tree.IsComposited(*iframe_scroll_node));
+
+ // Ensure we have a compositor scroll node for the noncomposited subscroller.
+ auto* child_scrollable_area = iframe->contentDocument()
+ ->getElementById("scroller")
+ ->GetScrollableArea();
+ const auto* child_scroll_node =
+ ScrollNodeForScrollableArea(child_scrollable_area);
+ ASSERT_TRUE(child_scroll_node);
+
+ EXPECT_EQ(
+ cc::MainThreadScrollingReason::kHasClipRelatedProperty,
+ child_scrollable_area->GetNonCompositedMainThreadScrollingReasons());
+ EXPECT_EQ(child_scroll_node->element_id,
+ child_scrollable_area->GetScrollElementId());
+
+ EXPECT_FALSE(RootCcLayer()
+ ->layer_tree_host()
+ ->property_trees()
+ ->scroll_tree.IsComposited(*child_scroll_node));
+}
+
+// Similar to the above test, but for deeper nesting iframes to ensure we
+// generate scroll nodes that are deeper than the main frame's children.
+TEST_P(ScrollingSimTest, ScrollNodeForNestedEmbeddedScrollers) {
+ SimRequest request("https://example.com/test.html", "text/html");
+ SimRequest child_request_1("https://example.com/child1.html", "text/html");
+ SimRequest child_request_2("https://example.com/child2.html", "text/html");
+ LoadURL("https://example.com/test.html");
+ request.Complete(R"HTML(
+ <!DOCTYPE html>
+ <style>
+ iframe {
+ width: 300px;
+ height: 300px;
+ overflow: auto;
+ }
+ </style>
+ <iframe id="child1" src="child1.html">
+ )HTML");
+
+ child_request_1.Complete(R"HTML(
+ <!DOCTYPE html>
+ <style>
+ iframe {
+ width: 300px;
+ height: 300px;
+ overflow: auto;
+ }
+ </style>
+ <iframe id="child2" src="child2.html">
+ )HTML");
+
+ child_request_2.Complete(R"HTML(
+ <!DOCTYPE html>
+ <style>
+ #scroller {
+ width: 200px;
+ height: 200px;
+ overflow: auto;
+ position: absolute;
+ top: 50px;
+ clip: rect(0px, 200px, 200px, 50px);
+ }
+ #spacer {
+ width: 100%;
+ height: 10000px;
+ }
+ </style>
+ <div id='scroller'>
+ <div id='spacer'></div>
+ </div>
+ <div id='spacer'></div>
+ )HTML");
+
+ RunIdleTasks();
+ Compositor().BeginFrame();
+
+ HTMLFrameOwnerElement* child_iframe_1 =
+ To<HTMLFrameOwnerElement>(GetDocument().getElementById("child1"));
+
+ HTMLFrameOwnerElement* child_iframe_2 = To<HTMLFrameOwnerElement>(
+ child_iframe_1->contentDocument()->getElementById("child2"));
+
+ // Ensure we have a compositor scroll node for the noncomposited subscroller
+ // nested in the second iframe.
+ auto* child_scrollable_area = child_iframe_2->contentDocument()
+ ->getElementById("scroller")
+ ->GetScrollableArea();
+ const auto* child_scroll_node =
+ ScrollNodeForScrollableArea(child_scrollable_area);
+ ASSERT_TRUE(child_scroll_node);
+
+ EXPECT_EQ(
+ cc::MainThreadScrollingReason::kHasClipRelatedProperty,
+ child_scrollable_area->GetNonCompositedMainThreadScrollingReasons());
+ EXPECT_EQ(child_scroll_node->element_id,
+ child_scrollable_area->GetScrollElementId());
+
+ EXPECT_FALSE(RootCcLayer()
+ ->layer_tree_host()
+ ->property_trees()
+ ->scroll_tree.IsComposited(*child_scroll_node));
+}
+
+// Tests that the compositor gets a scroll node for opacity 0 noncomposited
+// scrollers by loading a page with an opacity 0 scroller that has a clip path,
+// and ensuring that scroller generates a compositor scroll node with the proper
+// noncomposited reasons set. The test also ensures that there is no scroll node
+// for a display:none scroller, as there is no scrollable area.
+TEST_P(ScrollingSimTest, ScrollNodeForInvisibleNonCompositedScroller) {
+ SimRequest request("https://example.com/test.html", "text/html");
+ LoadURL("https://example.com/test.html");
+ request.Complete(R"HTML(
+ <!DOCTYPE html>
+ <style>
+ .noncomposited {
+ width: 200px;
+ height: 200px;
+ overflow: auto;
+ position: absolute;
+ top: 300px;
+ clip: rect(0px, 200px, 200px, 50px);
+ }
+ #invisible {
+ opacity: 0;
+ }
+ #displaynone {
+ display: none;
+ }
+ #spacer {
+ width: 100%;
+ height: 10000px;
+ }
+ </style>
+ <div id="invisible" class="noncomposited">
+ <div id="spacer"></div>
+ </div>
+ <div id="displaynone" class="noncomposited">
+ <div id="spacer"></div>
+ </div>
+ )HTML");
+ Compositor().BeginFrame();
+
+ // Ensure the opacity 0 noncomposited scrollable area generates a scroll node
+ auto* invisible_scrollable_area = MainFrame()
+ .GetFrame()
+ ->GetDocument()
+ ->getElementById("invisible")
+ ->GetScrollableArea();
+ ASSERT_EQ(
+ cc::MainThreadScrollingReason::kHasClipRelatedProperty,
+ invisible_scrollable_area->GetNonCompositedMainThreadScrollingReasons());
+
+ const auto* invisible_scroll_node =
+ ScrollNodeForScrollableArea(invisible_scrollable_area);
+ ASSERT_TRUE(invisible_scroll_node);
+
+ EXPECT_EQ(invisible_scroll_node->element_id,
+ invisible_scrollable_area->GetScrollElementId());
+
+ EXPECT_FALSE(RootCcLayer()
+ ->layer_tree_host()
+ ->property_trees()
+ ->scroll_tree.IsComposited(*invisible_scroll_node));
+
+ // Ensure there's no scrollable area (and therefore no scroll node) for a
+ // display none scroller.
+ EXPECT_EQ(nullptr, MainFrame()
+ .GetFrame()
+ ->GetDocument()
+ ->getElementById("displaynone")
+ ->GetScrollableArea());
+}
+
+// Tests that the compositor gets a scroll node for scrollable input boxes,
+// which are unique as they are not a composited scroller but also do not have
+// NonCompositedMainThreadScrollingReasons.
+TEST_P(ScrollingSimTest, ScrollNodeForInputBox) {
+ SimRequest request("https://example.com/test.html", "text/html");
+ LoadURL("https://example.com/test.html");
+ request.Complete(R"HTML(
+ <!DOCTYPE html>
+ <style>
+ input {
+ width: 50px;
+ }
+ </style>
+ <input id="textinput" type="text" value="some overflowing text"/>
+ )HTML");
+ Compositor().BeginFrame();
+
+ Element* input_element =
+ MainFrame().GetFrame()->GetDocument()->getElementById("textinput");
+ auto* scrollable_area = input_element->GetScrollableArea();
+ ASSERT_EQ(0u, scrollable_area->GetNonCompositedMainThreadScrollingReasons());
+
+ const auto* scroll_node = ScrollNodeForScrollableArea(scrollable_area);
+ ASSERT_TRUE(scroll_node);
+
+ EXPECT_EQ(scroll_node->element_id, scrollable_area->GetScrollElementId());
+ EXPECT_FALSE(RootCcLayer()
+ ->layer_tree_host()
+ ->property_trees()
+ ->scroll_tree.IsComposited(*scroll_node));
+}
+
class ScrollingTestWithAcceleratedContext : public ScrollingTest {
protected:
void SetUp() override {
diff --git a/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_anchor.cc b/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_anchor.cc
index ebdb5b14f8a..7af1b2bfbd5 100644
--- a/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_anchor.cc
+++ b/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_anchor.cc
@@ -7,6 +7,7 @@
#include "third_party/blink/renderer/core/display_lock/display_lock_utilities.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/element.h"
+#include "third_party/blink/renderer/core/editing/editing_utilities.h"
#include "third_party/blink/renderer/core/editing/editor.h"
#include "third_party/blink/renderer/core/editing/ephemeral_range.h"
#include "third_party/blink/renderer/core/editing/markers/document_marker_controller.h"
@@ -61,12 +62,25 @@ bool ParseTextDirective(const String& fragment,
bool CheckSecurityRestrictions(LocalFrame& frame,
bool same_document_navigation) {
// This algorithm checks the security restrictions detailed in
- // https://wicg.github.io/ScrollToTextFragment/#should-allow-text-fragment
-
- // We only allow text fragment anchors for user or browser initiated
- // navigations, i.e. no script navigations.
- if (!(frame.Loader().GetDocumentLoader()->HadTransientActivation() ||
- frame.Loader().GetDocumentLoader()->IsBrowserInitiated())) {
+ // https://wicg.github.io/ScrollToTextFragment/#should-allow-a-text-fragment
+ // TODO(bokan): These are really only relevant for observable actions like
+ // scrolling. We should consider allowing highlighting regardless of these
+ // conditions. See the TODO in the relevant spec section:
+ // https://wicg.github.io/ScrollToTextFragment/#restricting-the-text-fragment
+
+ // History navigation is special because it's considered to be browser
+ // initiated even if the navigation originated via use of the history API
+ // within the renderer. We avoid creating a text fragment for history
+ // navigations since history scroll restoration should take precedence but
+ // it'd be bad if we ever got here for a history navigation since the check
+ // below would pass even if the user took no action.
+ SECURITY_CHECK(frame.Loader().GetDocumentLoader()->GetNavigationType() !=
+ kWebNavigationTypeBackForward);
+
+ // We only allow text fragment anchors for user navigations, e.g. link
+ // clicks, omnibox navigations, no script navigations.
+ if (!frame.Loader().GetDocumentLoader()->HadTransientActivation() &&
+ !frame.Loader().GetDocumentLoader()->IsBrowserInitiated()) {
return false;
}
@@ -104,6 +118,17 @@ TextFragmentAnchor* TextFragmentAnchor::TryCreateFragmentDirective(
if (!frame.GetDocument()->GetFragmentDirective())
return nullptr;
+ // Avoid invoking the text fragment for history or reload navigations as
+ // they'll be clobbered by scroll restoration; this prevents a transient
+ // scroll as well as user gesture issues; see https://crbug.com/1042986 for
+ // details.
+ auto navigation_type =
+ frame.Loader().GetDocumentLoader()->GetNavigationType();
+ if (navigation_type == kWebNavigationTypeBackForward ||
+ navigation_type == kWebNavigationTypeReload) {
+ return nullptr;
+ }
+
if (!CheckSecurityRestrictions(frame, same_document_navigation))
return nullptr;
@@ -131,7 +156,9 @@ TextFragmentAnchor::TextFragmentAnchor(
DCHECK(!text_fragment_selectors.IsEmpty());
DCHECK(frame_->View());
- metrics_->DidCreateAnchor(text_fragment_selectors.size());
+ metrics_->DidCreateAnchor(
+ text_fragment_selectors.size(),
+ frame.GetDocument()->GetFragmentDirective().length());
text_fragment_finders_.ReserveCapacity(text_fragment_selectors.size());
for (TextFragmentSelector selector : text_fragment_selectors)
@@ -173,12 +200,17 @@ bool TextFragmentAnchor::Invoke() {
finder.FindMatch(*frame_->GetDocument());
}
- if (frame_->GetDocument()->IsLoadCompleted())
+ // Stop searching for matching text once the load event has fired. This may
+ // cause ScrollToTextFragment to not work on pages which dynamically load
+ // content: http://crbug.com/963045
+ if (frame_->GetDocument()->IsLoadCompleted() &&
+ beforematch_state_ != kEventQueued)
DidFinishSearch();
// We return true to keep this anchor alive as long as we need another invoke,
// are waiting to be dismissed, or are proxying an element fragment anchor.
- return !search_finished_ || !dismissed_ || element_fragment_anchor_;
+ return !search_finished_ || !dismissed_ || element_fragment_anchor_ ||
+ beforematch_state_ == kEventQueued;
}
void TextFragmentAnchor::Installed() {}
@@ -206,7 +238,9 @@ void TextFragmentAnchor::Trace(Visitor* visitor) {
FragmentAnchor::Trace(visitor);
}
-void TextFragmentAnchor::DidFindMatch(const EphemeralRangeInFlatTree& range) {
+void TextFragmentAnchor::DidFindMatch(
+ const EphemeralRangeInFlatTree& range,
+ const TextFragmentAnchorMetrics::Match match_metrics) {
if (search_finished_)
return;
@@ -222,6 +256,22 @@ void TextFragmentAnchor::DidFindMatch(const EphemeralRangeInFlatTree& range) {
return;
}
+ if (beforematch_state_ == kNoMatchFound) {
+ Element* enclosing_block =
+ EnclosingBlock(range.StartPosition(), kCannotCrossEditingBoundary);
+ DCHECK(enclosing_block);
+ frame_->GetDocument()->EnqueueAnimationFrameTask(
+ WTF::Bind(&TextFragmentAnchor::FireBeforeMatchEvent,
+ WrapPersistent(this), WrapWeakPersistent(enclosing_block)));
+ beforematch_state_ = kEventQueued;
+ return;
+ }
+ if (beforematch_state_ == kEventQueued)
+ return;
+ // TODO(jarhar): Consider what to do based on DOM/style modifications made by
+ // the beforematch event here and write tests for it once we decide on a
+ // behavior here: https://github.com/WICG/display-locking/issues/150
+
bool needs_style_and_layout = false;
// Apply :target to the first match
@@ -247,7 +297,7 @@ void TextFragmentAnchor::DidFindMatch(const EphemeralRangeInFlatTree& range) {
DocumentUpdateReason::kFindInPage);
}
- metrics_->DidFindMatch(PlainText(range));
+ metrics_->DidFindMatch(match_metrics);
did_find_match_ = true;
if (first_match_needs_scroll_) {
@@ -355,4 +405,10 @@ void TextFragmentAnchor::ApplyTargetToCommonAncestor(
}
}
+void TextFragmentAnchor::FireBeforeMatchEvent(Element* element) {
+ if (RuntimeEnabledFeatures::BeforeMatchEventEnabled())
+ element->DispatchEvent(*Event::Create(event_type_names::kBeforematch));
+ beforematch_state_ = kFiredEvent;
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_anchor.h b/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_anchor.h
index a1384171292..787896028d2 100644
--- a/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_anchor.h
+++ b/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_anchor.h
@@ -59,7 +59,9 @@ class CORE_EXPORT TextFragmentAnchor final : public FragmentAnchor,
void Trace(Visitor*) override;
// TextFragmentFinder::Client interface
- void DidFindMatch(const EphemeralRangeInFlatTree& range) override;
+ void DidFindMatch(
+ const EphemeralRangeInFlatTree& range,
+ const TextFragmentAnchorMetrics::Match match_metrics) override;
void DidFindAmbiguousMatch() override;
private:
@@ -69,6 +71,8 @@ class CORE_EXPORT TextFragmentAnchor final : public FragmentAnchor,
void ApplyTargetToCommonAncestor(const EphemeralRangeInFlatTree& range);
+ void FireBeforeMatchEvent(Element* element);
+
Vector<TextFragmentFinder> text_fragment_finders_;
Member<LocalFrame> frame_;
@@ -96,6 +100,12 @@ class CORE_EXPORT TextFragmentAnchor final : public FragmentAnchor,
// not scroll into view again.
bool should_scroll_ = false;
+ enum BeforematchState {
+ kNoMatchFound, // DidFindMatch has not been called.
+ kEventQueued, // Beforematch event has been queued, but not fired yet.
+ kFiredEvent // Beforematch event has been fired.
+ } beforematch_state_ = kNoMatchFound;
+
Member<TextFragmentAnchorMetrics> metrics_;
DISALLOW_COPY_AND_ASSIGN(TextFragmentAnchor);
diff --git a/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_anchor_metrics.cc b/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_anchor_metrics.cc
index fd8b4c20e61..9604860dd66 100644
--- a/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_anchor_metrics.cc
+++ b/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_anchor_metrics.cc
@@ -4,7 +4,7 @@
#include "third_party/blink/renderer/core/page/scrolling/text_fragment_anchor_metrics.h"
-#include "base/logging.h"
+#include "base/check.h"
#include "base/metrics/histogram_macros.h"
#include "base/trace_event/trace_event.h"
#include "third_party/blink/renderer/core/frame/web_feature.h"
@@ -21,14 +21,16 @@ const size_t kMaxTraceEventStringLength = 1000;
TextFragmentAnchorMetrics::TextFragmentAnchorMetrics(Document* document)
: document_(document) {}
-void TextFragmentAnchorMetrics::DidCreateAnchor(int selector_count) {
+void TextFragmentAnchorMetrics::DidCreateAnchor(int selector_count,
+ int directive_length) {
UseCounter::Count(document_, WebFeature::kTextFragmentAnchor);
create_time_ = base::TimeTicks::Now();
selector_count_ = selector_count;
+ directive_length_ = directive_length;
}
-void TextFragmentAnchorMetrics::DidFindMatch(const String text) {
- matches_.push_back(text);
+void TextFragmentAnchorMetrics::DidFindMatch(Match match) {
+ matches_.push_back(match);
}
void TextFragmentAnchorMetrics::ResetMatchCount() {
@@ -68,6 +70,12 @@ void TextFragmentAnchorMetrics::ReportMetrics() {
TRACE_EVENT_SCOPE_THREAD, "selector_count",
selector_count_);
+ UMA_HISTOGRAM_COUNTS_1000("TextFragmentAnchor.DirectiveLength",
+ directive_length_);
+ TRACE_EVENT_INSTANT1("blink", "TextFragmentAnchorMetrics::ReportMetrics",
+ TRACE_EVENT_SCOPE_THREAD, "directive_length",
+ directive_length_);
+
const int match_rate_percent =
static_cast<int>(100 * ((matches_.size() + 0.0) / selector_count_));
UMA_HISTOGRAM_PERCENTAGE("TextFragmentAnchor.MatchRate", match_rate_percent);
@@ -75,11 +83,41 @@ void TextFragmentAnchorMetrics::ReportMetrics() {
TRACE_EVENT_SCOPE_THREAD, "match_rate",
match_rate_percent);
- for (const String& match : matches_) {
- TRACE_EVENT_INSTANT2("blink", "TextFragmentAnchorMetrics::ReportMetrics",
- TRACE_EVENT_SCOPE_THREAD, "match_found",
- match.Utf8().substr(0, kMaxTraceEventStringLength),
- "match_length", match.length());
+ for (const Match& match : matches_) {
+ TRACE_EVENT_INSTANT2(
+ "blink", "TextFragmentAnchorMetrics::ReportMetrics",
+ TRACE_EVENT_SCOPE_THREAD, "match_found",
+ match.text.Utf8().substr(0, kMaxTraceEventStringLength), "match_length",
+ match.text.length());
+
+ if (match.selector.Type() == TextFragmentSelector::kExact) {
+ UMA_HISTOGRAM_COUNTS_1000("TextFragmentAnchor.ExactTextLength",
+ match.text.length());
+ TRACE_EVENT_INSTANT1("blink", "TextFragmentAnchorMetrics::ReportMetrics",
+ TRACE_EVENT_SCOPE_THREAD, "exact_text_length",
+ match.text.length());
+ } else if (match.selector.Type() == TextFragmentSelector::kRange) {
+ UMA_HISTOGRAM_COUNTS_1000("TextFragmentAnchor.RangeMatchLength",
+ match.text.length());
+ TRACE_EVENT_INSTANT1("blink", "TextFragmentAnchorMetrics::ReportMetrics",
+ TRACE_EVENT_SCOPE_THREAD, "range_match_length",
+ match.text.length());
+
+ UMA_HISTOGRAM_COUNTS_1000("TextFragmentAnchor.StartTextLength",
+ match.selector.Start().length());
+ TRACE_EVENT_INSTANT1("blink", "TextFragmentAnchorMetrics::ReportMetrics",
+ TRACE_EVENT_SCOPE_THREAD, "start_text_length",
+ match.selector.Start().length());
+
+ UMA_HISTOGRAM_COUNTS_1000("TextFragmentAnchor.EndTextLength",
+ match.selector.End().length());
+ TRACE_EVENT_INSTANT1("blink", "TextFragmentAnchorMetrics::ReportMetrics",
+ TRACE_EVENT_SCOPE_THREAD, "end_text_length",
+ match.selector.End().length());
+ }
+
+ UMA_HISTOGRAM_ENUMERATION("TextFragmentAnchor.Parameters",
+ GetParametersForMatch(match));
}
UMA_HISTOGRAM_BOOLEAN("TextFragmentAnchor.AmbiguousMatch", ambiguous_match_);
@@ -126,4 +164,33 @@ void TextFragmentAnchorMetrics::Trace(Visitor* visitor) {
visitor->Trace(document_);
}
+TextFragmentAnchorMetrics::TextFragmentAnchorParameters
+TextFragmentAnchorMetrics::GetParametersForMatch(const Match& match) {
+ TextFragmentAnchorParameters parameters =
+ TextFragmentAnchorParameters::kUnknown;
+
+ if (match.selector.Type() == TextFragmentSelector::SelectorType::kExact) {
+ if (match.selector.Prefix().length() && match.selector.Suffix().length())
+ parameters = TextFragmentAnchorParameters::kExactTextWithContext;
+ else if (match.selector.Prefix().length())
+ parameters = TextFragmentAnchorParameters::kExactTextWithPrefix;
+ else if (match.selector.Suffix().length())
+ parameters = TextFragmentAnchorParameters::kExactTextWithSuffix;
+ else
+ parameters = TextFragmentAnchorParameters::kExactText;
+ } else if (match.selector.Type() ==
+ TextFragmentSelector::SelectorType::kRange) {
+ if (match.selector.Prefix().length() && match.selector.Suffix().length())
+ parameters = TextFragmentAnchorParameters::kTextRangeWithContext;
+ else if (match.selector.Prefix().length())
+ parameters = TextFragmentAnchorParameters::kTextRangeWithPrefix;
+ else if (match.selector.Suffix().length())
+ parameters = TextFragmentAnchorParameters::kTextRangeWithSuffix;
+ else
+ parameters = TextFragmentAnchorParameters::kTextRange;
+ }
+
+ return parameters;
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_anchor_metrics.h b/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_anchor_metrics.h
index 64d114dcca2..22a227b56b2 100644
--- a/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_anchor_metrics.h
+++ b/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_anchor_metrics.h
@@ -7,6 +7,7 @@
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/dom/document.h"
+#include "third_party/blink/renderer/core/page/scrolling/text_fragment_selector.h"
namespace blink {
@@ -15,11 +16,33 @@ namespace blink {
class CORE_EXPORT TextFragmentAnchorMetrics final
: public GarbageCollected<TextFragmentAnchorMetrics> {
public:
- TextFragmentAnchorMetrics(Document* document);
-
- void DidCreateAnchor(int selector_count);
-
- void DidFindMatch(const String text);
+ struct Match {
+ explicit Match(TextFragmentSelector text_fragment_selector)
+ : selector(text_fragment_selector) {}
+
+ String text;
+ TextFragmentSelector selector;
+ };
+
+ // An enum to indicate which parameters were specified in the text fragment.
+ enum class TextFragmentAnchorParameters {
+ kUnknown = 0,
+ kExactText = 1,
+ kExactTextWithPrefix = 2,
+ kExactTextWithSuffix = 3,
+ kExactTextWithContext = 4,
+ kTextRange = 5,
+ kTextRangeWithPrefix = 6,
+ kTextRangeWithSuffix = 7,
+ kTextRangeWithContext = 8,
+ kMaxValue = kTextRangeWithContext,
+ };
+
+ explicit TextFragmentAnchorMetrics(Document* document);
+
+ void DidCreateAnchor(int selector_count, int directive_length);
+
+ void DidFindMatch(Match match);
void ResetMatchCount();
void DidFindAmbiguousMatch();
@@ -37,6 +60,8 @@ class CORE_EXPORT TextFragmentAnchorMetrics final
void Trace(Visitor*);
private:
+ TextFragmentAnchorParameters GetParametersForMatch(const Match& match);
+
Member<Document> document_;
#ifndef NDEBUG
@@ -44,7 +69,8 @@ class CORE_EXPORT TextFragmentAnchorMetrics final
#endif
wtf_size_t selector_count_ = 0;
- Vector<String> matches_;
+ wtf_size_t directive_length_ = 0;
+ Vector<Match> matches_;
bool ambiguous_match_ = false;
bool scroll_cancelled_ = false;
base::TimeTicks create_time_;
diff --git a/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_anchor_metrics_test.cc b/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_anchor_metrics_test.cc
index e81c97008b6..7f7ab2151be 100644
--- a/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_anchor_metrics_test.cc
+++ b/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_anchor_metrics_test.cc
@@ -2,11 +2,14 @@
// 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/core/page/scrolling/text_fragment_anchor_metrics.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/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
#include "third_party/blink/renderer/core/input/event_handler.h"
+#include "third_party/blink/renderer/core/page/scrolling/text_fragment_anchor.h"
#include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
#include "third_party/blink/renderer/core/testing/sim/sim_request.h"
#include "third_party/blink/renderer/core/testing/sim/sim_test.h"
@@ -35,7 +38,7 @@ class TextFragmentAnchorMetricsTest : public SimTest {
}
void SimulateClick(int x, int y) {
- WebMouseEvent event(WebInputEvent::kMouseDown, gfx::PointF(x, y),
+ WebMouseEvent event(WebInputEvent::Type::kMouseDown, gfx::PointF(x, y),
gfx::PointF(x, y), WebPointerProperties::Button::kLeft,
0, WebInputEvent::Modifiers::kLeftButtonDown,
base::TimeTicks::Now());
@@ -43,6 +46,17 @@ class TextFragmentAnchorMetricsTest : public SimTest {
GetDocument().GetFrame()->GetEventHandler().HandleMousePressEvent(event);
}
+ void BeginEmptyFrame() {
+ // If a test case doesn't find a match and therefore doesn't schedule the
+ // beforematch event, we should still render a second frame as if we did
+ // schedule the event to retain test coverage.
+ // When the beforematch event is not scheduled, a DCHECK will fail on
+ // BeginFrame() because no event was scheduled, so we schedule an empty task
+ // here.
+ GetDocument().EnqueueAnimationFrameTask(WTF::Bind([]() {}));
+ Compositor().BeginFrame();
+ }
+
HistogramTester histogram_tester_;
};
@@ -67,7 +81,9 @@ TEST_F(TextFragmentAnchorMetricsTest, UMAMetricsCollected) {
)HTML");
RunAsyncMatchingTasks();
+ // Render two frames to handle the async step added by the beforematch event.
Compositor().BeginFrame();
+ BeginEmptyFrame();
histogram_tester_.ExpectTotalCount("TextFragmentAnchor.SelectorCount", 1);
histogram_tester_.ExpectUniqueSample("TextFragmentAnchor.SelectorCount", 2,
@@ -90,6 +106,25 @@ TEST_F(TextFragmentAnchorMetricsTest, UMAMetricsCollected) {
histogram_tester_.ExpectTotalCount("TextFragmentAnchor.TimeToScrollIntoView",
1);
+
+ histogram_tester_.ExpectTotalCount("TextFragmentAnchor.DirectiveLength", 1);
+ histogram_tester_.ExpectUniqueSample("TextFragmentAnchor.DirectiveLength", 18,
+ 1);
+
+ histogram_tester_.ExpectTotalCount("TextFragmentAnchor.ExactTextLength", 1);
+ histogram_tester_.ExpectUniqueSample("TextFragmentAnchor.ExactTextLength", 4,
+ 1);
+
+ histogram_tester_.ExpectTotalCount("TextFragmentAnchor.RangeMatchLength", 0);
+ histogram_tester_.ExpectTotalCount("TextFragmentAnchor.StartTextLength", 0);
+ histogram_tester_.ExpectTotalCount("TextFragmentAnchor.EndTextLength", 0);
+
+ histogram_tester_.ExpectTotalCount("TextFragmentAnchor.Parameters", 1);
+ histogram_tester_.ExpectUniqueSample(
+ "TextFragmentAnchor.Parameters",
+ static_cast<int>(
+ TextFragmentAnchorMetrics::TextFragmentAnchorParameters::kExactText),
+ 1);
}
// Test UMA metrics collection when there is no match found
@@ -111,7 +146,9 @@ TEST_F(TextFragmentAnchorMetricsTest, NoMatchFound) {
)HTML");
RunAsyncMatchingTasks();
+ // Render two frames to handle the async step added by the beforematch event.
Compositor().BeginFrame();
+ BeginEmptyFrame();
histogram_tester_.ExpectTotalCount("TextFragmentAnchor.SelectorCount", 1);
histogram_tester_.ExpectUniqueSample("TextFragmentAnchor.SelectorCount", 1,
@@ -132,6 +169,18 @@ TEST_F(TextFragmentAnchorMetricsTest, NoMatchFound) {
histogram_tester_.ExpectTotalCount("TextFragmentAnchor.TimeToScrollIntoView",
0);
+
+ histogram_tester_.ExpectTotalCount("TextFragmentAnchor.DirectiveLength", 1);
+ histogram_tester_.ExpectUniqueSample("TextFragmentAnchor.DirectiveLength", 8,
+ 1);
+
+ histogram_tester_.ExpectTotalCount("TextFragmentAnchor.ExactTextLength", 0);
+
+ histogram_tester_.ExpectTotalCount("TextFragmentAnchor.RangeMatchLength", 0);
+ histogram_tester_.ExpectTotalCount("TextFragmentAnchor.StartTextLength", 0);
+ histogram_tester_.ExpectTotalCount("TextFragmentAnchor.EndTextLength", 0);
+
+ histogram_tester_.ExpectTotalCount("TextFragmentAnchor.Parameters", 0);
}
// Test that we don't collect any metrics when there is no text directive
@@ -142,7 +191,9 @@ TEST_F(TextFragmentAnchorMetricsTest, NoTextFragmentAnchor) {
<!DOCTYPE html>
<p>This is a test page</p>
)HTML");
+ // Render two frames to handle the async step added by the beforematch event.
Compositor().BeginFrame();
+ BeginEmptyFrame();
RunAsyncMatchingTasks();
@@ -158,6 +209,18 @@ TEST_F(TextFragmentAnchorMetricsTest, NoTextFragmentAnchor) {
histogram_tester_.ExpectTotalCount("TextFragmentAnchor.TimeToScrollIntoView",
0);
+
+ histogram_tester_.ExpectTotalCount("TextFragmentAnchor.DirectiveLength", 0);
+
+ histogram_tester_.ExpectTotalCount("TextFragmentAnchor.ExactTextLength", 0);
+
+ histogram_tester_.ExpectTotalCount("TextFragmentAnchor.RangeMatchLength", 0);
+
+ histogram_tester_.ExpectTotalCount("TextFragmentAnchor.StartTextLength", 0);
+
+ histogram_tester_.ExpectTotalCount("TextFragmentAnchor.EndTextLength", 0);
+
+ histogram_tester_.ExpectTotalCount("TextFragmentAnchor.Parameters", 0);
}
// Test that the correct metrics are collected when we found a match but didn't
@@ -171,7 +234,9 @@ TEST_F(TextFragmentAnchorMetricsTest, MatchFoundNoScroll) {
)HTML");
RunAsyncMatchingTasks();
+ // Render two frames to handle the async step added by the beforematch event.
Compositor().BeginFrame();
+ BeginEmptyFrame();
histogram_tester_.ExpectTotalCount("TextFragmentAnchor.SelectorCount", 1);
histogram_tester_.ExpectUniqueSample("TextFragmentAnchor.SelectorCount", 1,
@@ -194,6 +259,207 @@ TEST_F(TextFragmentAnchorMetricsTest, MatchFoundNoScroll) {
histogram_tester_.ExpectTotalCount("TextFragmentAnchor.TimeToScrollIntoView",
1);
+
+ histogram_tester_.ExpectTotalCount("TextFragmentAnchor.DirectiveLength", 1);
+ histogram_tester_.ExpectUniqueSample("TextFragmentAnchor.DirectiveLength", 9,
+ 1);
+
+ histogram_tester_.ExpectTotalCount("TextFragmentAnchor.ExactTextLength", 1);
+ histogram_tester_.ExpectUniqueSample("TextFragmentAnchor.ExactTextLength", 4,
+ 1);
+
+ histogram_tester_.ExpectTotalCount("TextFragmentAnchor.RangeMatchLength", 0);
+ histogram_tester_.ExpectTotalCount("TextFragmentAnchor.StartTextLength", 0);
+ histogram_tester_.ExpectTotalCount("TextFragmentAnchor.EndTextLength", 0);
+
+ histogram_tester_.ExpectTotalCount("TextFragmentAnchor.Parameters", 1);
+ histogram_tester_.ExpectUniqueSample(
+ "TextFragmentAnchor.Parameters",
+ static_cast<int>(
+ TextFragmentAnchorMetrics::TextFragmentAnchorParameters::kExactText),
+ 1);
+}
+
+// Test that the correct metrics are collected for all possible combinations of
+// context terms on an exact text directive.
+TEST_F(TextFragmentAnchorMetricsTest, ExactTextParameters) {
+ SimRequest request(
+ "https://example.com/"
+ "test.html#:~:text=this&text=is-,a&text=test,-page&text=with-,some,-"
+ "content",
+ "text/html");
+ LoadURL(
+ "https://example.com/"
+ "test.html#:~:text=this&text=is-,a&text=test,-page&text=with-,some,-"
+ "content");
+ request.Complete(R"HTML(
+ <!DOCTYPE html>
+ <p>This is a test page</p>
+ <p>With some content</p>
+ )HTML");
+ RunAsyncMatchingTasks();
+
+ Compositor().BeginFrame();
+ BeginEmptyFrame();
+
+ histogram_tester_.ExpectTotalCount("TextFragmentAnchor.SelectorCount", 1);
+ histogram_tester_.ExpectUniqueSample("TextFragmentAnchor.SelectorCount", 4,
+ 1);
+
+ histogram_tester_.ExpectTotalCount("TextFragmentAnchor.MatchRate", 1);
+ histogram_tester_.ExpectUniqueSample("TextFragmentAnchor.MatchRate", 100, 1);
+
+ histogram_tester_.ExpectTotalCount("TextFragmentAnchor.AmbiguousMatch", 1);
+ histogram_tester_.ExpectUniqueSample("TextFragmentAnchor.AmbiguousMatch", 0,
+ 1);
+
+ histogram_tester_.ExpectTotalCount("TextFragmentAnchor.ScrollCancelled", 1);
+ histogram_tester_.ExpectUniqueSample("TextFragmentAnchor.ScrollCancelled", 0,
+ 1);
+
+ histogram_tester_.ExpectTotalCount("TextFragmentAnchor.DidScrollIntoView", 1);
+ histogram_tester_.ExpectUniqueSample("TextFragmentAnchor.DidScrollIntoView",
+ 0, 1);
+
+ histogram_tester_.ExpectTotalCount("TextFragmentAnchor.TimeToScrollIntoView",
+ 1);
+
+ histogram_tester_.ExpectTotalCount("TextFragmentAnchor.DirectiveLength", 1);
+ histogram_tester_.ExpectUniqueSample("TextFragmentAnchor.DirectiveLength", 61,
+ 1);
+
+ histogram_tester_.ExpectTotalCount("TextFragmentAnchor.ExactTextLength", 4);
+ // "this", "test", "some"
+ histogram_tester_.ExpectBucketCount("TextFragmentAnchor.ExactTextLength", 4,
+ 3);
+ // "a"
+ histogram_tester_.ExpectBucketCount("TextFragmentAnchor.ExactTextLength", 1,
+ 1);
+
+ histogram_tester_.ExpectTotalCount("TextFragmentAnchor.RangeMatchLength", 0);
+ histogram_tester_.ExpectTotalCount("TextFragmentAnchor.StartTextLength", 0);
+ histogram_tester_.ExpectTotalCount("TextFragmentAnchor.EndTextLength", 0);
+
+ histogram_tester_.ExpectTotalCount("TextFragmentAnchor.Parameters", 4);
+ histogram_tester_.ExpectBucketCount(
+ "TextFragmentAnchor.Parameters",
+ static_cast<int>(
+ TextFragmentAnchorMetrics::TextFragmentAnchorParameters::kExactText),
+ 1);
+ histogram_tester_.ExpectBucketCount(
+ "TextFragmentAnchor.Parameters",
+ static_cast<int>(TextFragmentAnchorMetrics::TextFragmentAnchorParameters::
+ kExactTextWithPrefix),
+ 1);
+ histogram_tester_.ExpectBucketCount(
+ "TextFragmentAnchor.Parameters",
+ static_cast<int>(TextFragmentAnchorMetrics::TextFragmentAnchorParameters::
+ kExactTextWithSuffix),
+ 1);
+ histogram_tester_.ExpectBucketCount(
+ "TextFragmentAnchor.Parameters",
+ static_cast<int>(TextFragmentAnchorMetrics::TextFragmentAnchorParameters::
+ kExactTextWithContext),
+ 1);
+}
+
+// Test that the correct metrics are collected for all possible combinations of
+// context terms on a range text directive.
+TEST_F(TextFragmentAnchorMetricsTest, TextRangeParameters) {
+ SimRequest request(
+ "https://example.com/"
+ "test.html#:~:text=this,is&text=a-,test,page&text=with,some,-content&"
+ "text=about-,nothing,at,-all",
+ "text/html");
+ LoadURL(
+ "https://example.com/"
+ "test.html#:~:text=this,is&text=a-,test,page&text=with,some,-content&"
+ "text=about-,nothing,at,-all");
+ request.Complete(R"HTML(
+ <!DOCTYPE html>
+ <p>This is a test page</p>
+ <p>With some content</p>
+ <p>About nothing at all</p>
+ )HTML");
+ RunAsyncMatchingTasks();
+
+ Compositor().BeginFrame();
+ BeginEmptyFrame();
+
+ histogram_tester_.ExpectTotalCount("TextFragmentAnchor.SelectorCount", 1);
+ histogram_tester_.ExpectUniqueSample("TextFragmentAnchor.SelectorCount", 4,
+ 1);
+
+ histogram_tester_.ExpectTotalCount("TextFragmentAnchor.MatchRate", 1);
+ histogram_tester_.ExpectUniqueSample("TextFragmentAnchor.MatchRate", 100, 1);
+
+ histogram_tester_.ExpectTotalCount("TextFragmentAnchor.AmbiguousMatch", 1);
+ histogram_tester_.ExpectUniqueSample("TextFragmentAnchor.AmbiguousMatch", 0,
+ 1);
+
+ histogram_tester_.ExpectTotalCount("TextFragmentAnchor.ScrollCancelled", 1);
+ histogram_tester_.ExpectUniqueSample("TextFragmentAnchor.ScrollCancelled", 0,
+ 1);
+
+ histogram_tester_.ExpectTotalCount("TextFragmentAnchor.DidScrollIntoView", 1);
+ histogram_tester_.ExpectUniqueSample("TextFragmentAnchor.DidScrollIntoView",
+ 0, 1);
+
+ histogram_tester_.ExpectTotalCount("TextFragmentAnchor.TimeToScrollIntoView",
+ 1);
+
+ histogram_tester_.ExpectTotalCount("TextFragmentAnchor.DirectiveLength", 1);
+ histogram_tester_.ExpectUniqueSample("TextFragmentAnchor.DirectiveLength", 82,
+ 1);
+
+ histogram_tester_.ExpectTotalCount("TextFragmentAnchor.ExactTextLength", 0);
+
+ histogram_tester_.ExpectTotalCount("TextFragmentAnchor.RangeMatchLength", 4);
+ // "This is"
+ histogram_tester_.ExpectBucketCount("TextFragmentAnchor.RangeMatchLength", 7,
+ 1);
+ // "test page", "with some"
+ histogram_tester_.ExpectBucketCount("TextFragmentAnchor.RangeMatchLength", 9,
+ 2);
+ // "nothing at"
+ histogram_tester_.ExpectBucketCount("TextFragmentAnchor.RangeMatchLength", 10,
+ 1);
+
+ histogram_tester_.ExpectTotalCount("TextFragmentAnchor.StartTextLength", 4);
+ // "this", "test", "with"
+ histogram_tester_.ExpectBucketCount("TextFragmentAnchor.StartTextLength", 4,
+ 3);
+ // "nothing"
+ histogram_tester_.ExpectBucketCount("TextFragmentAnchor.StartTextLength", 7,
+ 1);
+
+ histogram_tester_.ExpectTotalCount("TextFragmentAnchor.EndTextLength", 4);
+ // "is", "at"
+ histogram_tester_.ExpectBucketCount("TextFragmentAnchor.EndTextLength", 2, 2);
+ // "page", "some"
+ histogram_tester_.ExpectBucketCount("TextFragmentAnchor.EndTextLength", 4, 2);
+
+ histogram_tester_.ExpectTotalCount("TextFragmentAnchor.Parameters", 4);
+ histogram_tester_.ExpectBucketCount(
+ "TextFragmentAnchor.Parameters",
+ static_cast<int>(
+ TextFragmentAnchorMetrics::TextFragmentAnchorParameters::kTextRange),
+ 1);
+ histogram_tester_.ExpectBucketCount(
+ "TextFragmentAnchor.Parameters",
+ static_cast<int>(TextFragmentAnchorMetrics::TextFragmentAnchorParameters::
+ kTextRangeWithPrefix),
+ 1);
+ histogram_tester_.ExpectBucketCount(
+ "TextFragmentAnchor.Parameters",
+ static_cast<int>(TextFragmentAnchorMetrics::TextFragmentAnchorParameters::
+ kTextRangeWithSuffix),
+ 1);
+ histogram_tester_.ExpectBucketCount(
+ "TextFragmentAnchor.Parameters",
+ static_cast<int>(TextFragmentAnchorMetrics::TextFragmentAnchorParameters::
+ kTextRangeWithContext),
+ 1);
}
// Test that the ScrollCancelled metric gets reported when a user scroll cancels
@@ -233,7 +499,9 @@ TEST_F(TextFragmentAnchorMetricsTest, ScrollCancelled) {
css_request.Complete("p { visibility: visible; top: 1001px; }");
RunAsyncMatchingTasks();
+ // Render two frames to handle the async step added by the beforematch event.
Compositor().BeginFrame();
+ BeginEmptyFrame();
histogram_tester_.ExpectTotalCount("TextFragmentAnchor.SelectorCount", 1);
histogram_tester_.ExpectUniqueSample("TextFragmentAnchor.SelectorCount", 1,
@@ -254,6 +522,25 @@ TEST_F(TextFragmentAnchorMetricsTest, ScrollCancelled) {
histogram_tester_.ExpectTotalCount("TextFragmentAnchor.TimeToScrollIntoView",
0);
+
+ histogram_tester_.ExpectTotalCount("TextFragmentAnchor.DirectiveLength", 1);
+ histogram_tester_.ExpectUniqueSample("TextFragmentAnchor.DirectiveLength", 9,
+ 1);
+
+ histogram_tester_.ExpectTotalCount("TextFragmentAnchor.ExactTextLength", 1);
+ histogram_tester_.ExpectUniqueSample("TextFragmentAnchor.ExactTextLength", 4,
+ 1);
+
+ histogram_tester_.ExpectTotalCount("TextFragmentAnchor.RangeMatchLength", 0);
+ histogram_tester_.ExpectTotalCount("TextFragmentAnchor.StartTextLength", 0);
+ histogram_tester_.ExpectTotalCount("TextFragmentAnchor.EndTextLength", 0);
+
+ histogram_tester_.ExpectTotalCount("TextFragmentAnchor.Parameters", 1);
+ histogram_tester_.ExpectUniqueSample(
+ "TextFragmentAnchor.Parameters",
+ static_cast<int>(
+ TextFragmentAnchorMetrics::TextFragmentAnchorParameters::kExactText),
+ 1);
}
// Test that the TapToDismiss feature gets use counted when the user taps to
@@ -277,7 +564,9 @@ TEST_F(TextFragmentAnchorMetricsTest, TapToDismiss) {
)HTML");
RunAsyncMatchingTasks();
+ // Render two frames to handle the async step added by the beforematch event.
Compositor().BeginFrame();
+ BeginEmptyFrame();
EXPECT_TRUE(GetDocument().IsUseCounted(WebFeature::kTextFragmentAnchor));
EXPECT_TRUE(
@@ -316,7 +605,10 @@ TEST_F(TextFragmentAnchorMetricsTest, InvalidFragmentDirective) {
<!DOCTYPE html>
<p id="element">This is a test page</p>
)HTML");
+ // Render two frames to handle the async step added by the beforematch
+ // event.
Compositor().BeginFrame();
+ BeginEmptyFrame();
RunAsyncMatchingTasks();
@@ -401,7 +693,10 @@ TEST_P(TextFragmentRelatedMetricTest, ElementIdSuccessFailureCounts) {
<p id=":~:text=name">This is a test page</p>
<p id="element:~:text=name">This is a test page</p>
)HTML");
+ // Render two frames to handle the async step added by the beforematch
+ // event.
Compositor().BeginFrame();
+ BeginEmptyFrame();
RunAsyncMatchingTasks();
@@ -464,7 +759,10 @@ TEST_P(TextFragmentRelatedMetricTest, TildeAmpersandTildeUseCounter) {
<!DOCTYPE html>
<p id="element">This is a test page</p>
)HTML");
+ // Render two frames to handle the async step added by the beforematch
+ // event.
Compositor().BeginFrame();
+ BeginEmptyFrame();
RunAsyncMatchingTasks();
@@ -502,7 +800,10 @@ TEST_P(TextFragmentRelatedMetricTest, TildeAtTildeUseCounter) {
<!DOCTYPE html>
<p id="element">This is a test page</p>
)HTML");
+ // Render two frames to handle the async step added by the beforematch
+ // event.
Compositor().BeginFrame();
+ BeginEmptyFrame();
RunAsyncMatchingTasks();
@@ -542,7 +843,10 @@ TEST_P(TextFragmentRelatedMetricTest, AmpersandDelimiterQuestionUseCounter) {
<!DOCTYPE html>
<p id="element">This is a test page</p>
)HTML");
+ // Render two frames to handle the async step added by the beforematch
+ // event.
Compositor().BeginFrame();
+ BeginEmptyFrame();
RunAsyncMatchingTasks();
@@ -584,7 +888,10 @@ TEST_P(TextFragmentRelatedMetricTest, NewDelimiterUseCounter) {
<!DOCTYPE html>
<p id="element">This is a test page</p>
)HTML");
+ // Render two frames to handle the async step added by the beforematch
+ // event.
Compositor().BeginFrame();
+ BeginEmptyFrame();
RunAsyncMatchingTasks();
@@ -600,6 +907,45 @@ TEST_P(TextFragmentRelatedMetricTest, NewDelimiterUseCounter) {
}
}
+// Test use counting the location.fragmentDirective API
+TEST_P(TextFragmentRelatedMetricTest, TextFragmentAPIUseCounter) {
+ SimRequest request("https://example.com/test.html", "text/html");
+ LoadURL("https://example.com/test.html");
+ request.Complete(R"HTML(
+ <!DOCTYPE html>
+ <script>
+ var textFragmentsSupported = typeof(location.fragmentDirective) == "object";
+ </script>
+ <p>This is a test page</p>
+ )HTML");
+ Compositor().BeginFrame();
+ RunAsyncMatchingTasks();
+
+ bool text_fragments_enabled = GetParam();
+
+ EXPECT_EQ(text_fragments_enabled,
+ GetDocument().IsUseCounted(
+ WebFeature::kLocationFragmentDirectiveAccessed));
+}
+
+// Test that simply activating a text fragment does not use count the API
+TEST_P(TextFragmentRelatedMetricTest, TextFragmentActivationDoesNotCountAPI) {
+ SimRequest request("https://example.com/test.html#:~:text=test", "text/html");
+ LoadURL("https://example.com/test.html#:~:text=test");
+ request.Complete(R"HTML(
+ <!DOCTYPE html>
+ <p>This is a test page</p>
+ )HTML");
+ Compositor().BeginFrame();
+ RunAsyncMatchingTasks();
+
+ bool text_fragments_enabled = GetParam();
+ EXPECT_EQ(text_fragments_enabled,
+ GetDocument().IsUseCounted(WebFeature::kTextFragmentAnchor));
+ EXPECT_FALSE(GetDocument().IsUseCounted(
+ WebFeature::kLocationFragmentDirectiveAccessed));
+}
+
} // namespace
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_anchor_test.cc b/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_anchor_test.cc
index c8c87c95319..c675298719c 100644
--- a/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_anchor_test.cc
+++ b/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_anchor_test.cc
@@ -43,6 +43,17 @@ class TextFragmentAnchorTest : public SimTest {
RunPendingTasks();
}
+ void BeginEmptyFrame() {
+ // If a test case doesn't find a match and therefore doesn't schedule the
+ // beforematch event, we should still render a second frame as if we did
+ // schedule the event to retain test coverage.
+ // When the beforematch event is not scheduled, a DCHECK will fail on
+ // BeginFrame() because no event was scheduled, so we schedule an empty task
+ // here.
+ GetDocument().EnqueueAnimationFrameTask(WTF::Bind([]() {}));
+ Compositor().BeginFrame();
+ }
+
ScrollableArea* LayoutViewport() {
return GetDocument().View()->LayoutViewport();
}
@@ -56,7 +67,7 @@ class TextFragmentAnchorTest : public SimTest {
}
void SimulateClick(int x, int y) {
- WebMouseEvent event(WebInputEvent::kMouseDown, gfx::PointF(x, y),
+ WebMouseEvent event(WebInputEvent::Type::kMouseDown, gfx::PointF(x, y),
gfx::PointF(x, y), WebPointerProperties::Button::kLeft,
0, WebInputEvent::Modifiers::kLeftButtonDown,
base::TimeTicks::Now());
@@ -65,7 +76,7 @@ class TextFragmentAnchorTest : public SimTest {
}
void SimulateTap(int x, int y) {
- WebGestureEvent event(WebInputEvent::kGestureTap,
+ WebGestureEvent event(WebInputEvent::Type::kGestureTap,
WebInputEvent::kNoModifiers, base::TimeTicks::Now(),
WebGestureDevice::kTouchscreen);
event.SetPositionInWidget(gfx::PointF(x, y));
@@ -94,6 +105,8 @@ TEST_F(TextFragmentAnchorTest, BasicSmokeTest) {
)HTML");
RunAsyncMatchingTasks();
+ // Render two frames to handle the async step added by the beforematch event.
+ Compositor().BeginFrame();
Compositor().BeginFrame();
Element& p = *GetDocument().getElementById("text");
@@ -125,7 +138,9 @@ TEST_F(TextFragmentAnchorTest, NonMatchingString) {
)HTML");
RunAsyncMatchingTasks();
+ // Render two frames to handle the async step added by the beforematch event.
Compositor().BeginFrame();
+ BeginEmptyFrame();
EXPECT_EQ(ScrollOffset(), LayoutViewport()->GetScrollOffset());
@@ -162,6 +177,8 @@ TEST_F(TextFragmentAnchorTest, MultipleMatches) {
)HTML");
RunAsyncMatchingTasks();
+ // Render two frames to handle the async step added by the beforematch event.
+ Compositor().BeginFrame();
Compositor().BeginFrame();
Element& first = *GetDocument().getElementById("first");
@@ -197,6 +214,8 @@ TEST_F(TextFragmentAnchorTest, NestedBlocks) {
)HTML");
RunAsyncMatchingTasks();
+ // Render two frames to handle the async step added by the beforematch event.
+ Compositor().BeginFrame();
Compositor().BeginFrame();
Element& match = *GetDocument().getElementById("match");
@@ -233,6 +252,8 @@ TEST_F(TextFragmentAnchorTest, MultipleTextFragments) {
)HTML");
RunAsyncMatchingTasks();
+ // Render two frames to handle the async step added by the beforematch event.
+ Compositor().BeginFrame();
Compositor().BeginFrame();
Element& first = *GetDocument().getElementById("first");
@@ -270,6 +291,8 @@ TEST_F(TextFragmentAnchorTest, FirstTextFragmentNotFound) {
)HTML");
RunAsyncMatchingTasks();
+ // Render two frames to handle the async step added by the beforematch event.
+ Compositor().BeginFrame();
Compositor().BeginFrame();
Element& second = *GetDocument().getElementById("second");
@@ -303,6 +326,8 @@ TEST_F(TextFragmentAnchorTest, OnlyFirstTextFragmentFound) {
)HTML");
RunAsyncMatchingTasks();
+ // Render two frames to handle the async step added by the beforematch event.
+ Compositor().BeginFrame();
Compositor().BeginFrame();
Element& p = *GetDocument().getElementById("text");
@@ -340,7 +365,9 @@ TEST_F(TextFragmentAnchorTest, MultipleNonMatchingStrings) {
)HTML");
RunAsyncMatchingTasks();
+ // Render two frames to handle the async step added by the beforematch event.
Compositor().BeginFrame();
+ BeginEmptyFrame();
EXPECT_EQ(ScrollOffset(), LayoutViewport()->GetScrollOffset());
@@ -373,6 +400,8 @@ TEST_F(TextFragmentAnchorTest, SameElementTextRange) {
)HTML");
RunAsyncMatchingTasks();
+ // Render two frames to handle the async step added by the beforematch event.
+ Compositor().BeginFrame();
Compositor().BeginFrame();
EXPECT_EQ(*GetDocument().getElementById("text"), *GetDocument().CssTarget());
@@ -408,6 +437,8 @@ TEST_F(TextFragmentAnchorTest, NeighboringElementTextRange) {
)HTML");
RunAsyncMatchingTasks();
+ // Render two frames to handle the async step added by the beforematch event.
+ Compositor().BeginFrame();
Compositor().BeginFrame();
EXPECT_EQ(*GetDocument().body(), *GetDocument().CssTarget());
@@ -453,6 +484,8 @@ TEST_F(TextFragmentAnchorTest, DifferentDepthElementTextRange) {
)HTML");
RunAsyncMatchingTasks();
+ // Render two frames to handle the async step added by the beforematch event.
+ Compositor().BeginFrame();
Compositor().BeginFrame();
EXPECT_EQ(*GetDocument().body(), *GetDocument().CssTarget());
@@ -527,6 +560,8 @@ TEST_F(TextFragmentAnchorTest, MultipleTextRanges) {
)HTML");
RunAsyncMatchingTasks();
+ // Render two frames to handle the async step added by the beforematch event.
+ Compositor().BeginFrame();
Compositor().BeginFrame();
EXPECT_EQ(*GetDocument().body(), *GetDocument().CssTarget());
@@ -568,6 +603,8 @@ TEST_F(TextFragmentAnchorTest, DistantElementTextRange) {
)HTML");
RunAsyncMatchingTasks();
+ // Render two frames to handle the async step added by the beforematch event.
+ Compositor().BeginFrame();
Compositor().BeginFrame();
Element& p = *GetDocument().getElementById("text");
@@ -588,6 +625,8 @@ TEST_F(TextFragmentAnchorTest, TextRangeWithContext) {
)HTML");
RunAsyncMatchingTasks();
+ // Render two frames to handle the async step added by the beforematch event.
+ Compositor().BeginFrame();
Compositor().BeginFrame();
EXPECT_EQ(*GetDocument().getElementById("text"), *GetDocument().CssTarget());
@@ -612,7 +651,10 @@ TEST_F(TextFragmentAnchorTest, PrefixNotFound) {
<!DOCTYPE html>
<p id="text">This is a test page</p>
)HTML");
+
+ // Render two frames to handle the async step added by the beforematch event.
Compositor().BeginFrame();
+ BeginEmptyFrame();
RunAsyncMatchingTasks();
@@ -658,6 +700,8 @@ TEST_F(TextFragmentAnchorTest, TextRangeWithCrossElementContext) {
)HTML");
RunAsyncMatchingTasks();
+ // Render two frames to handle the async step added by the beforematch event.
+ Compositor().BeginFrame();
Compositor().BeginFrame();
EXPECT_EQ(*GetDocument().getElementById("expected"),
@@ -702,6 +746,8 @@ TEST_F(TextFragmentAnchorTest, CrossElementAndWhitespaceContext) {
)HTML");
RunAsyncMatchingTasks();
+ // Render two frames to handle the async step added by the beforematch event.
+ Compositor().BeginFrame();
Compositor().BeginFrame();
EXPECT_EQ(*GetDocument().getElementById("expected"),
@@ -740,6 +786,8 @@ TEST_F(TextFragmentAnchorTest, CrossEmptySiblingAndParentElementContext) {
)HTML");
RunAsyncMatchingTasks();
+ // Render two frames to handle the async step added by the beforematch event.
+ Compositor().BeginFrame();
Compositor().BeginFrame();
EXPECT_EQ(*GetDocument().getElementById("expected"),
@@ -775,6 +823,8 @@ TEST_F(TextFragmentAnchorTest, DistantElementContext) {
)HTML");
RunAsyncMatchingTasks();
+ // Render two frames to handle the async step added by the beforematch event.
+ Compositor().BeginFrame();
Compositor().BeginFrame();
Element& p = *GetDocument().getElementById("text");
@@ -800,6 +850,8 @@ TEST_F(TextFragmentAnchorTest, OneContextTerm) {
)HTML");
RunAsyncMatchingTasks();
+ // Render two frames to handle the async step added by the beforematch event.
+ Compositor().BeginFrame();
Compositor().BeginFrame();
EXPECT_EQ(*GetDocument().getElementById("text1"), *GetDocument().CssTarget());
@@ -879,6 +931,8 @@ TEST_F(TextFragmentAnchorTest, ScrollCancelled) {
RunAsyncMatchingTasks();
+ // Render two frames to handle the async step added by the beforematch event.
+ Compositor().BeginFrame();
Compositor().BeginFrame();
Element& p = *GetDocument().getElementById("text");
@@ -921,7 +975,9 @@ TEST_F(TextFragmentAnchorTest, DisabledInIframes) {
)HTML");
RunAsyncMatchingTasks();
+ // Render two frames to handle the async step added by the beforematch event.
Compositor().BeginFrame();
+ BeginEmptyFrame();
Element* iframe = GetDocument().getElementById("iframe");
auto* child_frame =
@@ -943,7 +999,9 @@ TEST_F(TextFragmentAnchorTest, DisabledInWindowOpen) {
main_request.Complete(R"HTML(
<!DOCTYPE html>
)HTML");
+ // Render two frames to handle the async step added by the beforematch event.
Compositor().BeginFrame();
+ BeginEmptyFrame();
LocalDOMWindow* main_window = GetDocument().GetFrame()->DomWindow();
@@ -994,7 +1052,9 @@ TEST_F(TextFragmentAnchorTest, DisabledInSamePageNavigation) {
)HTML");
RunAsyncMatchingTasks();
+ // Render two frames to handle the async step added by the beforematch event.
Compositor().BeginFrame();
+ BeginEmptyFrame();
ASSERT_EQ(ScrollOffset(),
GetDocument().View()->GetScrollableArea()->GetScrollOffset());
@@ -1029,6 +1089,8 @@ TEST_F(TextFragmentAnchorTest, CaseInsensitive) {
)HTML");
RunAsyncMatchingTasks();
+ // Render two frames to handle the async step added by the beforematch event.
+ Compositor().BeginFrame();
Compositor().BeginFrame();
Element& p = *GetDocument().getElementById("text");
@@ -1058,7 +1120,9 @@ TEST_F(TextFragmentAnchorTest, TargetStaysInView) {
)HTML");
RunAsyncMatchingTasks();
- Compositor().PaintFrame();
+ // Render two frames to handle the async step added by the beforematch event.
+ Compositor().BeginFrame();
+ Compositor().BeginFrame();
ScrollOffset first_scroll_offset = LayoutViewport()->GetScrollOffset();
ASSERT_NE(ScrollOffset(), first_scroll_offset);
@@ -1105,6 +1169,8 @@ TEST_F(TextFragmentAnchorTest, OverlappingTextRanges) {
)HTML");
RunAsyncMatchingTasks();
+ // Render two frames to handle the async step added by the beforematch event.
+ Compositor().BeginFrame();
Compositor().BeginFrame();
EXPECT_EQ(1u, GetDocument().Markers().Markers().size());
@@ -1138,6 +1204,8 @@ TEST_F(TextFragmentAnchorTest, SpaceMatchesNbsp) {
)HTML");
RunAsyncMatchingTasks();
+ // Render two frames to handle the async step added by the beforematch event.
+ Compositor().BeginFrame();
Compositor().BeginFrame();
Element& p = *GetDocument().getElementById("text");
@@ -1170,6 +1238,8 @@ TEST_F(TextFragmentAnchorTest, CSSTextTransform) {
)HTML");
RunAsyncMatchingTasks();
+ // Render two frames to handle the async step added by the beforematch event.
+ Compositor().BeginFrame();
Compositor().BeginFrame();
Element& p = *GetDocument().getElementById("text");
@@ -1206,6 +1276,8 @@ TEST_F(TextFragmentAnchorTest, NoMatchFoundFallsBackToElementFragment) {
)HTML");
RunAsyncMatchingTasks();
+ // Render two frames to handle the async step added by the beforematch event.
+ Compositor().BeginFrame();
Compositor().BeginFrame();
// The TextFragmentAnchor needs another frame to invoke the element anchor
@@ -1302,6 +1374,8 @@ TEST_F(TextFragmentAnchorTest, CheckForWordBoundaryWithPartialWord) {
)HTML");
RunAsyncMatchingTasks();
+ // Render two frames to handle the async step added by the beforematch event.
+ Compositor().BeginFrame();
Compositor().BeginFrame();
Element& p = *GetDocument().getElementById("second");
@@ -1349,6 +1423,8 @@ TEST_F(TextFragmentAnchorTest, DismissTextHighlightWithClick) {
)HTML");
RunAsyncMatchingTasks();
+ // Render two frames to handle the async step added by the beforematch event.
+ Compositor().BeginFrame();
Compositor().BeginFrame();
EXPECT_EQ(2u, GetDocument().Markers().Markers().size());
@@ -1390,6 +1466,8 @@ TEST_F(TextFragmentAnchorTest, DismissTextHighlightWithTap) {
)HTML");
RunAsyncMatchingTasks();
+ // Render two frames to handle the async step added by the beforematch event.
+ Compositor().BeginFrame();
Compositor().BeginFrame();
EXPECT_EQ(2u, GetDocument().Markers().Markers().size());
@@ -1432,6 +1510,8 @@ TEST_F(TextFragmentAnchorTest, DismissTextHighlightOutOfView) {
css_request.Complete("p { visibility: visible; top: 1001px; }");
RunAsyncMatchingTasks();
+ // Render two frames to handle the async step added by the beforematch event.
+ Compositor().BeginFrame();
Compositor().BeginFrame();
EXPECT_EQ(1u, GetDocument().Markers().Markers().size());
@@ -1466,6 +1546,8 @@ TEST_F(TextFragmentAnchorTest, DismissTextHighlightInView) {
)HTML");
RunAsyncMatchingTasks();
+ // Render two frames to handle the async step added by the beforematch event.
+ Compositor().BeginFrame();
Compositor().BeginFrame();
EXPECT_EQ(ScrollOffset(), LayoutViewport()->GetScrollOffset());
@@ -1499,6 +1581,8 @@ TEST_F(TextFragmentAnchorTest, FragmentDirectiveDelimiter) {
)HTML");
RunAsyncMatchingTasks();
+ // Render two frames to handle the async step added by the beforematch event.
+ Compositor().BeginFrame();
Compositor().BeginFrame();
EXPECT_EQ(1u, GetDocument().Markers().Markers().size());
@@ -1532,6 +1616,8 @@ TEST_F(TextFragmentAnchorTest, FragmentDirectiveDelimiterWithElementFragment) {
)HTML");
RunAsyncMatchingTasks();
+ // Render two frames to handle the async step added by the beforematch event.
+ Compositor().BeginFrame();
Compositor().BeginFrame();
EXPECT_EQ(GetDocument().Url(), "https://example.com/test.html#element");
@@ -1569,6 +1655,8 @@ TEST_F(TextFragmentAnchorTest, IdFragmentWithFragmentDirective) {
)HTML");
RunAsyncMatchingTasks();
+ // Render two frames to handle the async step added by the beforematch event.
+ Compositor().BeginFrame();
Compositor().BeginFrame();
Element& p = *GetDocument().getElementById("element");
@@ -1598,6 +1686,8 @@ TEST_F(TextFragmentAnchorTest, TextDirectiveInSvg) {
)HTML");
RunAsyncMatchingTasks();
+ // Render two frames to handle the async step added by the beforematch event.
+ Compositor().BeginFrame();
Compositor().BeginFrame();
Element& text = *GetDocument().getElementById("text");
@@ -1611,7 +1701,11 @@ TEST_F(TextFragmentAnchorTest, TextDirectiveInSvg) {
}
// Ensure we restore the text highlight on page reload
-TEST_F(TextFragmentAnchorTest, HighlightOnReload) {
+// TODO(bokan): This test is disabled as this functionality was suppressed in
+// https://crrev.com/c/2135407; it would be better addressed by providing a
+// highlight-only function. See the TODO in
+// https://wicg.github.io/ScrollToTextFragment/#restricting-the-text-fragment
+TEST_F(TextFragmentAnchorTest, DISABLED_HighlightOnReload) {
SimRequest request("https://example.com/test.html#:~:text=test", "text/html");
LoadURL("https://example.com/test.html#:~:text=test");
const String& html = R"HTML(
@@ -1630,6 +1724,8 @@ TEST_F(TextFragmentAnchorTest, HighlightOnReload) {
request.Complete(html);
RunAsyncMatchingTasks();
+ // Render two frames to handle the async step added by the beforematch event.
+ Compositor().BeginFrame();
Compositor().BeginFrame();
EXPECT_EQ(1u, GetDocument().Markers().Markers().size());
@@ -1644,8 +1740,9 @@ TEST_F(TextFragmentAnchorTest, HighlightOnReload) {
MainFrame().StartReload(WebFrameLoadType::kReload);
reload_request.Complete(html);
+ // Render two frames to handle the async step added by the beforematch event.
+ Compositor().BeginFrame();
Compositor().BeginFrame();
- RunAsyncMatchingTasks();
EXPECT_EQ(*GetDocument().getElementById("text"), *GetDocument().CssTarget());
EXPECT_EQ(1u, GetDocument().Markers().Markers().size());
@@ -1675,6 +1772,8 @@ TEST_F(TextFragmentAnchorTest, NonTextDirectives) {
<p id="first">This is a test page</p>
<p id="second">This is some more text</p>
)HTML");
+ // Render two frames to handle the async step added by the beforematch event.
+ Compositor().BeginFrame();
Compositor().BeginFrame();
RunAsyncMatchingTasks();
@@ -1705,39 +1804,15 @@ TEST_F(TextFragmentAnchorTest, CssTarget) {
<p id="text">test</p>
)HTML");
- // With BlockHTMLParserOnStyleSheetsEnabled, the text fragment anchor won't be
- // invoked until the CSS is loaded. Otherwise, we test the behavior where the
- // text fragment anchor is invoked before and after the stylesheet is applied.
- if (!RuntimeEnabledFeatures::BlockHTMLParserOnStyleSheetsEnabled()) {
- Compositor().PaintFrame();
- ScrollOffset first_scroll_offset = LayoutViewport()->GetScrollOffset();
- ASSERT_NE(ScrollOffset(), first_scroll_offset);
-
- Element& p = *GetDocument().getElementById("text");
- IntRect first_bounding_rect = BoundingRectInFrame(p);
- EXPECT_TRUE(ViewportRect().Contains(first_bounding_rect));
-
- // Load CSS that has target styling that moves the text out of view
- css_request.Complete(R"CSS(
- :target {
- margin-top: 2000px;
- }
- )CSS");
- RunPendingTasks();
- Compositor().BeginFrame();
-
- // Ensure the target text is still in view and stayed centered
- ASSERT_NE(first_scroll_offset, LayoutViewport()->GetScrollOffset());
- EXPECT_EQ(first_bounding_rect, BoundingRectInFrame(p));
- } else {
- css_request.Complete(R"CSS(
- :target {
- margin-top: 2000px;
- }
- )CSS");
- RunPendingTasks();
- Compositor().BeginFrame();
- }
+ css_request.Complete(R"CSS(
+ :target {
+ margin-top: 2000px;
+ }
+ )CSS");
+ RunPendingTasks();
+ // Render two frames to handle the async step added by the beforematch event.
+ Compositor().BeginFrame();
+ BeginEmptyFrame();
Element& p = *GetDocument().getElementById("text");
EXPECT_TRUE(ViewportRect().Contains(BoundingRectInFrame(p)));
diff --git a/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_finder.cc b/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_finder.cc
index 589f375e3a6..275576fe690 100644
--- a/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_finder.cc
+++ b/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_finder.cc
@@ -7,6 +7,7 @@
#include <memory>
#include "third_party/blink/public/platform/web_string.h"
+#include "third_party/blink/renderer/core/display_lock/display_lock_document_state.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/range.h"
#include "third_party/blink/renderer/core/editing/ephemeral_range.h"
@@ -176,20 +177,33 @@ TextFragmentFinder::TextFragmentFinder(Client& client,
const TextFragmentSelector& selector)
: client_(client), selector_(selector) {
DCHECK(!selector_.Start().IsEmpty());
+ DCHECK(selector_.Type() != TextFragmentSelector::SelectorType::kInvalid);
}
void TextFragmentFinder::FindMatch(Document& document) {
PositionInFlatTree search_start =
PositionInFlatTree::FirstPositionInNode(document);
- auto forced_lock_scope = document.GetScopedForceActivatableLocks();
+ auto forced_lock_scope =
+ document.GetDisplayLockDocumentState().GetScopedForceActivatableLocks();
document.UpdateStyleAndLayout(DocumentUpdateReason::kFindInPage);
EphemeralRangeInFlatTree match =
FindMatchFromPosition(document, search_start);
if (match.IsNotNull()) {
- client_.DidFindMatch(match);
+ TextFragmentAnchorMetrics::Match match_metrics(selector_);
+
+ if (selector_.Type() == TextFragmentSelector::SelectorType::kExact) {
+ // If it's an exact match, we don't need to do the PlainText conversion,
+ // we can just use the text from the selector.
+ DCHECK_EQ(selector_.Start().length(), PlainText(match).length());
+ match_metrics.text = selector_.Start();
+ } else if (selector_.Type() == TextFragmentSelector::SelectorType::kRange) {
+ match_metrics.text = PlainText(match);
+ }
+
+ client_.DidFindMatch(match, match_metrics);
// Continue searching to see if we have an ambiguous selector.
// TODO(crbug.com/919204): This is temporary and only for measuring
diff --git a/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_finder.h b/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_finder.h
index d4e2714e6fd..a59ebb1b9bc 100644
--- a/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_finder.h
+++ b/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_finder.h
@@ -7,6 +7,7 @@
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/editing/forward.h"
+#include "third_party/blink/renderer/core/page/scrolling/text_fragment_anchor_metrics.h"
#include "third_party/blink/renderer/core/page/scrolling/text_fragment_selector.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
@@ -21,7 +22,9 @@ class CORE_EXPORT TextFragmentFinder final {
public:
class Client {
public:
- virtual void DidFindMatch(const EphemeralRangeInFlatTree& range) = 0;
+ virtual void DidFindMatch(
+ const EphemeralRangeInFlatTree& range,
+ const TextFragmentAnchorMetrics::Match match_metrics) = 0;
virtual void DidFindAmbiguousMatch() = 0;
};
diff --git a/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_selector.h b/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_selector.h
index 536cdb59b89..06013500e8e 100644
--- a/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_selector.h
+++ b/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_selector.h
@@ -30,7 +30,7 @@ class CORE_EXPORT TextFragmentSelector final {
const String& end,
const String& prefix,
const String& suffix);
- TextFragmentSelector(SelectorType type);
+ explicit TextFragmentSelector(SelectorType type);
~TextFragmentSelector() = default;
SelectorType Type() const { return type_; }
diff --git a/chromium/third_party/blink/renderer/core/page/spatial_navigation_controller.cc b/chromium/third_party/blink/renderer/core/page/spatial_navigation_controller.cc
index 0db2f04a01d..7b4d0e8e8b6 100644
--- a/chromium/third_party/blink/renderer/core/page/spatial_navigation_controller.cc
+++ b/chromium/third_party/blink/renderer/core/page/spatial_navigation_controller.cc
@@ -15,6 +15,7 @@
#include "third_party/blink/renderer/core/editing/frame_selection.h"
#include "third_party/blink/renderer/core/events/keyboard_event.h"
#include "third_party/blink/renderer/core/events/web_input_event_conversion.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/settings.h"
#include "third_party/blink/renderer/core/frame/visual_viewport.h"
@@ -162,7 +163,11 @@ bool IsInAccessibilityMode(Page* page) {
SpatialNavigationController::SpatialNavigationController(Page& page)
: page_(&page),
- spatial_navigation_state_(mojom::blink::SpatialNavigationState::New()) {
+ spatial_navigation_state_(mojom::blink::SpatialNavigationState::New()),
+ spatial_navigation_host_(
+ DynamicTo<LocalFrame>(page.MainFrame())
+ ? DynamicTo<LocalFrame>(page.MainFrame())->DomWindow()
+ : nullptr) {
DCHECK(page_->GetSettings().GetSpatialNavigationEnabled());
}
@@ -300,6 +305,7 @@ void SpatialNavigationController::DidDetachFrameView(
void SpatialNavigationController::Trace(Visitor* visitor) {
visitor->Trace(interest_element_);
visitor->Trace(page_);
+ visitor->Trace(spatial_navigation_host_);
}
bool SpatialNavigationController::Advance(
@@ -533,7 +539,7 @@ void SpatialNavigationController::DispatchMouseMoveAt(Element* element) {
FloatPoint event_position_screen = event_position;
int click_count = 0;
WebMouseEvent fake_mouse_move_event(
- WebInputEvent::kMouseMove, event_position, event_position_screen,
+ WebInputEvent::Type::kMouseMove, event_position, event_position_screen,
WebPointerProperties::Button::kNoButton, click_count,
WebInputEvent::kRelativeMotionEvent, base::TimeTicks::Now());
Vector<WebMouseEvent> coalesced_events, predicted_events;
@@ -693,7 +699,8 @@ bool SpatialNavigationController::UpdateHasDefaultVideoControls(
return true;
}
-const mojo::Remote<mojom::blink::SpatialNavigationHost>&
+const HeapMojoRemote<mojom::blink::SpatialNavigationHost,
+ HeapMojoWrapperMode::kWithoutContextObserver>&
SpatialNavigationController::GetSpatialNavigationHost() {
if (!spatial_navigation_host_.is_bound()) {
LocalFrame* frame = DynamicTo<LocalFrame>(page_->MainFrame());
diff --git a/chromium/third_party/blink/renderer/core/page/spatial_navigation_controller.h b/chromium/third_party/blink/renderer/core/page/spatial_navigation_controller.h
index fe6831cca2b..efd72e2dc6f 100644
--- a/chromium/third_party/blink/renderer/core/page/spatial_navigation_controller.h
+++ b/chromium/third_party/blink/renderer/core/page/spatial_navigation_controller.h
@@ -5,11 +5,12 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_PAGE_SPATIAL_NAVIGATION_CONTROLLER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_PAGE_SPATIAL_NAVIGATION_CONTROLLER_H_
-#include "mojo/public/cpp/bindings/remote.h"
#include "third_party/blink/public/mojom/page/spatial_navigation.mojom-blink.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/page/spatial_navigation.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
+#include "third_party/blink/renderer/platform/mojo/heap_mojo_remote.h"
+#include "third_party/blink/renderer/platform/mojo/heap_mojo_wrapper_mode.h"
namespace blink {
@@ -106,7 +107,8 @@ class CORE_EXPORT SpatialNavigationController final
bool UpdateIsFormFocused(Element* element);
bool UpdateHasDefaultVideoControls(Element* element);
- const mojo::Remote<mojom::blink::SpatialNavigationHost>&
+ const HeapMojoRemote<mojom::blink::SpatialNavigationHost,
+ HeapMojoWrapperMode::kWithoutContextObserver>&
GetSpatialNavigationHost();
void ResetMojoBindings();
@@ -121,7 +123,9 @@ class CORE_EXPORT SpatialNavigationController final
bool enter_key_press_seen_ = false;
mojom::blink::SpatialNavigationStatePtr spatial_navigation_state_;
- mojo::Remote<mojom::blink::SpatialNavigationHost> spatial_navigation_host_;
+ HeapMojoRemote<mojom::blink::SpatialNavigationHost,
+ HeapMojoWrapperMode::kWithoutContextObserver>
+ spatial_navigation_host_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/page/spatial_navigation_test.cc b/chromium/third_party/blink/renderer/core/page/spatial_navigation_test.cc
index acad766887e..4b06392fe00 100644
--- a/chromium/third_party/blink/renderer/core/page/spatial_navigation_test.cc
+++ b/chromium/third_party/blink/renderer/core/page/spatial_navigation_test.cc
@@ -772,19 +772,19 @@ TEST_P(SpatialNavigationWithFocuslessModeTest, PressEnterKeyActiveElement) {
Element* b = GetDocument().getElementById("b");
// Move interest to button.
- WebKeyboardEvent arrow_down{WebInputEvent::kRawKeyDown,
+ WebKeyboardEvent arrow_down{WebInputEvent::Type::kRawKeyDown,
WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests()};
arrow_down.dom_key = ui::DomKey::ARROW_DOWN;
GetDocument().GetFrame()->GetEventHandler().KeyEvent(arrow_down);
- arrow_down.SetType(WebInputEvent::kKeyUp);
+ arrow_down.SetType(WebInputEvent::Type::kKeyUp);
GetDocument().GetFrame()->GetEventHandler().KeyEvent(arrow_down);
EXPECT_FALSE(b->IsActive());
// Enter key down add :active state to element.
- WebKeyboardEvent enter{WebInputEvent::kRawKeyDown,
+ WebKeyboardEvent enter{WebInputEvent::Type::kRawKeyDown,
WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests()};
enter.dom_key = ui::DomKey::ENTER;
@@ -792,7 +792,7 @@ TEST_P(SpatialNavigationWithFocuslessModeTest, PressEnterKeyActiveElement) {
EXPECT_TRUE(b->IsActive());
// Enter key up remove :active state to element.
- enter.SetType(WebInputEvent::kKeyUp);
+ enter.SetType(WebInputEvent::Type::kKeyUp);
GetDocument().GetFrame()->GetEventHandler().KeyEvent(enter);
EXPECT_FALSE(b->IsActive());
}
@@ -807,22 +807,22 @@ class FocuslessSpatialNavigationSimTest : public SimTest {
}
void SimulateKeyPress(int dom_key) {
- WebKeyboardEvent event{WebInputEvent::kRawKeyDown,
+ WebKeyboardEvent event{WebInputEvent::Type::kRawKeyDown,
WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests()};
event.dom_key = dom_key;
WebView().MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(event));
+ WebCoalescedInputEvent(event, ui::LatencyInfo()));
if (dom_key == ui::DomKey::ENTER) {
- event.SetType(WebInputEvent::kChar);
+ event.SetType(WebInputEvent::Type::kChar);
WebView().MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(event));
+ WebCoalescedInputEvent(event, ui::LatencyInfo()));
}
- event.SetType(WebInputEvent::kKeyUp);
+ event.SetType(WebInputEvent::Type::kKeyUp);
WebView().MainFrameWidget()->HandleInputEvent(
- WebCoalescedInputEvent(event));
+ WebCoalescedInputEvent(event, ui::LatencyInfo()));
}
ScopedFocuslessSpatialNavigationForTest use_focusless_mode_;
diff --git a/chromium/third_party/blink/renderer/core/page/validation_message_overlay_delegate.cc b/chromium/third_party/blink/renderer/core/page/validation_message_overlay_delegate.cc
index cad8d885d3d..ffc35f8455f 100644
--- a/chromium/third_party/blink/renderer/core/page/validation_message_overlay_delegate.cc
+++ b/chromium/third_party/blink/renderer/core/page/validation_message_overlay_delegate.cc
@@ -158,8 +158,8 @@ void ValidationMessageOverlayDelegate::CreatePage(const FrameOverlay& overlay) {
main_settings.GetMinimumLogicalFontSize());
auto* frame = MakeGarbageCollected<LocalFrame>(
- MakeGarbageCollected<EmptyLocalFrameClient>(), *page_, nullptr, nullptr,
- nullptr);
+ MakeGarbageCollected<EmptyLocalFrameClient>(), *page_, nullptr,
+ base::UnguessableToken::Create(), nullptr, nullptr);
frame->SetView(MakeGarbageCollected<LocalFrameView>(*frame, view_size));
frame->Init();
frame->View()->SetCanHaveScrollbars(false);
diff --git a/chromium/third_party/blink/renderer/core/page/viewport_test.cc b/chromium/third_party/blink/renderer/core/page/viewport_test.cc
index 40e96faaee7..5c0e2100f08 100644
--- a/chromium/third_party/blink/renderer/core/page/viewport_test.cc
+++ b/chromium/third_party/blink/renderer/core/page/viewport_test.cc
@@ -2795,20 +2795,6 @@ TEST_F(ViewportTest, viewportLegacyOrdering8) {
EXPECT_TRUE(page->GetViewportDescription().user_zoom);
}
-TEST_F(ViewportTest, viewportLegacyEmptyAtViewportDoesntOverrideViewportMeta) {
- RegisterMockedHttpURLLoad("viewport/viewport-legacy-ordering-10.html");
-
- frame_test_helpers::WebViewHelper web_view_helper;
- web_view_helper.InitializeAndLoad(
- base_url_ + "viewport/viewport-legacy-ordering-10.html", nullptr, nullptr,
- nullptr, SetViewportSettings);
-
- Page* page = web_view_helper.GetWebView()->GetPage();
- PageScaleConstraints constraints = RunViewportTest(page, 800, 600);
-
- EXPECT_EQ(5000, constraints.layout_size.Width());
-}
-
TEST_F(ViewportTest, viewportLegacyDefaultValueChangedByXHTMLMP) {
RegisterMockedHttpURLLoad("viewport/viewport-legacy-xhtmlmp.html");
diff --git a/chromium/third_party/blink/renderer/core/paint/BUILD.gn b/chromium/third_party/blink/renderer/core/paint/BUILD.gn
index 98c25ea6a92..c0ddeecaec4 100644
--- a/chromium/third_party/blink/renderer/core/paint/BUILD.gn
+++ b/chromium/third_party/blink/renderer/core/paint/BUILD.gn
@@ -206,8 +206,6 @@ blink_core_sources("paint") {
"selection_painting_utils.h",
"svg_container_painter.cc",
"svg_container_painter.h",
- "svg_filter_painter.cc",
- "svg_filter_painter.h",
"svg_foreign_object_painter.cc",
"svg_foreign_object_painter.h",
"svg_image_painter.cc",
@@ -259,6 +257,8 @@ blink_core_sources("paint") {
"theme_painter_default.h",
"theme_painter_mac.h",
"theme_painter_mac.mm",
+ "url_metadata_utils.cc",
+ "url_metadata_utils.h",
"video_painter.cc",
"video_painter.h",
"view_painter.cc",
diff --git a/chromium/third_party/blink/renderer/core/paint/DEPS b/chromium/third_party/blink/renderer/core/paint/DEPS
index 75b3e64e39c..4283a731d52 100644
--- a/chromium/third_party/blink/renderer/core/paint/DEPS
+++ b/chromium/third_party/blink/renderer/core/paint/DEPS
@@ -14,6 +14,9 @@ specific_include_rules = {
".*test\.cc": [
"+base/test/trace_event_analyzer.h",
],
+ "ng_box_fragment_painter_test.cc": [
+ "+components/paint_preview/common/paint_preview_tracker.h",
+ ],
"video_painter_test.cc": [
"+components/paint_preview/common/paint_preview_tracker.h",
],
diff --git a/chromium/third_party/blink/renderer/core/paint/applied_decoration_painter.cc b/chromium/third_party/blink/renderer/core/paint/applied_decoration_painter.cc
index b428f2f6c96..2c372e384af 100644
--- a/chromium/third_party/blink/renderer/core/paint/applied_decoration_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/applied_decoration_painter.cc
@@ -84,7 +84,6 @@ FloatRect AppliedDecorationPainter::Bounds() {
}
case ETextDecorationStyle::kWavy:
return PrepareWavyStrokePath().StrokeBoundingRect(stroke_data);
- break;
case ETextDecorationStyle::kDouble:
if (double_offset_ > 0) {
return FloatRect(start_point_.X(), start_point_.Y(),
@@ -94,7 +93,6 @@ FloatRect AppliedDecorationPainter::Bounds() {
return FloatRect(start_point_.X(), start_point_.Y() + double_offset_,
decoration_info_.width,
-double_offset_ + decoration_info_.thickness);
- break;
case ETextDecorationStyle::kSolid:
return FloatRect(start_point_.X(), start_point_.Y(),
decoration_info_.width, decoration_info_.thickness);
diff --git a/chromium/third_party/blink/renderer/core/paint/background_image_geometry.cc b/chromium/third_party/blink/renderer/core/paint/background_image_geometry.cc
index eadaebbe0fc..6920506ba5b 100644
--- a/chromium/third_party/blink/renderer/core/paint/background_image_geometry.cc
+++ b/chromium/third_party/blink/renderer/core/paint/background_image_geometry.cc
@@ -89,16 +89,10 @@ void BackgroundImageGeometry::SetNoRepeatX(const FillLayer& fill_layer,
}
if (x_offset > 0) {
- DCHECK(snapped_x_offset >= LayoutUnit());
// Move the dest rect if the offset is positive. The image "stays" where
// it is over the dest rect, so this effectively modifies the phase.
unsnapped_dest_rect_.Move(x_offset, LayoutUnit());
-
- // For the snapped geometry, note that negative x_offsets typically
- // arise when using positive offsets from the bottom of the background
- // rect. We try to move the snapped dest rect to give the same offset.
- LayoutUnit dx = snapped_dest_rect_.Width() - unsnapped_dest_rect_.Width();
- snapped_dest_rect_.Move(x_offset + dx, LayoutUnit());
+ snapped_dest_rect_.SetX(LayoutUnit(unsnapped_dest_rect_.X().Round()));
// Make the dest as wide as a tile, which will reduce the dest
// rect if the tile is too small to fill the paint_rect. If not,
@@ -134,17 +128,12 @@ void BackgroundImageGeometry::SetNoRepeatY(const FillLayer& fill_layer,
LayoutSize(SpaceSize().Width(), unsnapped_dest_rect_.Height()));
return;
}
+
if (y_offset > 0) {
- DCHECK(snapped_y_offset >= LayoutUnit());
// Move the dest rect if the offset is positive. The image "stays" where
// it is in the paint rect, so this effectively modifies the phase.
unsnapped_dest_rect_.Move(LayoutUnit(), y_offset);
-
- // For the snapped geometry, note that negative y_offsets typically
- // arise when using positive offsets from the bottom of the background
- // rect. We try to move the snapped dest rect to give the same offset.
- LayoutUnit dy = snapped_dest_rect_.Height() - unsnapped_dest_rect_.Height();
- snapped_dest_rect_.Move(LayoutUnit(), y_offset + dy);
+ snapped_dest_rect_.SetY(LayoutUnit(unsnapped_dest_rect_.Y().Round()));
// Make the dest as wide as a tile, which will reduce the dest
// rect if the tile is too small to fill the paint_rect. If not,
@@ -182,7 +171,7 @@ void BackgroundImageGeometry::SetRepeatX(const FillLayer& fill_layer,
// unsnapped widths to correctly set the phase.
LayoutUnit computed_position =
MinimumValueForLength(fill_layer.PositionX(), available_width) -
- offset_in_background_.X();
+ OffsetInBackground(fill_layer).X();
// Identify the number of tiles that fit within the computed
// position in the direction we should be moving.
@@ -219,7 +208,7 @@ void BackgroundImageGeometry::SetRepeatY(const FillLayer& fill_layer,
// unsnapped widths to correctly set the phase.
LayoutUnit computed_position =
MinimumValueForLength(fill_layer.PositionY(), available_height) -
- offset_in_background_.Y();
+ OffsetInBackground(fill_layer).Y();
// Identify the number of tiles that fit within the computed
// position in the direction we should be moving.
@@ -292,7 +281,7 @@ static void ExpandToTableColumnGroup(const LayoutTableCell& cell,
}
}
-LayoutPoint BackgroundImageGeometry::GetOffsetForCell(
+LayoutPoint BackgroundImageGeometry::GetPositioningOffsetForCell(
const LayoutTableCell& cell,
const LayoutBox& positioning_box) {
LayoutSize border_spacing = LayoutSize(cell.Table()->HBorderSpacing(),
@@ -424,15 +413,14 @@ LayoutRect FixedAttachmentPositioningArea(const LayoutBoxModelObject& obj,
BackgroundImageGeometry::BackgroundImageGeometry(
const LayoutView& view,
- bool root_elemnet_has_transform)
- : box_(view),
- positioning_box_(view.RootBox()),
- painting_view_(true),
- root_element_has_transform_(root_elemnet_has_transform) {
+ const LayoutPoint& element_positioning_area_offset)
+ : box_(view), positioning_box_(view.RootBox()), painting_view_(true) {
// The background of the box generated by the root element covers the
// entire canvas and will be painted by the view object, but the we should
// still use the root element box for positioning.
positioning_size_override_ = view.RootBox().Size();
+ // The background image should paint from the root element's coordinate space.
+ element_positioning_area_offset_ = element_positioning_area_offset;
}
BackgroundImageGeometry::BackgroundImageGeometry(
@@ -453,8 +441,8 @@ BackgroundImageGeometry::BackgroundImageGeometry(
cell_using_container_background_ =
background_object && !background_object->IsTableCell();
if (cell_using_container_background_) {
- offset_in_background_ =
- GetOffsetForCell(cell, ToLayoutBox(*background_object));
+ element_positioning_area_offset_ =
+ GetPositioningOffsetForCell(cell, ToLayoutBox(*background_object));
positioning_size_override_ =
GetBackgroundObjectDimensions(cell, ToLayoutBox(*background_object));
}
@@ -625,7 +613,6 @@ void BackgroundImageGeometry::ComputePositioningArea(
if (ShouldUseFixedAttachment(fill_layer)) {
// No snapping for fixed attachment.
SetHasNonLocalGeometry();
- offset_in_background_ = LayoutPoint();
unsnapped_positioning_area =
FixedAttachmentPositioningArea(box_, container, flags);
unsnapped_dest_rect_ = snapped_dest_rect_ = snapped_positioning_area =
@@ -702,17 +689,6 @@ void BackgroundImageGeometry::ComputePositioningArea(
snapped_box_offset =
LayoutPoint(snapped_box_outset.Left() - snapped_dest_adjust.Left(),
snapped_box_outset.Top() - snapped_dest_adjust.Top());
-
- // |paint_rect|'s location is usually assumed by BackgroundImageGeometry
- // to encode paint offset in the local transform space. The one case in
- // which this is not true is painting the background of the LayoutView
- // canvas when the HTML element has a transform. In that case, the
- // paint offset is zero, and the offset gets applied later by a
- // PaintOffsetTranslation.
- if (painting_view_ && root_element_has_transform_) {
- unsnapped_box_offset -= paint_rect.Location();
- snapped_box_offset -= paint_rect.Location();
- }
}
}
@@ -897,10 +873,10 @@ void BackgroundImageGeometry::Calculate(const LayoutBoxModelObject* container,
// snapped values.
LayoutUnit computed_x_position =
MinimumValueForLength(fill_layer.PositionX(), snapped_available_width) -
- offset_in_background_.X();
+ OffsetInBackground(fill_layer).X();
LayoutUnit computed_y_position =
MinimumValueForLength(fill_layer.PositionY(), snapped_available_height) -
- offset_in_background_.Y();
+ OffsetInBackground(fill_layer).Y();
if (background_repeat_x == EFillRepeat::kRoundFill &&
snapped_positioning_area_size.Width() > LayoutUnit() &&
@@ -978,7 +954,7 @@ void BackgroundImageGeometry::Calculate(const LayoutBoxModelObject* container,
: computed_x_position;
SetNoRepeatX(fill_layer, unsnapped_box_offset.X() + x_offset,
snapped_box_offset.X() + snapped_x_offset);
- if (offset_in_background_.X() > tile_size_.Width())
+ if (OffsetInBackground(fill_layer).X() > tile_size_.Width())
unsnapped_dest_rect_ = snapped_dest_rect_ = LayoutRect();
}
@@ -1009,7 +985,7 @@ void BackgroundImageGeometry::Calculate(const LayoutBoxModelObject* container,
: computed_y_position;
SetNoRepeatY(fill_layer, unsnapped_box_offset.Y() + y_offset,
snapped_box_offset.Y() + snapped_y_offset);
- if (offset_in_background_.Y() > tile_size_.Height())
+ if (OffsetInBackground(fill_layer).Y() > tile_size_.Height())
unsnapped_dest_rect_ = snapped_dest_rect_ = LayoutRect();
}
@@ -1044,4 +1020,11 @@ InterpolationQuality BackgroundImageGeometry::ImageInterpolationQuality()
return box_.StyleRef().GetInterpolationQuality();
}
+LayoutPoint BackgroundImageGeometry::OffsetInBackground(
+ const FillLayer& fill_layer) const {
+ if (ShouldUseFixedAttachment(fill_layer))
+ return LayoutPoint();
+ return element_positioning_area_offset_;
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/background_image_geometry.h b/chromium/third_party/blink/renderer/core/paint/background_image_geometry.h
index 02c1f2eb794..24b397440eb 100644
--- a/chromium/third_party/blink/renderer/core/paint/background_image_geometry.h
+++ b/chromium/third_party/blink/renderer/core/paint/background_image_geometry.h
@@ -31,7 +31,8 @@ class BackgroundImageGeometry {
public:
// Constructor for LayoutView where the coordinate space is different.
- BackgroundImageGeometry(const LayoutView&, bool root_elemnet_has_transform);
+ BackgroundImageGeometry(const LayoutView&,
+ const LayoutPoint& element_positioning_area_offset);
// Constructor for table cells where background_object may be the row or
// column the background image is attached to.
@@ -95,9 +96,9 @@ class BackgroundImageGeometry {
const ComputedStyle& ImageStyle() const;
InterpolationQuality ImageInterpolationQuality() const;
+ private:
static bool ShouldUseFixedAttachment(const FillLayer&);
- private:
void SetSpaceSize(const LayoutSize& repeat_spacing) {
repeat_spacing_ = repeat_spacing;
}
@@ -121,7 +122,8 @@ class BackgroundImageGeometry {
void UseFixedAttachment(const LayoutPoint& attachment_point);
void SetHasNonLocalGeometry() { has_non_local_geometry_ = true; }
- LayoutPoint GetOffsetForCell(const LayoutTableCell&, const LayoutBox&);
+ LayoutPoint GetPositioningOffsetForCell(const LayoutTableCell&,
+ const LayoutBox&);
LayoutSize GetBackgroundObjectDimensions(const LayoutTableCell&,
const LayoutBox&);
@@ -157,6 +159,9 @@ class BackgroundImageGeometry {
const LayoutSize&,
const LayoutSize&);
+ // The offset of the background image within the background positioning area.
+ LayoutPoint OffsetInBackground(const FillLayer&) const;
+
// |box_| is the source for the Document. In most cases it also provides the
// background properties (see |positioning_box_| for exceptions.) It's also
// the image client unless painting the view background.
@@ -172,9 +177,9 @@ class BackgroundImageGeometry {
// differs from the requested paint rect.
LayoutSize positioning_size_override_;
- // Used only when painting table cells, this is the cell's background
- // offset within the table's background positioning area.
- LayoutPoint offset_in_background_;
+ // The background image offset from within the background positioning area for
+ // non-fixed background attachment. Used for table cells and the view.
+ LayoutPoint element_positioning_area_offset_;
LayoutRect unsnapped_dest_rect_;
LayoutRect snapped_dest_rect_;
@@ -185,7 +190,6 @@ class BackgroundImageGeometry {
bool painting_view_ = false;
bool painting_table_cell_ = false;
bool cell_using_container_background_ = false;
- bool root_element_has_transform_ = false;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/box_painter.cc b/chromium/third_party/blink/renderer/core/paint/box_painter.cc
index be14cf89e05..b07886218ca 100644
--- a/chromium/third_party/blink/renderer/core/paint/box_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/box_painter.cc
@@ -299,23 +299,19 @@ void BoxPainter::RecordScrollHitTestData(
if (!fragment)
return;
- // Only create scroll hit test data for objects that scroll.
- if (layout_box_.GetScrollableArea()->ScrollsOverflow()) {
- const auto* properties = fragment->PaintProperties();
-
- // If there is an associated scroll node, emit scroll hit test data.
- if (properties && properties->Scroll()) {
- DCHECK(properties->ScrollTranslation());
- // We record scroll hit test data in the local border box properties
- // instead of the contents properties so that the scroll hit test is not
- // clipped or scrolled.
- auto& paint_controller = paint_info.context.GetPaintController();
- DCHECK_EQ(fragment->LocalBorderBoxProperties(),
- paint_controller.CurrentPaintChunkProperties());
- paint_controller.RecordScrollHitTestData(
- background_client, DisplayItem::kScrollHitTest,
- properties->ScrollTranslation(), fragment->VisualRect());
- }
+ // If there is an associated scroll node, emit scroll hit test data.
+ const auto* properties = fragment->PaintProperties();
+ if (properties && properties->Scroll()) {
+ DCHECK(properties->ScrollTranslation());
+ // We record scroll hit test data in the local border box properties
+ // instead of the contents properties so that the scroll hit test is not
+ // clipped or scrolled.
+ auto& paint_controller = paint_info.context.GetPaintController();
+ DCHECK_EQ(fragment->LocalBorderBoxProperties(),
+ paint_controller.CurrentPaintChunkProperties());
+ paint_controller.RecordScrollHitTestData(
+ background_client, DisplayItem::kScrollHitTest,
+ properties->ScrollTranslation(), fragment->VisualRect());
}
ScrollableAreaPainter(*layout_box_.GetScrollableArea())
diff --git a/chromium/third_party/blink/renderer/core/paint/box_painter_test.cc b/chromium/third_party/blink/renderer/core/paint/box_painter_test.cc
index 5a929df6094..e2568b1663a 100644
--- a/chromium/third_party/blink/renderer/core/paint/box_painter_test.cc
+++ b/chromium/third_party/blink/renderer/core/paint/box_painter_test.cc
@@ -44,19 +44,28 @@ TEST_P(BoxPainterTest, EmptyDecorationBackground) {
IsSameId(div1, kBackgroundType),
IsSameId(div2, DisplayItem::PaintPhaseToDrawingType(
PaintPhase::kSelfOutlineOnly))));
- EXPECT_THAT(
- RootPaintController().PaintChunks(),
- ElementsAre(
- IsPaintChunk(0, 1,
- PaintChunk::Id(ViewScrollingBackgroundClient(),
- kDocumentBackgroundType),
- GetLayoutView().FirstFragment().ContentsProperties(),
- nullptr, IntRect(0, 0, 800, 600)),
- // Empty backgrounds contribute to bounds of paint chunks.
- IsPaintChunk(1, 3,
- PaintChunk::Id(*body->Layer(), DisplayItem::kLayerChunk),
- body->FirstFragment().LocalBorderBoxProperties(),
- nullptr, IntRect(-2, 0, 202, 350))));
+
+ if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
+ EXPECT_THAT(
+ RootPaintController().PaintChunks(),
+ ElementsAre(
+ IsPaintChunk(0, 0), IsPaintChunk(0, 1), // LayoutView chunks.
+ // Empty backgrounds contribute to bounds of paint chunks.
+ IsPaintChunk(
+ 1, 3, PaintChunk::Id(*body->Layer(), DisplayItem::kLayerChunk),
+ body->FirstFragment().LocalBorderBoxProperties(), nullptr,
+ IntRect(-2, 0, 202, 350))));
+ } else {
+ EXPECT_THAT(
+ RootPaintController().PaintChunks(),
+ ElementsAre(
+ IsPaintChunk(0, 1), // LayoutView chunks.
+ // Empty backgrounds contribute to bounds of paint chunks.
+ IsPaintChunk(
+ 1, 3, PaintChunk::Id(*body->Layer(), DisplayItem::kLayerChunk),
+ body->FirstFragment().LocalBorderBoxProperties(), nullptr,
+ IntRect(-2, 0, 202, 350))));
+ }
}
TEST_P(BoxPainterTest, ScrollHitTestOrderWithScrollBackgroundAttachment) {
@@ -101,10 +110,7 @@ TEST_P(BoxPainterTest, ScrollHitTestOrderWithScrollBackgroundAttachment) {
EXPECT_THAT(
RootPaintController().PaintChunks(),
ElementsAre(
- IsPaintChunk(0, 1,
- PaintChunk::Id(ViewScrollingBackgroundClient(),
- kDocumentBackgroundType),
- GetLayoutView().FirstFragment().ContentsProperties()),
+ IsPaintChunk(0, 0), IsPaintChunk(0, 1), // LayoutView chunks.
IsPaintChunk(
1, 2,
PaintChunk::Id(*container.Layer(), DisplayItem::kLayerChunk),
@@ -176,10 +182,7 @@ TEST_P(BoxPainterTest, ScrollHitTestOrderWithLocalBackgroundAttachment) {
EXPECT_THAT(
RootPaintController().PaintChunks(),
ElementsAre(
- IsPaintChunk(0, 1,
- PaintChunk::Id(ViewScrollingBackgroundClient(),
- kDocumentBackgroundType),
- GetLayoutView().FirstFragment().ContentsProperties()),
+ IsPaintChunk(0, 0), IsPaintChunk(0, 1), // LayoutView chunks.
IsPaintChunk(
1, 1,
PaintChunk::Id(*container.Layer(), DisplayItem::kLayerChunk),
@@ -250,40 +253,59 @@ TEST_P(BoxPainterTest, ScrollHitTestProperties) {
scroll_hit_test_data.scroll_translation =
&scrolling_contents_properties.Transform();
scroll_hit_test_data.scroll_hit_test_rect = IntRect(0, 0, 200, 200);
- EXPECT_THAT(
- paint_chunks,
- ElementsAre(
- IsPaintChunk(0, 1,
- PaintChunk::Id(ViewScrollingBackgroundClient(),
- kDocumentBackgroundType),
- GetLayoutView().FirstFragment().ContentsProperties()),
- IsPaintChunk(
- 1, 2,
- PaintChunk::Id(*container.Layer(), DisplayItem::kLayerChunk),
- container.FirstFragment().LocalBorderBoxProperties()),
- IsPaintChunk(2, 2,
- PaintChunk::Id(container, DisplayItem::kScrollHitTest),
- container.FirstFragment().LocalBorderBoxProperties(),
- &scroll_hit_test_data, IntRect(0, 0, 200, 200)),
- IsPaintChunk(
- 2, 3,
- PaintChunk::Id(container, kClippedContentsBackgroundChunkType),
- scrolling_contents_properties)));
+ if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
+ EXPECT_THAT(
+ paint_chunks,
+ ElementsAre(
+ IsPaintChunk(0, 0), IsPaintChunk(0, 1), // LayoutView chunks.
+ IsPaintChunk(
+ 1, 2,
+ PaintChunk::Id(*container.Layer(), DisplayItem::kLayerChunk),
+ container.FirstFragment().LocalBorderBoxProperties()),
+ IsPaintChunk(2, 2,
+ PaintChunk::Id(container, DisplayItem::kScrollHitTest),
+ container.FirstFragment().LocalBorderBoxProperties(),
+ &scroll_hit_test_data, IntRect(0, 0, 200, 200)),
+ IsPaintChunk(
+ 2, 3,
+ PaintChunk::Id(container, kClippedContentsBackgroundChunkType),
+ scrolling_contents_properties)));
+ } else {
+ EXPECT_THAT(
+ paint_chunks,
+ ElementsAre(
+ IsPaintChunk(0, 1), // LayoutView.
+ IsPaintChunk(
+ 1, 2,
+ PaintChunk::Id(*container.Layer(), DisplayItem::kLayerChunk),
+ container.FirstFragment().LocalBorderBoxProperties()),
+ IsPaintChunk(2, 2,
+ PaintChunk::Id(container, DisplayItem::kScrollHitTest),
+ container.FirstFragment().LocalBorderBoxProperties(),
+ &scroll_hit_test_data, IntRect(0, 0, 200, 200)),
+ IsPaintChunk(
+ 2, 3,
+ PaintChunk::Id(container, kClippedContentsBackgroundChunkType),
+ scrolling_contents_properties)));
+ }
// We always create scroll node for the root layer.
- const auto& root_transform = paint_chunks[0].properties.Transform();
+ wtf_size_t chunk_index =
+ RuntimeEnabledFeatures::CompositeAfterPaintEnabled() ? 1 : 0;
+ const auto& root_transform = paint_chunks[chunk_index].properties.Transform();
EXPECT_NE(nullptr, root_transform.ScrollNode());
// The container's background chunk should not scroll and therefore should use
// the root transform. Its local transform is actually a paint offset
// transform.
- const auto& container_transform = paint_chunks[1].properties.Transform();
+ const auto& container_transform =
+ paint_chunks[++chunk_index].properties.Transform();
EXPECT_EQ(&root_transform, container_transform.Parent());
EXPECT_EQ(nullptr, container_transform.ScrollNode());
// The scroll hit test should not be scrolled and should not be clipped.
// Its local transform is actually a paint offset transform.
- const auto& scroll_hit_test_chunk = paint_chunks[2];
+ const auto& scroll_hit_test_chunk = paint_chunks[++chunk_index];
const auto& scroll_hit_test_transform =
scroll_hit_test_chunk.properties.Transform();
EXPECT_EQ(nullptr, scroll_hit_test_transform.ScrollNode());
@@ -293,7 +315,7 @@ TEST_P(BoxPainterTest, ScrollHitTestProperties) {
scroll_hit_test_clip.UnsnappedClipRect().Rect());
// The scrolled contents should be scrolled and clipped.
- const auto& contents_chunk = paint_chunks[3];
+ const auto& contents_chunk = paint_chunks[++chunk_index];
const auto& contents_transform = contents_chunk.properties.Transform();
const auto* contents_scroll = contents_transform.ScrollNode();
EXPECT_EQ(IntSize(200, 300), contents_scroll->ContentsSize());
diff --git a/chromium/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.cc b/chromium/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.cc
index 4a32393fafc..91ceb4707ee 100644
--- a/chromium/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.cc
+++ b/chromium/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.cc
@@ -39,7 +39,6 @@
#include "third_party/blink/renderer/core/html/canvas/canvas_rendering_context.h"
#include "third_party/blink/renderer/core/html/canvas/html_canvas_element.h"
#include "third_party/blink/renderer/core/html/html_iframe_element.h"
-#include "third_party/blink/renderer/core/html/html_image_element.h"
#include "third_party/blink/renderer/core/html/media/html_media_element.h"
#include "third_party/blink/renderer/core/html/media/html_video_element.h"
#include "third_party/blink/renderer/core/html_names.h"
@@ -48,12 +47,10 @@
#include "third_party/blink/renderer/core/layout/layout_embedded_content.h"
#include "third_party/blink/renderer/core/layout/layout_embedded_object.h"
#include "third_party/blink/renderer/core/layout/layout_html_canvas.h"
-#include "third_party/blink/renderer/core/layout/layout_image.h"
#include "third_party/blink/renderer/core/layout/layout_inline.h"
#include "third_party/blink/renderer/core/layout/layout_shift_tracker.h"
#include "third_party/blink/renderer/core/layout/layout_video.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
-#include "third_party/blink/renderer/core/loader/resource/image_resource_content.h"
#include "third_party/blink/renderer/core/page/chrome_client.h"
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/core/page/scrolling/scrolling_coordinator.h"
@@ -72,7 +69,6 @@
#include "third_party/blink/renderer/core/probe/core_probes.h"
#include "third_party/blink/renderer/platform/fonts/font_cache.h"
#include "third_party/blink/renderer/platform/geometry/length_functions.h"
-#include "third_party/blink/renderer/platform/graphics/bitmap_image.h"
#include "third_party/blink/renderer/platform/graphics/compositor_filter_operations.h"
#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
#include "third_party/blink/renderer/platform/graphics/paint/cull_rect.h"
@@ -183,7 +179,7 @@ static bool NeedsDecorationOutlineLayer(const PaintLayer& paint_layer,
layout_object.IsCanvas() || IsA<LayoutVideo>(layout_object);
return could_obscure_decorations && layout_object.StyleRef().HasOutline() &&
- layout_object.StyleRef().OutlineOffset() < -min_border_width;
+ layout_object.StyleRef().OutlineOffsetInt() < -min_border_width;
}
CompositedLayerMapping::CompositedLayerMapping(PaintLayer& layer)
@@ -403,14 +399,6 @@ bool CompositedLayerMapping::UpdateGraphicsLayerConfiguration(
UpdateBackgroundColor();
- if (layout_object.IsImage()) {
- if (IsDirectlyCompositedImage()) {
- UpdateImageContents();
- } else if (graphics_layer_->HasContentsLayer()) {
- graphics_layer_->SetContentsToImage(nullptr, Image::kUnspecifiedDecode);
- }
- }
-
if (layout_object.IsLayoutEmbeddedContent()) {
if (WebPluginContainerImpl* plugin = GetPluginContainer(layout_object)) {
graphics_layer_->SetContentsToCcLayer(
@@ -448,9 +436,6 @@ bool CompositedLayerMapping::UpdateGraphicsLayerConfiguration(
UpdateElementId();
- graphics_layer_->SetHasWillChangeTransformHint(
- style.HasWillChangeTransformHint());
-
if (style.Preserves3D() && style.HasOpacity() &&
owning_layer_.Has3DTransformedDescendant()) {
UseCounter::Count(layout_object.GetDocument(),
@@ -997,7 +982,7 @@ void CompositedLayerMapping::UpdateDrawsContentAndPaintsHitTest() {
scrolling_contents_are_empty_ =
!owning_layer_.HasVisibleContent() ||
!(GetLayoutObject().StyleRef().HasBackground() ||
- GetLayoutObject().HasBackdropFilter() || PaintsChildren());
+ GetLayoutObject().HasNonInitialBackdropFilter() || PaintsChildren());
scrolling_contents_layer_->SetDrawsContent(!scrolling_contents_are_empty_);
scrolling_contents_layer_->SetPaintsHitTest(paints_hit_test);
}
@@ -1303,8 +1288,9 @@ bool CompositedLayerMapping::UpdateMaskLayer(bool needs_mask_layer) {
GetLayoutObject().UniqueId(),
CompositorElementIdNamespace::kEffectMask);
mask_layer_->SetElementId(element_id);
- if (GetLayoutObject().HasBackdropFilter())
+ if (GetLayoutObject().HasNonInitialBackdropFilter())
mask_layer_->CcLayer()->SetIsBackdropFilterMask(true);
+ mask_layer_->SetHitTestable(true);
layer_changed = true;
}
} else if (mask_layer_) {
@@ -1477,9 +1463,6 @@ bool CompositedLayerMapping::ContainsPaintedContent() const {
if (CompositedBounds().IsEmpty())
return false;
- if (GetLayoutObject().IsImage() && IsDirectlyCompositedImage())
- return false;
-
LayoutObject& layout_object = GetLayoutObject();
// FIXME: we could optimize cases where the image, video or canvas is known to
// fill the border box entirely, and set background color on the layer in that
@@ -1528,43 +1511,7 @@ bool CompositedLayerMapping::ContainsPaintedContent() const {
return PaintsChildren();
}
-// An image can be directly composited if it's the sole content of the layer,
-// and has no box decorations or clipping that require painting. Direct
-// compositing saves a backing store.
-bool CompositedLayerMapping::IsDirectlyCompositedImage() const {
- DCHECK(GetLayoutObject().IsImage());
-
- LayoutImage& image_layout_object = ToLayoutImage(GetLayoutObject());
-
- if (owning_layer_.HasBoxDecorationsOrBackground() ||
- image_layout_object.HasClip() || image_layout_object.HasClipPath() ||
- image_layout_object.HasObjectFit())
- return false;
-
- if (ImageResourceContent* cached_image = image_layout_object.CachedImage()) {
- if (!cached_image->HasImage())
- return false;
-
- if (!IsA<BitmapImage>(cached_image->GetImage()))
- return false;
-
- UseCounter::Count(GetLayoutObject().GetDocument(),
- WebFeature::kDirectlyCompositedImage);
- return true;
- }
-
- return false;
-}
-
void CompositedLayerMapping::ContentChanged(ContentChangeType change_type) {
- if ((change_type == kImageChanged) && GetLayoutObject().IsImage() &&
- IsDirectlyCompositedImage()) {
- SetNeedsGraphicsLayerUpdate(kGraphicsLayerUpdateLocal);
- Compositor()->SetNeedsCompositingUpdate(
- kCompositingUpdateAfterGeometryChange);
- return;
- }
-
if (change_type == kCanvasChanged &&
IsTextureLayerCanvas(GetLayoutObject())) {
graphics_layer_->SetContentsNeedsDisplay();
@@ -1572,49 +1519,6 @@ void CompositedLayerMapping::ContentChanged(ContentChangeType change_type) {
}
}
-void CompositedLayerMapping::UpdateImageContents() {
- DCHECK_EQ(owning_layer_.Compositor()->Lifecycle().GetState(),
- DocumentLifecycle::kInCompositingUpdate);
-
- DCHECK(GetLayoutObject().IsImage());
- LayoutImage& image_layout_object = ToLayoutImage(GetLayoutObject());
-
- ImageResourceContent* cached_image = image_layout_object.CachedImage();
- if (!cached_image)
- return;
-
- Image* image = cached_image->GetImage();
- if (!image)
- return;
-
- auto* html_image_element =
- DynamicTo<HTMLImageElement>(image_layout_object.GetNode());
- Image::ImageDecodingMode decode_mode =
- html_image_element ? html_image_element->GetDecodingModeForPainting(
- image->paint_image_id())
- : Image::kUnspecifiedDecode;
-
- // This is a no-op if the layer doesn't have an inner layer for the image.
- graphics_layer_->SetContentsToImage(
- image, decode_mode,
- LayoutObject::ShouldRespectImageOrientation(&image_layout_object));
-
- graphics_layer_->SetFilterQuality(
- GetLayoutObject().StyleRef().ImageRendering() ==
- EImageRendering::kPixelated
- ? kNone_SkFilterQuality
- : kLow_SkFilterQuality);
-
- // Prevent double-drawing: https://bugs.webkit.org/show_bug.cgi?id=58632
- UpdateDrawsContentAndPaintsHitTest();
-
- // Image animation is "lazy", in that it automatically stops unless someone is
- // drawing the image. So we have to kick the animation each time; this has the
- // downside that the image will keep animating, even if its layer is not
- // visible.
- image->StartAnimation();
-}
-
FloatPoint3D CompositedLayerMapping::ComputeTransformOrigin(
const IntRect& border_box) const {
const ComputedStyle& style = GetLayoutObject().StyleRef();
@@ -2153,18 +2057,14 @@ void CompositedLayerMapping::PaintScrollableArea(
CullRect cull_rect(interest_rect);
cull_rect.Move(graphics_layer->OffsetFromLayoutObject());
PaintLayerScrollableArea* scrollable_area = owning_layer_.GetScrollableArea();
+ ScrollableAreaPainter painter(*scrollable_area);
if (graphics_layer == LayerForHorizontalScrollbar()) {
- if (const Scrollbar* scrollbar = scrollable_area->HorizontalScrollbar()) {
- if (cull_rect.Intersects(scrollbar->FrameRect()))
- scrollbar->Paint(context, IntPoint());
- }
+ if (Scrollbar* scrollbar = scrollable_area->HorizontalScrollbar())
+ painter.PaintScrollbar(context, *scrollbar, IntPoint(), cull_rect);
} else if (graphics_layer == LayerForVerticalScrollbar()) {
- if (const Scrollbar* scrollbar = scrollable_area->VerticalScrollbar()) {
- if (cull_rect.Intersects(scrollbar->FrameRect()))
- scrollbar->Paint(context, IntPoint());
- }
+ if (Scrollbar* scrollbar = scrollable_area->VerticalScrollbar())
+ painter.PaintScrollbar(context, *scrollbar, IntPoint(), cull_rect);
} else if (graphics_layer == LayerForScrollCorner()) {
- ScrollableAreaPainter painter(*scrollable_area);
painter.PaintScrollCorner(context, IntPoint(), cull_rect);
painter.PaintResizer(context, IntPoint(), cull_rect);
}
diff --git a/chromium/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.h b/chromium/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.h
index bb399d8b1d5..5a4ed36ff32 100644
--- a/chromium/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.h
+++ b/chromium/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.h
@@ -367,10 +367,6 @@ class CORE_EXPORT CompositedLayerMapping final : public GraphicsLayerClient {
// Returns true if this layer has content that needs to be displayed by
// painting into the backing store.
bool ContainsPaintedContent() const;
- // Returns true if the Layer just contains an image that we can composite
- // directly.
- bool IsDirectlyCompositedImage() const;
- void UpdateImageContents();
Color LayoutObjectBackgroundColor() const;
void UpdateBackgroundColor();
diff --git a/chromium/third_party/blink/renderer/core/paint/compositing/compositing_inputs_updater.cc b/chromium/third_party/blink/renderer/core/paint/compositing/compositing_inputs_updater.cc
index d745fb4a8fa..ed18dfe1b7f 100644
--- a/chromium/third_party/blink/renderer/core/paint/compositing/compositing_inputs_updater.cc
+++ b/chromium/third_party/blink/renderer/core/paint/compositing/compositing_inputs_updater.cc
@@ -50,9 +50,10 @@ void CompositingInputsUpdater::Update() {
PaintLayer* layer =
compositing_inputs_root_ ? compositing_inputs_root_ : root_layer_;
- if (DisplayLockUtilities::NearestLockedExclusiveAncestor(
+ // We don't need to do anything if the layer is under a locked display lock
+ // that prevents updates.
+ if (DisplayLockUtilities::LockedAncestorPreventingPrePaint(
layer->GetLayoutObject())) {
- compositing_inputs_root_ = nullptr;
return;
}
@@ -116,13 +117,13 @@ void CompositingInputsUpdater::UpdateSelfAndDescendantsRecursively(
// root layer, we are no longer viewport constrained.
if (previous_overflow_layer && previous_overflow_layer->IsRootLayer()) {
layout_object.View()->GetFrameView()->RemoveViewportConstrainedObject(
- layout_object);
+ layout_object, LocalFrameView::ViewportConstrainedType::kSticky);
}
}
if (info.last_overflow_clip_layer->IsRootLayer()) {
layout_object.View()->GetFrameView()->AddViewportConstrainedObject(
- layout_object);
+ layout_object, LocalFrameView::ViewportConstrainedType::kSticky);
}
layout_object.UpdateStickyPositionConstraints();
@@ -175,13 +176,14 @@ void CompositingInputsUpdater::UpdateSelfAndDescendantsRecursively(
DisplayLockLifecycleTarget::kChildren);
bool should_recurse = (layer->ChildNeedsCompositingInputsUpdate() ||
- update_type == kForceUpdate) &&
- !recursion_blocked_by_display_lock;
+ update_type == kForceUpdate);
layer->SetDescendantHasDirectOrScrollingCompositingReason(false);
bool descendant_has_direct_compositing_reason = false;
- for (PaintLayer* child = layer->FirstChild(); child;
- child = child->NextSibling()) {
+
+ auto* first_child =
+ recursion_blocked_by_display_lock ? nullptr : layer->FirstChild();
+ for (PaintLayer* child = first_child; child; child = child->NextSibling()) {
if (should_recurse)
UpdateSelfAndDescendantsRecursively(child, update_type, info);
descendant_has_direct_compositing_reason |=
@@ -466,7 +468,6 @@ void CompositingInputsUpdater::UpdateAncestorDependentCompositingInputs(
if (info.needs_reparent_scroll && layout_object.StyleRef().IsStacked())
properties.scroll_parent = info.scrolling_ancestor;
- properties.is_under_position_sticky = info.is_under_position_sticky;
properties.nearest_contained_layout_layer =
info.nearest_contained_layout_layer;
diff --git a/chromium/third_party/blink/renderer/core/paint/compositing/compositing_layer_assigner.cc b/chromium/third_party/blink/renderer/core/paint/compositing/compositing_layer_assigner.cc
index 81eb11a2ed2..eb8bc29eb7f 100644
--- a/chromium/third_party/blink/renderer/core/paint/compositing/compositing_layer_assigner.cc
+++ b/chromium/third_party/blink/renderer/core/paint/compositing/compositing_layer_assigner.cc
@@ -127,6 +127,9 @@ SquashingDisallowedReasons
CompositingLayerAssigner::GetReasonsPreventingSquashing(
const PaintLayer* layer,
const CompositingLayerAssigner::SquashingState& squashing_state) {
+ if (RuntimeEnabledFeatures::DisableLayerSquashingEnabled())
+ return SquashingDisallowedReason::kDisabled;
+
if (!squashing_state.have_assigned_backings_to_entire_squashing_layer_subtree)
return SquashingDisallowedReason::kWouldBreakPaintOrder;
diff --git a/chromium/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder.cc b/chromium/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder.cc
index 3570a6d184e..dece8c8a2b8 100644
--- a/chromium/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder.cc
+++ b/chromium/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder.cc
@@ -76,8 +76,8 @@ CompositingReasonFinder::PotentialCompositingReasonsFromStyle(
DCHECK((style.HasOpacity() || layout_object.HasMask() ||
layout_object.HasClipPath() ||
layout_object.HasFilterInducingProperty() ||
- layout_object.HasBackdropFilter() || style.HasBlendMode()) ==
- layout_object.CreatesGroup());
+ layout_object.HasNonInitialBackdropFilter() ||
+ style.HasBlendMode()) == layout_object.CreatesGroup());
if (style.HasMask() || style.ClipPath())
reasons |= CompositingReason::kMaskWithCompositedDescendants;
@@ -285,9 +285,13 @@ CompositingReasons CompositingReasonFinder::CompositingReasonsForWillChange(
reasons |= CompositingReason::kWillChangeTransform;
if (style.HasWillChangeOpacityHint())
reasons |= CompositingReason::kWillChangeOpacity;
+ if (style.HasWillChangeFilterHint())
+ reasons |= CompositingReason::kWillChangeFilter;
+ if (style.HasWillChangeBackdropFilterHint())
+ reasons |= CompositingReason::kWillChangeBackdropFilter;
- // kWillChangeOther is needed only when neither kWillChangeTransform nor
- // kWillChangeOpacity is set.
+ // kWillChangeOther is needed only when none of the explicit kWillChange*
+ // reasons are set.
if (reasons == CompositingReason::kNone &&
style.HasWillChangeCompositingHint())
reasons |= CompositingReason::kWillChangeOther;
diff --git a/chromium/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder_test.cc b/chromium/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder_test.cc
index ec556f3f98d..980a9ef8dc2 100644
--- a/chromium/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder_test.cc
+++ b/chromium/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder_test.cc
@@ -109,42 +109,6 @@ TEST_F(CompositingReasonFinderTest, OnlyAnchoredStickyPositionPromoted) {
->GetCompositingState());
}
-TEST_F(CompositingReasonFinderTest,
- OnlyAnchoredStickyPositionPromotedAssumeOverlap) {
- base::test::ScopedFeatureList feature_list;
- feature_list.InitWithFeatureState(
- blink::features::kAssumeOverlapAfterFixedOrStickyPosition, true);
- SetBodyInnerHTML(R"HTML(
- <style>
- .scroller {contain: paint; width: 400px; height: 400px; overflow: auto;
- will-change: transform;}
- .sticky { position: sticky; width: 10px; height: 10px;}</style>
- <div class='scroller'>
- <div id='sticky-top' class='sticky' style='top: 0px;'></div>
- <div id='sticky-no-anchor' class='sticky'></div>
- <div style='height: 2000px;'></div>
- </div>
- )HTML");
-
- EXPECT_EQ(kPaintsIntoOwnBacking,
- ToLayoutBoxModelObject(GetLayoutObjectByElementId("sticky-top"))
- ->Layer()
- ->GetCompositingState());
- // Any scroll dependent layer, such as sticky-top, assumes that it overlaps
- // anything which draws after it.
- EXPECT_EQ(
- kPaintsIntoOwnBacking,
- ToLayoutBoxModelObject(GetLayoutObjectByElementId("sticky-no-anchor"))
- ->Layer()
- ->GetCompositingState());
- EXPECT_EQ(
- CompositingReason::kAssumedOverlap,
- ToLayoutBoxModelObject(GetLayoutObjectByElementId("sticky-no-anchor"))
- ->Layer()
- ->GetCompositingReasons() &
- CompositingReason::kAssumedOverlap);
-}
-
TEST_F(CompositingReasonFinderTest, OnlyScrollingStickyPositionPromoted) {
SetBodyInnerHTML(R"HTML(
<style>.scroller {width: 400px; height: 400px; overflow: auto;
diff --git a/chromium/third_party/blink/renderer/core/paint/compositing/compositing_requirements_updater.cc b/chromium/third_party/blink/renderer/core/paint/compositing/compositing_requirements_updater.cc
index 0b9f70b8b36..1407cb0447d 100644
--- a/chromium/third_party/blink/renderer/core/paint/compositing/compositing_requirements_updater.cc
+++ b/chromium/third_party/blink/renderer/core/paint/compositing/compositing_requirements_updater.cc
@@ -27,7 +27,6 @@
#include "third_party/blink/renderer/core/paint/compositing/compositing_requirements_updater.h"
#include "base/macros.h"
-#include "third_party/blink/public/common/features.h"
#include "third_party/blink/renderer/core/layout/layout_embedded_content.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
#include "third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.h"
@@ -596,10 +595,7 @@ void CompositingRequirementsUpdater::UpdateRecursive(
CompositingReason::kClipsCompositingDescendants);
if ((!child_recursion_data.testing_overlap_ &&
!is_composited_clipping_layer) ||
- layer->GetLayoutObject().StyleRef().HasCurrentTransformAnimation() ||
- ((direct_reasons & CompositingReason::kScrollDependentPosition) &&
- base::FeatureList::IsEnabled(
- features::kAssumeOverlapAfterFixedOrStickyPosition)))
+ layer->GetLayoutObject().StyleRef().HasCurrentTransformAnimation())
current_recursion_data.testing_overlap_ = false;
if (child_recursion_data.compositing_ancestor_ == layer)
diff --git a/chromium/third_party/blink/renderer/core/paint/compositing/compositing_test.cc b/chromium/third_party/blink/renderer/core/paint/compositing/compositing_test.cc
index cefe3499d81..8a90f5ad5cd 100644
--- a/chromium/third_party/blink/renderer/core/paint/compositing/compositing_test.cc
+++ b/chromium/third_party/blink/renderer/core/paint/compositing/compositing_test.cc
@@ -19,6 +19,7 @@
#include "third_party/blink/renderer/core/html/html_element.h"
#include "third_party/blink/renderer/core/html/html_iframe_element.h"
#include "third_party/blink/renderer/core/layout/layout_box.h"
+#include "third_party/blink/renderer/core/layout/layout_view.h"
#include "third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.h"
#include "third_party/blink/renderer/core/paint/paint_layer.h"
#include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
@@ -221,6 +222,133 @@ TEST_P(CompositingTest, WillChangeTransformHint) {
EXPECT_TRUE(layer->has_will_change_transform_hint());
}
+TEST_P(CompositingTest, BackgroundColorInScrollingContentsLayer) {
+ InitializeWithHTML(*WebView()->MainFrameImpl()->GetFrame(), R"HTML(
+ <style>
+ html {
+ background-color: rgb(10, 20, 30);
+ }
+ #scroller {
+ will-change: transform;
+ overflow: scroll;
+ height: 100px;
+ width: 100px;
+ background-color: rgb(30, 40, 50);
+ }
+ .spacer {
+ height: 1000px;
+ }
+ </style>
+ <div id="scroller">
+ <div class="spacer"></div>
+ </div>
+ <div class="spacer"></div>
+ )HTML");
+ UpdateAllLifecyclePhases();
+
+ LayoutView* layout_view = GetLocalFrameView()->GetLayoutView();
+ Element* scroller = GetElementById("scroller");
+ LayoutBox* scroller_box = ToLayoutBox(scroller->GetLayoutObject());
+ ASSERT_TRUE(layout_view->GetBackgroundPaintLocation() ==
+ kBackgroundPaintInScrollingContents);
+ ASSERT_TRUE(scroller_box->GetBackgroundPaintLocation() ==
+ kBackgroundPaintInScrollingContents);
+
+ // In CAP mode, background_color is only set on the cc::Layer which draws the
+ // background; in pre-CAP mode, it is set on both the main layer and the
+ // scrolling contents layer.
+ bool cap_mode = RuntimeEnabledFeatures::CompositeAfterPaintEnabled();
+
+ // The root layer and root scrolling contents layer get background_color by
+ // blending the CSS background-color of the <html> element with
+ // LocalFrameView::BaseBackgroundColor(), which is white by default.
+ auto* layer = CcLayersByName(RootCcLayer(), "LayoutView #document")[0];
+ SkColor expected_color = SkColorSetRGB(10, 20, 30);
+ EXPECT_EQ(layer->background_color(),
+ cap_mode ? SK_ColorTRANSPARENT : expected_color);
+ auto* scrollable_area = GetLocalFrameView()->LayoutViewport();
+ layer = ScrollingContentsCcLayerByScrollElementId(
+ RootCcLayer(), scrollable_area->GetScrollElementId());
+ EXPECT_EQ(layer->background_color(), expected_color);
+
+ // Non-root layers set background_color based on the CSS background color of
+ // the layer-defining element.
+ expected_color = SkColorSetRGB(30, 40, 50);
+ layer = CcLayerByDOMElementId("scroller");
+ EXPECT_EQ(layer->background_color(),
+ cap_mode ? SK_ColorTRANSPARENT : expected_color);
+ scrollable_area = scroller_box->GetScrollableArea();
+ layer = ScrollingContentsCcLayerByScrollElementId(
+ RootCcLayer(), scrollable_area->GetScrollElementId());
+ EXPECT_EQ(layer->background_color(), expected_color);
+}
+
+TEST_P(CompositingTest, BackgroundColorInGraphicsLayer) {
+ InitializeWithHTML(*WebView()->MainFrameImpl()->GetFrame(), R"HTML(
+ <style>
+ html {
+ background-image: linear-gradient(rgb(10, 20, 30), rgb(60, 70, 80));
+ background-attachment: fixed;
+ }
+ #scroller {
+ will-change: transform;
+ overflow: scroll;
+ height: 100px;
+ width: 100px;
+ background-color: rgba(30, 40, 50, .6);
+ background-clip: content-box;
+ background-attachment: scroll;
+ padding: 1px;
+ }
+ .spacer {
+ height: 1000px;
+ }
+ </style>
+ <div id="scroller">
+ <div class="spacer"></div>
+ </div>
+ <div class="spacer"></div>
+ )HTML");
+ UpdateAllLifecyclePhases();
+
+ LayoutView* layout_view = GetLocalFrameView()->GetLayoutView();
+ Element* scroller = GetElementById("scroller");
+ LayoutBox* scroller_box = ToLayoutBox(scroller->GetLayoutObject());
+ ASSERT_TRUE(layout_view->GetBackgroundPaintLocation() ==
+ kBackgroundPaintInGraphicsLayer);
+ ASSERT_TRUE(scroller_box->GetBackgroundPaintLocation() ==
+ kBackgroundPaintInGraphicsLayer);
+
+ // In CAP mode, background_color is only set on the cc::Layer which draws the
+ // background; in pre-CAP mode, it is set on both the main layer and the
+ // scrolling contents layer.
+ bool cap_mode = RuntimeEnabledFeatures::CompositeAfterPaintEnabled();
+
+ // The root layer and root scrolling contents layer get background_color by
+ // blending the CSS background-color of the <html> element with
+ // LocalFrameView::BaseBackgroundColor(), which is white by default. In this
+ // case, because the background is a gradient, it will blend transparent with
+ // white, resulting in white.
+ auto* layer = CcLayersByName(RootCcLayer(), "LayoutView #document")[0];
+ EXPECT_EQ(layer->background_color(), SK_ColorWHITE);
+ auto* scrollable_area = GetLocalFrameView()->LayoutViewport();
+ layer = ScrollingContentsCcLayerByScrollElementId(
+ RootCcLayer(), scrollable_area->GetScrollElementId());
+ EXPECT_EQ(layer->background_color(),
+ cap_mode ? SK_ColorTRANSPARENT : SK_ColorWHITE);
+
+ // Non-root layers set background_color based on the CSS background color of
+ // the layer-defining element.
+ SkColor expected_color = SkColorSetARGB(roundf(255. * 0.6), 30, 40, 50);
+ layer = CcLayerByDOMElementId("scroller");
+ EXPECT_EQ(layer->background_color(), expected_color);
+ scrollable_area = scroller_box->GetScrollableArea();
+ layer = ScrollingContentsCcLayerByScrollElementId(
+ RootCcLayer(), scrollable_area->GetScrollElementId());
+ EXPECT_EQ(layer->background_color(),
+ cap_mode ? SK_ColorTRANSPARENT : expected_color);
+}
+
class CompositingSimTest : public PaintTestConfigurations, public SimTest {
public:
void InitializeWithHTML(const String& html) {
@@ -903,7 +1031,7 @@ TEST_P(CompositingSimTest, LayerClipPropertyChanged) {
Compositor().BeginFrame();
auto* inner_element_layer = CcLayerByDOMElementId("inner");
- EXPECT_FALSE(inner_element_layer->double_sided());
+ EXPECT_TRUE(inner_element_layer->should_check_backface_visibility());
// Initially, no layer should have |subtree_property_changed| set.
EXPECT_FALSE(inner_element_layer->subtree_property_changed());
@@ -915,7 +1043,7 @@ TEST_P(CompositingSimTest, LayerClipPropertyChanged) {
UpdateAllLifecyclePhases();
inner_element_layer = CcLayerByDOMElementId("inner");
- EXPECT_FALSE(inner_element_layer->double_sided());
+ EXPECT_TRUE(inner_element_layer->should_check_backface_visibility());
EXPECT_TRUE(inner_element_layer->subtree_property_changed());
// After a frame the |subtree_property_changed| value should be reset.
@@ -999,6 +1127,21 @@ TEST_P(CompositingSimTest, SafeOpaqueBackgroundColorGetsSet) {
(squashed_bg_color == SK_ColorCYAN));
}
+// Test that a pleasant checkerboard color is used in the presence of blending.
+TEST_P(CompositingSimTest, RootScrollingContentsSafeOpaqueBackgroundColor) {
+ InitializeWithHTML(R"HTML(
+ <!DOCTYPE html>
+ <div style="mix-blend-mode: multiply;"></div>
+ <div id="forcescroll" style="height: 10000px;"></div>
+ )HTML");
+ Compositor().BeginFrame();
+
+ auto* scrolling_contents = ScrollingContentsCcLayerByScrollElementId(
+ RootCcLayer(),
+ MainFrame().GetFrameView()->LayoutViewport()->GetScrollElementId());
+ EXPECT_EQ(scrolling_contents->SafeOpaqueBackgroundColor(), SK_ColorWHITE);
+}
+
TEST_P(CompositingSimTest, NonDrawableLayersIgnoredForRenderSurfaces) {
// TODO(crbug.com/765003): CAP may make different layerization decisions. When
// CAP gets closer to launch, this test should be updated to pass.
diff --git a/chromium/third_party/blink/renderer/core/paint/compositing/graphics_layer_updater.cc b/chromium/third_party/blink/renderer/core/paint/compositing/graphics_layer_updater.cc
index 3026c276c50..8ab1291f868 100644
--- a/chromium/third_party/blink/renderer/core/paint/compositing/graphics_layer_updater.cc
+++ b/chromium/third_party/blink/renderer/core/paint/compositing/graphics_layer_updater.cc
@@ -140,9 +140,13 @@ void GraphicsLayerUpdater::UpdateRecursive(
}
}
+ PaintLayer* first_child =
+ layer.GetLayoutObject().PrePaintBlockedByDisplayLock(
+ DisplayLockLifecycleTarget::kChildren)
+ ? nullptr
+ : layer.FirstChild();
UpdateContext child_context(context, layer);
- for (PaintLayer* child = layer.FirstChild(); child;
- child = child->NextSibling()) {
+ for (PaintLayer* child = first_child; child; child = child->NextSibling()) {
UpdateRecursive(*child, update_type, child_context,
layers_needing_paint_invalidation);
}
diff --git a/chromium/third_party/blink/renderer/core/paint/decoration_info.h b/chromium/third_party/blink/renderer/core/paint/decoration_info.h
index 52d71f9f15d..7da9c66328c 100644
--- a/chromium/third_party/blink/renderer/core/paint/decoration_info.h
+++ b/chromium/third_party/blink/renderer/core/paint/decoration_info.h
@@ -15,7 +15,12 @@ namespace blink {
class ComputedStyle;
class SimpleFontData;
-enum class ResolvedUnderlinePosition { kRoman, kUnder, kOver };
+enum class ResolvedUnderlinePosition {
+ kNearAlphabeticBaselineAuto,
+ kNearAlphabeticBaselineFromFont,
+ kUnder,
+ kOver
+};
// Holds text decoration painting values to be computed once and subsequently
// use multiple times to handle decoration paint order correctly. See also
diff --git a/chromium/third_party/blink/renderer/core/paint/filter_effect_builder.cc b/chromium/third_party/blink/renderer/core/paint/filter_effect_builder.cc
index 900b20688cf..9c77e9224ab 100644
--- a/chromium/third_party/blink/renderer/core/paint/filter_effect_builder.cc
+++ b/chromium/third_party/blink/renderer/core/paint/filter_effect_builder.cc
@@ -415,22 +415,17 @@ CompositorFilterOperations FilterEffectBuilder::BuildFilterOperations(
Filter* FilterEffectBuilder::BuildReferenceFilter(
const ReferenceFilterOperation& reference_operation,
- FilterEffect* previous_effect) const {
- SVGResource* resource = reference_operation.Resource();
- if (auto* filter =
- DynamicTo<SVGFilterElement>(resource ? resource->Target() : nullptr))
- return BuildReferenceFilter(*filter, previous_effect);
- return nullptr;
-}
-
-Filter* FilterEffectBuilder::BuildReferenceFilter(
- SVGFilterElement& filter_element,
FilterEffect* previous_effect,
SVGFilterGraphNodeMap* node_map) const {
+ SVGResource* resource = reference_operation.Resource();
+ auto* filter_element =
+ DynamicTo<SVGFilterElement>(resource ? resource->Target() : nullptr);
+ if (!filter_element)
+ return nullptr;
FloatRect filter_region =
SVGLengthContext::ResolveRectangle<SVGFilterElement>(
- &filter_element,
- filter_element.filterUnits()->CurrentValue()->EnumValue(),
+ filter_element,
+ filter_element->filterUnits()->CurrentValue()->EnumValue(),
reference_box_);
// TODO(fs): We rely on the presence of a node map here to opt-in to the
// check for an empty filter region. The reason for this is that we lack a
@@ -439,7 +434,7 @@ Filter* FilterEffectBuilder::BuildReferenceFilter(
return nullptr;
bool primitive_bounding_box_mode =
- filter_element.primitiveUnits()->CurrentValue()->EnumValue() ==
+ filter_element->primitiveUnits()->CurrentValue()->EnumValue() ==
SVGUnitTypes::kSvgUnitTypeObjectboundingbox;
Filter::UnitScaling unit_scaling =
primitive_bounding_box_mode ? Filter::kBoundingBox : Filter::kUserSpace;
@@ -449,7 +444,7 @@ Filter* FilterEffectBuilder::BuildReferenceFilter(
previous_effect = result->GetSourceGraphic();
SVGFilterBuilder builder(previous_effect, node_map, fill_flags_,
stroke_flags_);
- builder.BuildGraph(result, filter_element, reference_box_);
+ builder.BuildGraph(result, *filter_element, reference_box_);
result->SetLastEffect(builder.LastEffect());
return result;
}
diff --git a/chromium/third_party/blink/renderer/core/paint/filter_effect_builder.h b/chromium/third_party/blink/renderer/core/paint/filter_effect_builder.h
index 32497c0c144..111b5d2a140 100644
--- a/chromium/third_party/blink/renderer/core/paint/filter_effect_builder.h
+++ b/chromium/third_party/blink/renderer/core/paint/filter_effect_builder.h
@@ -41,7 +41,6 @@ class FilterEffect;
class FilterOperations;
class FloatRect;
class ReferenceFilterOperation;
-class SVGFilterElement;
class SVGFilterGraphNodeMap;
class CORE_EXPORT FilterEffectBuilder final {
@@ -55,7 +54,7 @@ class CORE_EXPORT FilterEffectBuilder final {
SkBlurImageFilter::TileMode blur_tile_mode =
SkBlurImageFilter::kClampToBlack_TileMode);
- Filter* BuildReferenceFilter(SVGFilterElement&,
+ Filter* BuildReferenceFilter(const ReferenceFilterOperation&,
FilterEffect* previous_effect,
SVGFilterGraphNodeMap* = nullptr) const;
@@ -65,9 +64,6 @@ class CORE_EXPORT FilterEffectBuilder final {
const FilterOperations&) const;
private:
- Filter* BuildReferenceFilter(const ReferenceFilterOperation&,
- FilterEffect* previous_effect) const;
-
FloatRect reference_box_;
float zoom_;
const PaintFlags* fill_flags_;
diff --git a/chromium/third_party/blink/renderer/core/paint/first_meaningful_paint_detector.cc b/chromium/third_party/blink/renderer/core/paint/first_meaningful_paint_detector.cc
index 97c06979db0..65743da01fe 100644
--- a/chromium/third_party/blink/renderer/core/paint/first_meaningful_paint_detector.cc
+++ b/chromium/third_party/blink/renderer/core/paint/first_meaningful_paint_detector.cc
@@ -144,11 +144,15 @@ void FirstMeaningfulPaintDetector::OnNetwork2Quiet() {
}
}
+bool FirstMeaningfulPaintDetector::SeenFirstMeaningfulPaint() const {
+ return !first_meaningful_paint_.is_null();
+}
+
void FirstMeaningfulPaintDetector::RegisterNotifySwapTime(PaintEvent event) {
++outstanding_swap_promise_count_;
paint_timing_->RegisterNotifySwapTime(
- event, CrossThreadBindOnce(&FirstMeaningfulPaintDetector::ReportSwapTime,
- WrapCrossThreadWeakPersistent(this), event));
+ CrossThreadBindOnce(&FirstMeaningfulPaintDetector::ReportSwapTime,
+ WrapCrossThreadWeakPersistent(this), event));
}
void FirstMeaningfulPaintDetector::ReportSwapTime(PaintEvent event,
diff --git a/chromium/third_party/blink/renderer/core/paint/first_meaningful_paint_detector.h b/chromium/third_party/blink/renderer/core/paint/first_meaningful_paint_detector.h
index a093acfcf0b..f4314fb7f41 100644
--- a/chromium/third_party/blink/renderer/core/paint/first_meaningful_paint_detector.h
+++ b/chromium/third_party/blink/renderer/core/paint/first_meaningful_paint_detector.h
@@ -42,6 +42,7 @@ class CORE_EXPORT FirstMeaningfulPaintDetector
void ReportSwapTime(PaintEvent, WebSwapResult, base::TimeTicks);
void NotifyFirstContentfulPaint(base::TimeTicks swap_stamp);
void OnNetwork2Quiet();
+ bool SeenFirstMeaningfulPaint() const;
// The caller owns the |clock| which must outlive the paint detector.
static void SetTickClockForTesting(const base::TickClock* clock);
diff --git a/chromium/third_party/blink/renderer/core/paint/html_canvas_painter.cc b/chromium/third_party/blink/renderer/core/paint/html_canvas_painter.cc
index 1658fc2f598..63a0cd08826 100644
--- a/chromium/third_party/blink/renderer/core/paint/html_canvas_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/html_canvas_painter.cc
@@ -37,8 +37,7 @@ void HTMLCanvasPainter::PaintReplaced(const PaintInfo& paint_info,
paint_rect.Move(paint_offset);
auto* canvas = To<HTMLCanvasElement>(layout_html_canvas_.GetNode());
- if (canvas->IsOffscreenCanvasRegistered())
- canvas->UpdateOffscreenCanvasFilterQuality(canvas->FilterQuality());
+ canvas->UpdateFilterQuality();
if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
if (auto* layer = canvas->ContentsCcLayer()) {
diff --git a/chromium/third_party/blink/renderer/core/paint/image_element_timing.cc b/chromium/third_party/blink/renderer/core/paint/image_element_timing.cc
index 4a824465ff5..771c75aa95b 100644
--- a/chromium/third_party/blink/renderer/core/paint/image_element_timing.cc
+++ b/chromium/third_party/blink/renderer/core/paint/image_element_timing.cc
@@ -167,7 +167,7 @@ void ImageElementTiming::NotifyImagePaintedInternal(
timing_allow_check = Performance::PassesTimingAllowCheck(
cached_image.GetResponse(), cached_image.GetResponse(),
*layout_object.GetDocument().GetSecurityOrigin(),
- layout_object.GetDocument().ToExecutionContext(),
+ layout_object.GetDocument().GetExecutionContext(),
&response_tainting_not_basic, &tainted_origin_flag);
}
if (!timing_allow_check) {
diff --git a/chromium/third_party/blink/renderer/core/paint/image_paint_timing_detector.cc b/chromium/third_party/blink/renderer/core/paint/image_paint_timing_detector.cc
index eea55437e84..c58112fd2e9 100644
--- a/chromium/third_party/blink/renderer/core/paint/image_paint_timing_detector.cc
+++ b/chromium/third_party/blink/renderer/core/paint/image_paint_timing_detector.cc
@@ -142,11 +142,11 @@ void ImagePaintTimingDetector::OnPaintFinished() {
.UpdateLargestContentfulPaintCandidate();
}
- if (!records_manager_.HasUnregisteredRecordsInQueued(
+ if (!records_manager_.HasUnregisteredRecordsInQueue(
last_registered_frame_index_))
return;
- last_registered_frame_index_ = records_manager_.LastQueuedFrameIndex();
+ last_registered_frame_index_ = frame_index_ - 1;
RegisterNotifySwapTime();
}
@@ -181,9 +181,8 @@ void ImagePaintTimingDetector::RegisterNotifySwapTime() {
num_pending_swap_callbacks_++;
}
-void ImagePaintTimingDetector::ReportSwapTime(
- unsigned last_queued_frame_index,
- base::TimeTicks timestamp) {
+void ImagePaintTimingDetector::ReportSwapTime(unsigned last_queued_frame_index,
+ base::TimeTicks timestamp) {
if (!is_recording_)
return;
// The callback is safe from race-condition only when running on main-thread.
@@ -342,7 +341,12 @@ ImageRecord* ImageRecordsManager::FindLargestPaintCandidate() const {
return size_ordered_set_.begin()->get();
}
+void ImageRecordsManager::Trace(Visitor* visitor) {
+ visitor->Trace(frame_view_);
+}
+
void ImagePaintTimingDetector::Trace(Visitor* visitor) {
+ visitor->Trace(records_manager_);
visitor->Trace(frame_view_);
visitor->Trace(callback_manager_);
}
diff --git a/chromium/third_party/blink/renderer/core/paint/image_paint_timing_detector.h b/chromium/third_party/blink/renderer/core/paint/image_paint_timing_detector.h
index 29c490a6481..2e9b233ff9b 100644
--- a/chromium/third_party/blink/renderer/core/paint/image_paint_timing_detector.h
+++ b/chromium/third_party/blink/renderer/core/paint/image_paint_timing_detector.h
@@ -63,6 +63,8 @@ typedef std::pair<const LayoutObject*, const ImageResourceContent*> RecordId;
// Node, LayoutObject, etc.
class CORE_EXPORT ImageRecordsManager {
friend class ImagePaintTimingDetectorTest;
+ DISALLOW_NEW();
+
using NodesQueueComparator = bool (*)(const base::WeakPtr<ImageRecord>&,
const base::WeakPtr<ImageRecord>&);
using ImageRecordSet =
@@ -122,7 +124,7 @@ class CORE_EXPORT ImageRecordsManager {
// Compare the last frame index in queue with the last frame index that has
// registered for assigning paint time.
- inline bool HasUnregisteredRecordsInQueued(
+ inline bool HasUnregisteredRecordsInQueue(
unsigned last_registered_frame_index) {
while (!images_queued_for_paint_time_.IsEmpty() &&
!images_queued_for_paint_time_.back()) {
@@ -130,7 +132,6 @@ class CORE_EXPORT ImageRecordsManager {
}
if (images_queued_for_paint_time_.IsEmpty())
return false;
- DCHECK(last_registered_frame_index <= LastQueuedFrameIndex());
return last_registered_frame_index < LastQueuedFrameIndex();
}
void AssignPaintTimeToRegisteredQueuedRecords(
@@ -141,6 +142,8 @@ class CORE_EXPORT ImageRecordsManager {
return images_queued_for_paint_time_.back()->frame_index;
}
+ void Trace(Visitor* visitor);
+
private:
// Find the image record of an visible image.
inline base::WeakPtr<ImageRecord> FindVisibleRecord(
@@ -172,9 +175,8 @@ class CORE_EXPORT ImageRecordsManager {
// Map containing timestamps of when LayoutObject::ImageNotifyFinished is
// first called.
HashMap<RecordId, base::TimeTicks> image_finished_times_;
- // ImageRecordsManager is always owned by ImagePaintTimingDetector, which
- // contains the LocalFrameView as a Member.
- UntracedMember<LocalFrameView> frame_view_;
+
+ Member<LocalFrameView> frame_view_;
DISALLOW_COPY_AND_ASSIGN(ImageRecordsManager);
};
diff --git a/chromium/third_party/blink/renderer/core/paint/image_paint_timing_detector_test.cc b/chromium/third_party/blink/renderer/core/paint/image_paint_timing_detector_test.cc
index 66125f8a9c2..4ed10990516 100644
--- a/chromium/third_party/blink/renderer/core/paint/image_paint_timing_detector_test.cc
+++ b/chromium/third_party/blink/renderer/core/paint/image_paint_timing_detector_test.cc
@@ -256,7 +256,7 @@ class ImagePaintTimingDetectorTest : public testing::Test,
}
void SimulateKeyUp() {
- GetPaintTimingDetector().NotifyInputEvent(WebInputEvent::kKeyUp);
+ GetPaintTimingDetector().NotifyInputEvent(WebInputEvent::Type::kKeyUp);
}
scoped_refptr<base::TestMockTimeTaskRunner> test_task_runner_;
diff --git a/chromium/third_party/blink/renderer/core/paint/image_painter.cc b/chromium/third_party/blink/renderer/core/paint/image_painter.cc
index 86470ade240..6436abe2bb9 100644
--- a/chromium/third_party/blink/renderer/core/paint/image_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/image_painter.cc
@@ -127,7 +127,7 @@ void ImagePainter::PaintAreaElementFocusRing(const PaintInfo& paint_info) {
paint_info.context.Clip(PixelSnappedIntRect(focus_rect));
paint_info.context.DrawFocusRing(
path, area_element_style->GetOutlineStrokeWidthForFocusRing(),
- area_element_style->OutlineOffset(),
+ area_element_style->OutlineOffsetInt(),
layout_image_.ResolveColor(*area_element_style,
GetCSSPropertyOutlineColor()));
paint_info.context.Restore();
diff --git a/chromium/third_party/blink/renderer/core/paint/line_box_list_painter.cc b/chromium/third_party/blink/renderer/core/paint/line_box_list_painter.cc
index 1bbdc7dcc45..7717975490b 100644
--- a/chromium/third_party/blink/renderer/core/paint/line_box_list_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/line_box_list_painter.cc
@@ -14,6 +14,7 @@
#include "third_party/blink/renderer/core/paint/object_painter.h"
#include "third_party/blink/renderer/core/paint/paint_info.h"
#include "third_party/blink/renderer/core/paint/paint_timing_detector.h"
+#include "third_party/blink/renderer/core/paint/url_metadata_utils.h"
#include "third_party/blink/renderer/platform/graphics/color.h"
#include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h"
@@ -74,20 +75,6 @@ void BuildBackplate(const InlineFlowBox* box,
}
}
-void AddURLRectsForInlineChildrenRecursively(
- const LayoutObject& layout_object,
- const PaintInfo& paint_info,
- const PhysicalOffset& paint_offset) {
- for (LayoutObject* child = layout_object.SlowFirstChild(); child;
- child = child->NextSibling()) {
- if (!child->IsLayoutInline() ||
- ToLayoutBoxModelObject(child)->HasSelfPaintingLayer())
- continue;
- ObjectPainter(*child).AddURLRectIfNeeded(paint_info, paint_offset);
- AddURLRectsForInlineChildrenRecursively(*child, paint_info, paint_offset);
- }
-}
-
} // anonymous namespace
bool LineBoxListPainter::ShouldPaint(const LayoutBoxModelObject& layout_object,
diff --git a/chromium/third_party/blink/renderer/core/paint/link_highlight_impl_test.cc b/chromium/third_party/blink/renderer/core/paint/link_highlight_impl_test.cc
index c7cb2458cb9..c9da60b4329 100644
--- a/chromium/third_party/blink/renderer/core/paint/link_highlight_impl_test.cc
+++ b/chromium/third_party/blink/renderer/core/paint/link_highlight_impl_test.cc
@@ -133,7 +133,7 @@ TEST_P(LinkHighlightImplTest, verifyWebViewImplIntegration) {
web_view_impl->MainFrameWidget()->Resize(WebSize(page_width, page_height));
UpdateAllLifecyclePhases();
- WebGestureEvent touch_event(WebInputEvent::kGestureShowPress,
+ WebGestureEvent touch_event(WebInputEvent::Type::kGestureShowPress,
WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests(),
WebGestureDevice::kTouchscreen);
@@ -183,7 +183,7 @@ TEST_P(LinkHighlightImplTest, resetDuringNodeRemoval) {
web_view_impl->MainFrameWidget()->Resize(WebSize(page_width, page_height));
UpdateAllLifecyclePhases();
- WebGestureEvent touch_event(WebInputEvent::kGestureShowPress,
+ WebGestureEvent touch_event(WebInputEvent::Type::kGestureShowPress,
WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests(),
WebGestureDevice::kTouchscreen);
@@ -215,7 +215,7 @@ TEST_P(LinkHighlightImplTest, resetLayerTreeView) {
web_view_impl->MainFrameWidget()->Resize(WebSize(page_width, page_height));
UpdateAllLifecyclePhases();
- WebGestureEvent touch_event(WebInputEvent::kGestureShowPress,
+ WebGestureEvent touch_event(WebInputEvent::Type::kGestureShowPress,
WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests(),
WebGestureDevice::kTouchscreen);
@@ -240,7 +240,7 @@ TEST_P(LinkHighlightImplTest, HighlightLayerEffectNode) {
UpdateAllLifecyclePhases();
size_t layer_count_before_highlight = LayerCount();
- WebGestureEvent touch_event(WebInputEvent::kGestureShowPress,
+ WebGestureEvent touch_event(WebInputEvent::Type::kGestureShowPress,
WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests(),
WebGestureDevice::kTouchscreen);
@@ -303,7 +303,7 @@ TEST_P(LinkHighlightImplTest, MultiColumn) {
UpdateAllLifecyclePhases();
size_t layer_count_before_highlight = LayerCount();
- WebGestureEvent touch_event(WebInputEvent::kGestureShowPress,
+ WebGestureEvent touch_event(WebInputEvent::Type::kGestureShowPress,
WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests(),
WebGestureDevice::kTouchscreen);
@@ -387,7 +387,7 @@ TEST_P(LinkHighlightImplTest, DisplayContents) {
web_view_impl->MainFrameWidget()->Resize(WebSize(page_width, page_height));
UpdateAllLifecyclePhases();
- WebGestureEvent touch_event(WebInputEvent::kGestureShowPress,
+ WebGestureEvent touch_event(WebInputEvent::Type::kGestureShowPress,
WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests(),
WebGestureDevice::kTouchscreen);
diff --git a/chromium/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc b/chromium/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc
index e8ff0f43f2f..61f9f6343f7 100644
--- a/chromium/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc
@@ -20,6 +20,7 @@
#include "third_party/blink/renderer/core/layout/ng/inline/ng_physical_line_box_fragment.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_physical_text_fragment.h"
#include "third_party/blink/renderer/core/layout/ng/layout_ng_mixin.h"
+#include "third_party/blink/renderer/core/layout/ng/ng_block_break_token.h"
#include "third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h"
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/core/paint/background_image_geometry.h"
@@ -41,11 +42,13 @@
#include "third_party/blink/renderer/core/paint/scoped_paint_state.h"
#include "third_party/blink/renderer/core/paint/scrollable_area_painter.h"
#include "third_party/blink/renderer/core/paint/theme_painter.h"
+#include "third_party/blink/renderer/core/paint/url_metadata_utils.h"
#include "third_party/blink/renderer/core/scroll/scroll_types.h"
#include "third_party/blink/renderer/platform/geometry/layout_rect_outsets.h"
#include "third_party/blink/renderer/platform/graphics/graphics_context_state_saver.h"
#include "third_party/blink/renderer/platform/graphics/paint/display_item_cache_skipper.h"
#include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h"
+#include "third_party/blink/renderer/platform/graphics/paint/scoped_display_item_fragment.h"
namespace blink {
@@ -58,6 +61,10 @@ LayoutRectOutsets BoxStrutToLayoutRectOutsets(
LayoutUnit(box_strut.bottom), LayoutUnit(box_strut.left));
}
+inline bool HasSelection(const LayoutObject* layout_object) {
+ return layout_object->GetSelectionState() != SelectionState::kNone;
+}
+
inline bool IsVisibleToPaint(const NGPhysicalFragment& fragment,
const ComputedStyle& style) {
return !fragment.IsHiddenForPaint() &&
@@ -92,26 +99,17 @@ bool FragmentVisibleToHitTestRequest(const NGPhysicalFragment& fragment,
// Hit tests inline ancestor elements of |fragment| who do not have their own
// box fragments.
// @param physical_offset Physical offset of |fragment| in the paint layer.
-bool HitTestCulledInlineAncestors(HitTestResult& result,
- const NGPaintFragment& fragment,
- const NGPaintFragment* previous_sibling,
- const HitTestLocation& hit_test_location,
- const PhysicalOffset& physical_offset) {
- DCHECK(fragment.Parent());
- DCHECK(fragment.PhysicalFragment().IsInline());
- const NGPaintFragment& parent = *fragment.Parent();
- // To be passed as |accumulated_offset| to LayoutInline::HitTestCulledInline,
- // where it equals the physical offset of the containing block in paint layer.
- const PhysicalOffset fallback_accumulated_offset =
- physical_offset - fragment.OffsetInContainerBlock();
- const LayoutObject* limit_layout_object =
- parent.PhysicalFragment().IsLineBox() ? parent.Parent()->GetLayoutObject()
- : parent.GetLayoutObject();
-
- const LayoutObject* current_layout_object = fragment.GetLayoutObject();
- for (LayoutObject* culled_parent = current_layout_object->Parent();
- culled_parent && culled_parent != limit_layout_object;
- culled_parent = culled_parent->Parent()) {
+bool HitTestCulledInlineAncestors(
+ HitTestResult& result,
+ const NGInlineCursor& parent_cursor,
+ const LayoutObject* current,
+ const LayoutObject* limit,
+ const NGInlineCursorPosition& previous_sibling,
+ const HitTestLocation& hit_test_location,
+ const PhysicalOffset fallback_accumulated_offset) {
+ DCHECK(current != limit && current->IsDescendantOf(limit));
+ for (LayoutObject* parent = current->Parent(); parent && parent != limit;
+ current = parent, parent = parent->Parent()) {
// |culled_parent| is a culled inline element to be hit tested, since it's
// "between" |fragment| and |fragment->Parent()| but doesn't have its own
// box fragment.
@@ -124,24 +122,65 @@ bool HitTestCulledInlineAncestors(HitTestResult& result,
// ancestor of |previous_sibling|; otherwise, |previous_sibling| has to be
// hit tested first.
// TODO(crbug.com/849331): It's wrong for bidi inline fragmentation. Fix it.
- const bool has_sibling = current_layout_object->PreviousSibling() ||
- current_layout_object->NextSibling();
+ const bool has_sibling =
+ current->PreviousSibling() || current->NextSibling();
if (has_sibling && previous_sibling &&
- previous_sibling->GetLayoutObject()->IsDescendantOf(culled_parent))
+ previous_sibling.GetLayoutObject()->IsDescendantOf(parent))
break;
- if (culled_parent->IsLayoutInline() &&
- ToLayoutInline(culled_parent)
- ->HitTestCulledInline(result, hit_test_location,
- fallback_accumulated_offset, &parent))
- return true;
-
- current_layout_object = culled_parent;
+ if (auto* parent_layout_inline = ToLayoutInlineOrNull(parent)) {
+ if (parent_layout_inline->HitTestCulledInline(result, hit_test_location,
+ fallback_accumulated_offset,
+ &parent_cursor))
+ return true;
+ }
}
return false;
}
+bool HitTestCulledInlineAncestors(
+ HitTestResult& result,
+ const NGInlineCursor& parent_cursor,
+ const NGPaintFragment& fragment,
+ const NGInlineCursorPosition& previous_sibling,
+ const HitTestLocation& hit_test_location,
+ const PhysicalOffset& physical_offset) {
+ DCHECK(fragment.Parent());
+ DCHECK(fragment.PhysicalFragment().IsInline());
+ const NGPaintFragment& parent = *fragment.Parent();
+ // To be passed as |accumulated_offset| to LayoutInline::HitTestCulledInline,
+ // where it equals the physical offset of the containing block in paint layer.
+ const PhysicalOffset fallback_accumulated_offset =
+ physical_offset - fragment.OffsetInContainerBlock();
+ const LayoutObject* limit_layout_object =
+ parent.PhysicalFragment().IsLineBox() ? parent.Parent()->GetLayoutObject()
+ : parent.GetLayoutObject();
+ return HitTestCulledInlineAncestors(
+ result, parent_cursor, fragment.GetLayoutObject(), limit_layout_object,
+ previous_sibling, hit_test_location, fallback_accumulated_offset);
+}
+
+bool HitTestCulledInlineAncestors(
+ HitTestResult& result,
+ const NGPhysicalBoxFragment& container,
+ const NGInlineCursor& parent_cursor,
+ const NGFragmentItem& item,
+ const NGInlineCursorPosition& previous_sibling,
+ const HitTestLocation& hit_test_location,
+ const PhysicalOffset& physical_offset) {
+ // To be passed as |accumulated_offset| to LayoutInline::HitTestCulledInline,
+ // where it equals the physical offset of the containing block in paint layer.
+ const PhysicalOffset fallback_accumulated_offset =
+ physical_offset - item.OffsetInContainerBlock();
+ return HitTestCulledInlineAncestors(
+ result, parent_cursor, item.GetLayoutObject(),
+ // Limit the traversal up to the container fragment, or its container if
+ // the fragment is not a CSSBox.
+ container.GetSelfOrContainerLayoutObject(), previous_sibling,
+ hit_test_location, fallback_accumulated_offset);
+}
+
// Returns if this fragment may not be laid out by LayoutNG.
//
// This function is for an optimization to skip a few virtual
@@ -274,6 +313,15 @@ bool NodeAtPointInFragment(const NGPhysicalBoxFragment& fragment,
accumulated_offset, action);
}
+// Return an ID for this fragmentainer, which is unique within the fragmentation
+// context. We need to provide this ID when block-fragmenting, so that we can
+// cache the painting of each individual fragment.
+unsigned FragmentainerUniqueIdentifier(const NGPhysicalBoxFragment& fragment) {
+ if (const auto* break_token = To<NGBlockBreakToken>(fragment.BreakToken()))
+ return break_token->SequenceNumber() + 1;
+ return 0;
+}
+
} // anonymous namespace
const NGBorderEdges& NGBoxFragmentPainter::BorderEdges() const {
@@ -449,6 +497,7 @@ void NGBoxFragmentPainter::PaintObject(
physical_box_fragment.HasItems() || inline_box_cursor_) &&
!paint_info.DescendantPaintingBlocked()) {
if (UNLIKELY(paint_phase == PaintPhase::kForeground &&
+ box_fragment_.IsCSSBox() &&
box_fragment_.Style().HasColumnRule()))
PaintColumnRules(paint_info, paint_offset);
@@ -578,8 +627,7 @@ void NGBoxFragmentPainter::PaintBlockChildren(const PaintInfo& paint_info,
for (const NGLink& child : box_fragment_.Children()) {
const NGPhysicalFragment& child_fragment = *child;
DCHECK(child_fragment.IsBox());
- if (child_fragment.HasSelfPaintingLayer() || child_fragment.IsFloating() ||
- child_fragment.IsColumnBox())
+ if (child_fragment.HasSelfPaintingLayer() || child_fragment.IsFloating())
continue;
const auto& box_child_fragment = To<NGPhysicalBoxFragment>(child_fragment);
@@ -592,6 +640,20 @@ void NGBoxFragmentPainter::PaintBlockChildren(const PaintInfo& paint_info,
// Bypass Paint() and jump directly to PaintObject(), to skip the code
// that assumes that we have a LayoutObject (and FragmentData).
PhysicalOffset child_offset = paint_offset + child.offset;
+
+ if (box_child_fragment.IsColumnBox()) {
+ // This is a fragmentainer, and when node inside a fragmentation
+ // context paints multiple block fragments, we need to distinguish
+ // between them somehow, for paint caching to work. Therefore,
+ // establish a display item scope here.
+ unsigned identifier =
+ FragmentainerUniqueIdentifier(box_child_fragment);
+ ScopedDisplayItemFragment scope(paint_info.context, identifier);
+ NGBoxFragmentPainter(box_child_fragment)
+ .PaintObject(paint_info, child_offset);
+ continue;
+ }
+
NGBoxFragmentPainter(box_child_fragment)
.PaintObject(paint_info, child_offset);
continue;
@@ -601,7 +663,24 @@ void NGBoxFragmentPainter::PaintBlockChildren(const PaintInfo& paint_info,
.Paint(paint_info_for_descendants);
continue;
}
- child_fragment.GetLayoutObject()->Paint(paint_info_for_descendants);
+
+ // Fall back to flow-thread painting when reaching a column (the flow thread
+ // is treated as a self-painting PaintLayer when fragment traversal is
+ // disabled, so nothing to do here).
+ if (box_child_fragment.IsColumnBox())
+ continue;
+
+ auto* layout_object = child_fragment.GetLayoutObject();
+ DCHECK(layout_object);
+ if (child_fragment.IsPaintedAtomically() &&
+ child_fragment.IsLegacyLayoutRoot()) {
+ ObjectPainter(*layout_object)
+ .PaintAllPhasesAtomically(paint_info_for_descendants);
+ } else {
+ // TODO(ikilpatrick): Once FragmentItem ships we should call the
+ // NGBoxFragmentPainter directly for NG objects.
+ layout_object->Paint(paint_info_for_descendants);
+ }
}
}
@@ -651,7 +730,7 @@ void NGBoxFragmentPainter::PaintFloatingChildren(
for (const NGLink& child : container.Children()) {
const NGPhysicalFragment& child_fragment = *child;
- if (child_fragment.HasSelfPaintingLayer() || child_fragment.IsColumnBox())
+ if (child_fragment.HasSelfPaintingLayer())
continue;
if (child_fragment.CanTraverse()) {
@@ -710,7 +789,18 @@ void NGBoxFragmentPainter::PaintFloatingChildren(
continue;
}
- PaintFloatingChildren(*child_container, paint_info, float_paint_info);
+ if (child_container->IsColumnBox()) {
+ // This is a fragmentainer, and when node inside a fragmentation context
+ // paints multiple block fragments, we need to distinguish between them
+ // somehow, for paint caching to work. Therefore, establish a display item
+ // scope here.
+ unsigned identifier = FragmentainerUniqueIdentifier(
+ To<NGPhysicalBoxFragment>(*child_container));
+ ScopedDisplayItemFragment scope(paint_info.context, identifier);
+ PaintFloatingChildren(*child_container, paint_info, float_paint_info);
+ } else {
+ PaintFloatingChildren(*child_container, paint_info, float_paint_info);
+ }
}
}
@@ -831,16 +921,11 @@ void NGBoxFragmentPainter::PaintBoxDecorationBackground(
RecordScrollHitTestData(paint_info, *background_client);
}
-// TODO(kojii): This logic is kept in sync with BoxPainter. Not much efforts to
-// eliminate LayoutObject dependency were done yet.
void NGBoxFragmentPainter::PaintBoxDecorationBackgroundWithRect(
const PaintInfo& paint_info,
const PhysicalRect& paint_rect,
const DisplayItemClient& background_client) {
- const LayoutObject& layout_object = *box_fragment_.GetLayoutObject();
- const LayoutBox& layout_box = ToLayoutBox(layout_object);
-
- const ComputedStyle& style = box_fragment_.Style();
+ const LayoutBox& layout_box = ToLayoutBox(*box_fragment_.GetLayoutObject());
base::Optional<DisplayItemCacheSkipper> cache_skipper;
if (RuntimeEnabledFeatures::PaintUnderInvalidationCheckingEnabled() &&
@@ -858,6 +943,21 @@ void NGBoxFragmentPainter::PaintBoxDecorationBackgroundWithRect(
DrawingRecorder recorder(paint_info.context, background_client,
DisplayItem::kBoxDecorationBackground);
+
+ PaintBoxDecorationBackgroundWithRectImpl(paint_info, paint_rect,
+ box_decoration_data);
+}
+// TODO(kojii): This logic is kept in sync with BoxPainter. Not much efforts to
+// eliminate LayoutObject dependency were done yet.
+void NGBoxFragmentPainter::PaintBoxDecorationBackgroundWithRectImpl(
+ const PaintInfo& paint_info,
+ const PhysicalRect& paint_rect,
+ const BoxDecorationData& box_decoration_data) {
+ const LayoutObject& layout_object = *box_fragment_.GetLayoutObject();
+ const LayoutBox& layout_box = ToLayoutBox(layout_object);
+
+ const ComputedStyle& style = box_fragment_.Style();
+
GraphicsContextStateSaver state_saver(paint_info.context, false);
const NGBorderEdges& border_edges = BorderEdges();
@@ -958,6 +1058,7 @@ void NGBoxFragmentPainter::PaintColumnRules(
const PaintInfo& paint_info,
const PhysicalOffset& paint_offset) {
const ComputedStyle& style = box_fragment_.Style();
+ DCHECK(box_fragment_.IsCSSBox());
DCHECK(style.HasColumnRule());
// TODO(crbug.com/792437): Certain rule styles should be converted.
@@ -1200,9 +1301,11 @@ void NGBoxFragmentPainter::PaintLineBoxChildren(
DCHECK(!layout_object || layout_object->IsLayoutBlock() ||
(layout_object->IsLayoutInline() && layout_object->HasLayer()));
- // if (paint_info.phase == PaintPhase::kForeground && paint_info.IsPrinting())
- // AddPDFURLRectsForInlineChildrenRecursively(layout_object, paint_info,
- // paint_offset);
+ if (paint_info.phase == PaintPhase::kForeground &&
+ paint_info.ShouldAddUrlMetadata()) {
+ AddURLRectsForInlineChildrenRecursively(*layout_object, paint_info,
+ paint_offset);
+ }
// If we have no lines then we have no work to do.
if (!*children)
@@ -1354,7 +1457,8 @@ void NGBoxFragmentPainter::PaintInlineChildren(
if (!paint_info.IntersectsCullRect(child->InkOverflow(),
paint_offset + child->Offset()) &&
// Don't skip empty size text in order to paint selection for <br>.
- !(child_fragment.IsText() && child_fragment.Size().IsEmpty()))
+ !(child_fragment.IsText() && child_fragment.Size().IsEmpty() &&
+ HasSelection(child_fragment.GetLayoutObject())))
continue;
if (child_fragment.Type() == NGPhysicalFragment::kFragmentText) {
@@ -1423,26 +1527,17 @@ void NGBoxFragmentPainter::PaintTextItem(const NGInlineCursor& cursor,
paint_info.phase != PaintPhase::kMask)
return;
+ // Skip if this child does not intersect with CullRect.
+ if (!paint_info.IntersectsCullRect(
+ item.InkOverflow(), paint_offset + item.OffsetInContainerBlock()) &&
+ // Don't skip <br>, it doesn't have ink but need to paint selection.
+ !(item.IsLineBreak() && HasSelection(item.GetLayoutObject())))
+ return;
+
NGTextFragmentPainter<NGInlineCursor> text_painter(cursor, parent_offset);
text_painter.Paint(paint_info, paint_offset);
}
-NGBoxFragmentPainter::MoveTo NGBoxFragmentPainter::PaintLineBoxItem(
- const NGFragmentItem& item,
- const PaintInfo& paint_info,
- const PhysicalOffset& paint_offset) {
- DCHECK_EQ(item.Type(), NGFragmentItem::kLine);
- DCHECK(items_);
- // TODO(kojii): Check CullRect.
- const PhysicalOffset line_box__offset =
- paint_offset + item.OffsetInContainerBlock();
- const NGPhysicalLineBoxFragment* line_box_fragment = item.LineBoxFragment();
- DCHECK(line_box_fragment);
- PaintLineBox(*line_box_fragment, item, /* line_box_paint_fragment */ nullptr,
- &item, paint_info, line_box__offset);
- return kDontSkipChildren;
-}
-
// Paint non-culled box item.
void NGBoxFragmentPainter::PaintBoxItem(
const NGFragmentItem& item,
@@ -1457,7 +1552,10 @@ void NGBoxFragmentPainter::PaintBoxItem(
if (child_fragment.HasSelfPaintingLayer() || child_fragment.IsFloating())
return;
- // TODO(kojii): Check CullRect.
+ // Skip if this child does not intersect with CullRect.
+ if (!paint_info.IntersectsCullRect(
+ item.InkOverflow(), paint_offset + item.OffsetInContainerBlock()))
+ return;
if (child_fragment.IsAtomicInline() || child_fragment.IsListMarker()) {
if (FragmentRequiresLegacyFallback(child_fragment)) {
@@ -1486,6 +1584,11 @@ void NGBoxFragmentPainter::PaintBoxItem(const NGFragmentItem& item,
return;
}
+ // Skip if this child does not intersect with CullRect.
+ if (!paint_info.IntersectsCullRect(
+ item.InkOverflow(), paint_offset + item.OffsetInContainerBlock()))
+ return;
+
// This |item| is a culled inline box.
DCHECK(item.GetLayoutObject()->IsLayoutInline());
NGInlineCursor children = cursor.CursorForDescendants();
@@ -1713,9 +1816,25 @@ bool NGBoxFragmentPainter::NodeAtPoint(const HitTestContext& hit_test,
if (fragment.IsInlineBox())
bounds_rect = PhysicalRect(PixelSnappedIntRect(bounds_rect));
if (hit_test.location.Intersects(bounds_rect)) {
- if (hit_test.AddNodeToResult(fragment.NodeForHitTest(), bounds_rect,
- physical_offset))
- return true;
+ // We set offset in container block instead of offset in |fragment| like
+ // |NGBoxFragmentPainter::HitTestTextFragment()|.
+ // See http://crbug.com/1043471
+ if (box_item_ && box_item_->IsInlineBox()) {
+ if (hit_test.AddNodeToResult(
+ fragment.NodeForHitTest(), bounds_rect,
+ physical_offset - box_item_->OffsetInContainerBlock()))
+ return true;
+ } else if (paint_fragment_ &&
+ paint_fragment_->PhysicalFragment().IsInline()) {
+ if (hit_test.AddNodeToResult(
+ fragment.NodeForHitTest(), bounds_rect,
+ physical_offset - paint_fragment_->OffsetInContainerBlock()))
+ return true;
+ } else {
+ if (hit_test.AddNodeToResult(fragment.NodeForHitTest(), bounds_rect,
+ physical_offset))
+ return true;
+ }
}
}
@@ -1826,7 +1945,8 @@ bool NGBoxFragmentPainter::HitTestLineBoxFragment(
const NGPhysicalLineBoxFragment& fragment,
const NGInlineBackwardCursor& cursor,
const PhysicalOffset& physical_offset) {
- if (HitTestChildren(hit_test, cursor.CursorForDescendants(), physical_offset))
+ if (HitTestChildren(hit_test, PhysicalFragment(),
+ cursor.CursorForDescendants(), physical_offset))
return true;
if (hit_test.action != kHitTestForeground)
@@ -1861,8 +1981,8 @@ bool NGBoxFragmentPainter::HitTestLineBoxFragment(
DCHECK_NE(hit_test.action, kHitTestFloat);
HitTestContext hit_test_float = hit_test;
hit_test_float.action = kHitTestFloat;
- if (HitTestChildren(hit_test_float, cursor.CursorForDescendants(),
- physical_offset))
+ if (HitTestChildren(hit_test_float, PhysicalFragment(),
+ cursor.CursorForDescendants(), physical_offset))
return false;
}
@@ -1928,6 +2048,7 @@ bool NGBoxFragmentPainter::HitTestChildBoxFragment(
bool NGBoxFragmentPainter::HitTestChildBoxItem(
const HitTestContext& hit_test,
+ const NGPhysicalBoxFragment& container,
const NGFragmentItem& item,
const NGInlineBackwardCursor& cursor) {
DCHECK_EQ(&item, cursor.Current().Item());
@@ -1942,7 +2063,7 @@ bool NGBoxFragmentPainter::HitTestChildBoxItem(
DCHECK(item.GetLayoutObject()->IsLayoutInline());
DCHECK(!ToLayoutInline(item.GetLayoutObject())->ShouldCreateBoxFragment());
if (NGInlineCursor descendants = cursor.CursorForDescendants()) {
- if (HitTestItemsChildren(hit_test, descendants))
+ if (HitTestItemsChildren(hit_test, container, descendants))
return true;
}
@@ -1975,17 +2096,21 @@ bool NGBoxFragmentPainter::HitTestChildren(
const PhysicalOffset& accumulated_offset) {
if (paint_fragment_) {
NGInlineCursor cursor(*paint_fragment_);
- return HitTestChildren(hit_test, cursor, accumulated_offset);
+ return HitTestChildren(hit_test, PhysicalFragment(), cursor,
+ accumulated_offset);
}
if (UNLIKELY(inline_box_cursor_)) {
NGInlineCursor descendants = inline_box_cursor_->CursorForDescendants();
- if (descendants)
- return HitTestChildren(hit_test, descendants, accumulated_offset);
+ if (descendants) {
+ return HitTestChildren(hit_test, PhysicalFragment(), descendants,
+ accumulated_offset);
+ }
return false;
}
if (items_) {
NGInlineCursor cursor(*items_);
- return HitTestChildren(hit_test, cursor, accumulated_offset);
+ return HitTestChildren(hit_test, PhysicalFragment(), cursor,
+ accumulated_offset);
}
// Check descendants of this fragment because floats may be in the
// |NGFragmentItems| of the descendants.
@@ -2005,12 +2130,13 @@ bool NGBoxFragmentPainter::HitTestChildren(
bool NGBoxFragmentPainter::HitTestChildren(
const HitTestContext& hit_test,
+ const NGPhysicalBoxFragment& container,
const NGInlineCursor& children,
const PhysicalOffset& accumulated_offset) {
if (children.IsPaintFragmentCursor())
return HitTestPaintFragmentChildren(hit_test, children, accumulated_offset);
if (children.IsItemCursor())
- return HitTestItemsChildren(hit_test, children);
+ return HitTestItemsChildren(hit_test, container, children);
// Hits nothing if there were no children.
return false;
}
@@ -2030,20 +2156,26 @@ bool NGBoxFragmentPainter::HitTestBlockChildren(
const PhysicalOffset child_offset = accumulated_offset + child.offset;
- if (block_child.IsPaintedAtomically()) {
- if (HitTestAllPhasesInFragment(block_child, hit_test_location,
- child_offset, &result))
- return true;
+ bool hit_child =
+ block_child.IsPaintedAtomically()
+ ? HitTestAllPhasesInFragment(block_child, hit_test_location,
+ child_offset, &result)
+ : NodeAtPointInFragment(block_child, hit_test_location,
+ child_offset, action, &result);
- continue;
- }
-
- if (NodeAtPointInFragment(block_child, hit_test_location, child_offset,
- action, &result)) {
+ if (hit_child) {
if (const LayoutObject* child_object = block_child.GetLayoutObject()) {
child_object->UpdateHitTestResult(
result, hit_test_location.Point() - accumulated_offset);
}
+
+ // Our child may have been an anonymous-block, update the hit-test node
+ // to include our node if needed.
+ if (const LayoutObject* object = box_fragment_.GetLayoutObject()) {
+ object->UpdateHitTestResult(
+ result, hit_test_location.Point() - accumulated_offset);
+ }
+
return true;
}
}
@@ -2089,11 +2221,9 @@ bool NGBoxFragmentPainter::HitTestPaintFragmentChildren(
if (child_fragment.IsInline() && hit_test.action == kHitTestForeground) {
// Hit test culled inline boxes between |fragment| and its parent
// fragment.
- const NGPaintFragment* previous_sibling =
- cursor ? cursor.Current().PaintFragment() : nullptr;
- if (HitTestCulledInlineAncestors(*hit_test.result, *child_paint_fragment,
- previous_sibling, hit_test.location,
- child_offset))
+ if (HitTestCulledInlineAncestors(*hit_test.result, children,
+ *child_paint_fragment, cursor.Current(),
+ hit_test.location, child_offset))
return true;
}
}
@@ -2103,6 +2233,7 @@ bool NGBoxFragmentPainter::HitTestPaintFragmentChildren(
bool NGBoxFragmentPainter::HitTestItemsChildren(
const HitTestContext& hit_test,
+ const NGPhysicalBoxFragment& container,
const NGInlineCursor& children) {
DCHECK(children.IsItemCursor());
for (NGInlineBackwardCursor cursor(children); cursor;) {
@@ -2125,13 +2256,25 @@ bool NGBoxFragmentPainter::HitTestItemsChildren(
child_offset))
return true;
} else if (item->Type() == NGFragmentItem::kBox) {
- if (HitTestChildBoxItem(hit_test, *item, cursor))
+ if (HitTestChildBoxItem(hit_test, container, *item, cursor))
return true;
} else {
NOTREACHED();
}
cursor.MoveToPreviousSibling();
+
+ if (item->Type() != NGFragmentItem::kLine &&
+ hit_test.action == kHitTestForeground) {
+ // Hit test culled inline boxes between |fragment| and its parent
+ // fragment.
+ const PhysicalOffset child_offset =
+ hit_test.inline_root_offset + item->OffsetInContainerBlock();
+ if (HitTestCulledInlineAncestors(*hit_test.result, container, children,
+ *item, cursor.Current(),
+ hit_test.location, child_offset))
+ return true;
+ }
}
return false;
diff --git a/chromium/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.h b/chromium/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.h
index 5fe1f5fe9a1..d497ad8adc5 100644
--- a/chromium/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.h
+++ b/chromium/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.h
@@ -18,6 +18,7 @@
namespace blink {
+class BoxDecorationData;
class FillLayer;
class HitTestLocation;
class HitTestRequest;
@@ -71,6 +72,10 @@ class NGBoxFragmentPainter : public BoxPainterBase {
const PhysicalOffset& accumulated_offset,
HitTestFilter = kHitTestAll);
+ void PaintBoxDecorationBackgroundWithRectImpl(const PaintInfo&,
+ const PhysicalRect&,
+ const BoxDecorationData&);
+
protected:
LayoutRectOutsets ComputeBorders() const override;
LayoutRectOutsets ComputePadding() const override;
@@ -109,6 +114,7 @@ class NGBoxFragmentPainter : public BoxPainterBase {
void PaintBoxDecorationBackgroundWithRect(const PaintInfo&,
const PhysicalRect&,
const DisplayItemClient&);
+
void PaintColumnRules(const PaintInfo&, const PhysicalOffset& paint_offset);
void PaintInternal(const PaintInfo&);
@@ -148,9 +154,6 @@ class NGBoxFragmentPainter : public BoxPainterBase {
const PaintInfo&,
const PhysicalOffset& paint_offset,
const PhysicalOffset& parent_offset);
- MoveTo PaintLineBoxItem(const NGFragmentItem& item,
- const PaintInfo& paint_info,
- const PhysicalOffset& paint_offset);
void PaintBoxItem(const NGFragmentItem& item,
const NGPhysicalBoxFragment& child_fragment,
const NGInlineCursor& cursor,
@@ -223,6 +226,7 @@ class NGBoxFragmentPainter : public BoxPainterBase {
bool HitTestChildren(const HitTestContext& hit_test,
const PhysicalOffset& physical_offset);
bool HitTestChildren(const HitTestContext& hit_test,
+ const NGPhysicalBoxFragment& container,
const NGInlineCursor& children,
const PhysicalOffset& physical_offset);
bool HitTestBlockChildren(HitTestResult&,
@@ -233,6 +237,7 @@ class NGBoxFragmentPainter : public BoxPainterBase {
const NGInlineCursor& children,
const PhysicalOffset& physical_offset);
bool HitTestItemsChildren(const HitTestContext& hit_test,
+ const NGPhysicalBoxFragment& container,
const NGInlineCursor& children);
bool HitTestFloatingChildren(const HitTestContext& hit_test,
const NGPhysicalContainerFragment& container,
@@ -250,6 +255,7 @@ class NGBoxFragmentPainter : public BoxPainterBase {
const NGInlineBackwardCursor& cursor,
const PhysicalOffset& physical_offset);
bool HitTestChildBoxItem(const HitTestContext& hit_test,
+ const NGPhysicalBoxFragment& container,
const NGFragmentItem& item,
const NGInlineBackwardCursor& cursor);
diff --git a/chromium/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter_test.cc b/chromium/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter_test.cc
index ccaf7fcbf22..2efb7da48ef 100644
--- a/chromium/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter_test.cc
+++ b/chromium/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter_test.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.h"
+#include "components/paint_preview/common/paint_preview_tracker.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.h"
@@ -11,6 +12,7 @@
#include "third_party/blink/renderer/core/layout/ng/ng_block_node.h"
#include "third_party/blink/renderer/core/paint/ng/ng_paint_fragment.h"
#include "third_party/blink/renderer/core/paint/paint_controller_paint_test.h"
+#include "third_party/blink/renderer/platform/graphics/paint/paint_record_builder.h"
#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
using testing::ElementsAre;
@@ -67,10 +69,7 @@ TEST_P(NGBoxFragmentPainterTest, ScrollHitTestOrder) {
EXPECT_THAT(
RootPaintController().PaintChunks(),
ElementsAre(
- IsPaintChunk(0, 1,
- PaintChunk::Id(ViewScrollingBackgroundClient(),
- DisplayItem::kDocumentBackground),
- GetLayoutView().FirstFragment().ContentsProperties()),
+ IsPaintChunk(0, 0), IsPaintChunk(0, 1), // LayoutView chunks.
IsPaintChunk(
1, 1,
PaintChunk::Id(*scroller.Layer(), DisplayItem::kLayerChunk),
@@ -85,10 +84,7 @@ TEST_P(NGBoxFragmentPainterTest, ScrollHitTestOrder) {
EXPECT_THAT(
RootPaintController().PaintChunks(),
ElementsAre(
- IsPaintChunk(0, 1,
- PaintChunk::Id(ViewScrollingBackgroundClient(),
- DisplayItem::kDocumentBackground),
- GetLayoutView().FirstFragment().ContentsProperties()),
+ IsPaintChunk(0, 1), // LayutView.
IsPaintChunk(
1, 1,
PaintChunk::Id(root_fragment, DisplayItem::kScrollHitTest),
@@ -98,4 +94,42 @@ TEST_P(NGBoxFragmentPainterTest, ScrollHitTestOrder) {
}
}
+TEST_P(NGBoxFragmentPainterTest, AddUrlRects) {
+ SetBodyInnerHTML(R"HTML(
+ <!DOCTYPE html>
+ <div>
+ <p>
+ <a href="https://www.chromium.org">Chromium</a>
+ </p>
+ <p>
+ <a href="https://www.wikipedia.org">Wikipedia</a>
+ </p>
+ </div>
+ )HTML");
+ // Use Paint Preview to test this as printing falls back to the legacy layout
+ // engine.
+
+ // PaintPreviewTracker records URLs via the GraphicsContext under certain
+ // flagsets when painting. This is the simplest way to check if URLs were
+ // annotated.
+ GetDocument().SetIsPaintingPreview(true);
+ UpdateAllLifecyclePhasesForTest();
+
+ paint_preview::PaintPreviewTracker tracker(base::UnguessableToken::Create(),
+ base::nullopt, true);
+ PaintRecordBuilder builder(nullptr, nullptr, nullptr, &tracker);
+ builder.Context().SetIsPaintingPreview(true);
+
+ GetDocument().View()->PaintContentsOutsideOfLifecycle(
+ builder.Context(),
+ kGlobalPaintNormalPhase | kGlobalPaintAddUrlMetadata |
+ kGlobalPaintFlattenCompositingLayers,
+ CullRect::Infinite());
+
+ builder.EndRecording();
+ ASSERT_EQ(tracker.GetLinks().size(), 2U);
+ EXPECT_EQ(tracker.GetLinks()[0]->url, "https://www.chromium.org/");
+ EXPECT_EQ(tracker.GetLinks()[1]->url, "https://www.wikipedia.org/");
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/ng/ng_inline_box_fragment_painter.cc b/chromium/third_party/blink/renderer/core/paint/ng/ng_inline_box_fragment_painter.cc
index 15aa6b95573..3badb3849dd 100644
--- a/chromium/third_party/blink/renderer/core/paint/ng/ng_inline_box_fragment_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/ng/ng_inline_box_fragment_painter.cc
@@ -33,7 +33,15 @@ inline bool HasMultiplePaintFragments(const LayoutObject& layout_object) {
return HasMultipleItems(NGPaintFragment::InlineFragmentsFor(&layout_object));
}
-inline bool HasMultipleFragmentItems(const LayoutObject& layout_object) {
+inline bool MayHaveMultipleFragmentItems(const LayoutObject& layout_object) {
+ // TODO(crbug.com/1061423): NGInlineCursor is currently unable to deal with
+ // objects split into multiple fragmentainers (e.g. columns). Just return true
+ // if it's possible that this object participates in a fragmentation
+ // context. This will give false positives, but that should be harmless, given
+ // the way the return value is used by the caller.
+ if (layout_object.IsInsideFlowThread())
+ return true;
+
NGInlineCursor cursor;
cursor.MoveTo(layout_object);
DCHECK(cursor);
@@ -113,9 +121,9 @@ void NGInlineBoxFragmentPainterBase::PaintBackgroundBorderShadow(
DCHECK(inline_box_fragment_.GetLayoutObject());
const LayoutObject& layout_object = *inline_box_fragment_.GetLayoutObject();
- bool object_has_multiple_boxes =
+ bool object_may_have_multiple_boxes =
inline_box_paint_fragment_ ? HasMultiplePaintFragments(layout_object)
- : HasMultipleFragmentItems(layout_object);
+ : MayHaveMultipleFragmentItems(layout_object);
// TODO(eae): Switch to LayoutNG version of BackgroundImageGeometry.
BackgroundImageGeometry geometry(*static_cast<const LayoutBoxModelObject*>(
@@ -127,7 +135,7 @@ void NGInlineBoxFragmentPainterBase::PaintBackgroundBorderShadow(
inline_box_paint_fragment_);
PaintBoxDecorationBackground(
box_painter, paint_info, paint_offset, adjusted_frame_rect, geometry,
- object_has_multiple_boxes, border_edges.line_left,
+ object_may_have_multiple_boxes, border_edges.line_left,
border_edges.line_right);
return;
}
@@ -137,7 +145,7 @@ void NGInlineBoxFragmentPainterBase::PaintBackgroundBorderShadow(
To<NGPhysicalBoxFragment>(inline_box_fragment_));
PaintBoxDecorationBackground(box_painter, paint_info, paint_offset,
adjusted_frame_rect, geometry,
- object_has_multiple_boxes,
+ object_may_have_multiple_boxes,
border_edges.line_left, border_edges.line_right);
}
diff --git a/chromium/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.cc b/chromium/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.cc
index 9cd79dd07b2..ce2576b1aa0 100644
--- a/chromium/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.cc
+++ b/chromium/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.cc
@@ -491,15 +491,8 @@ void NGPaintFragment::AssociateWithLayoutObject(
DCHECK(layout_object->IsInline());
DCHECK(PhysicalFragment().IsInline());
-#if DCHECK_IS_ON()
- // Check we don't add the same fragment twice.
- for (const NGPaintFragment* fragment :
- FragmentRange(layout_object->FirstInlineFragment())) {
- DCHECK_NE(this, fragment);
- }
-#endif
-
auto add_result = last_fragment_map->insert(layout_object, this);
+ NGPaintFragment* last_fragment;
if (add_result.is_new_entry) {
NGPaintFragment* first_fragment = layout_object->FirstInlineFragment();
if (!first_fragment) {
@@ -507,16 +500,15 @@ void NGPaintFragment::AssociateWithLayoutObject(
return;
}
// This |layout_object| was fragmented across multiple blocks.
- DCHECK_EQ(layout_object, first_fragment->GetLayoutObject());
- NGPaintFragment* last_fragment = first_fragment->LastForSameLayoutObject();
- last_fragment->next_for_same_layout_object_ = this;
- return;
+ last_fragment = first_fragment->LastForSameLayoutObject();
+ } else {
+ last_fragment = add_result.stored_value->value;
+ DCHECK(last_fragment) << layout_object;
+ add_result.stored_value->value = this;
}
- NGPaintFragment* last_fragment = add_result.stored_value->value;
- DCHECK(last_fragment) << layout_object;
DCHECK_EQ(layout_object, last_fragment->GetLayoutObject());
+ DCHECK_NE(this, last_fragment);
last_fragment->next_for_same_layout_object_ = this;
- add_result.stored_value->value = this;
}
// TODO(kojii): Consider unifying this with
@@ -796,101 +788,6 @@ const NGPaintFragment* NGPaintFragment::Root() const {
return root;
}
-void NGPaintFragment::DirtyLinesFromChangedChild(LayoutObject* child) {
- if (!RuntimeEnabledFeatures::LayoutNGLineCacheEnabled())
- return;
-
- // This function should be called on every child that has
- // |IsInLayoutNGInlineFormattingContext()|, meaning it was once collected into
- // |NGInlineNode|.
- //
- // New LayoutObjects will be handled in the next |CollectInline()|.
- DCHECK(child && child->IsInLayoutNGInlineFormattingContext());
-
- if (child->IsInline() || child->IsFloatingOrOutOfFlowPositioned())
- MarkLineBoxesDirtyFor(*child);
-}
-
-void NGPaintFragment::MarkLineBoxesDirtyFor(const LayoutObject& layout_object) {
- DCHECK(RuntimeEnabledFeatures::LayoutNGLineCacheEnabled());
- DCHECK(layout_object.IsInline() ||
- layout_object.IsFloatingOrOutOfFlowPositioned())
- << layout_object;
-
- // Since |layout_object| isn't in fragment tree, check preceding siblings.
- // Note: Once we reuse lines below dirty lines, we should check next siblings.
- for (LayoutObject* previous = layout_object.PreviousSibling(); previous;
- previous = previous->PreviousSibling()) {
- // If the previoius object had never been laid out, it should have already
- // marked the line box dirty.
- if (!previous->EverHadLayout())
- return;
-
- if (previous->IsFloatingOrOutOfFlowPositioned())
- continue;
-
- // |previous| may not be in inline formatting context, e.g. <object>.
- if (TryMarkLastLineBoxDirtyFor(*previous))
- return;
- }
-
- // There is no siblings, try parent. If it's a non-atomic inline (e.g., span),
- // mark dirty for it, but if it's an atomic inline (e.g., inline block), do
- // not propagate across inline formatting context boundary.
- const LayoutObject& parent = *layout_object.Parent();
- if (parent.IsInline() && !parent.IsAtomicInlineLevel())
- return MarkLineBoxesDirtyFor(parent);
-
- // The |layout_object| is inserted into an empty block.
- // Mark the first line box dirty.
- if (const NGPaintFragment* paint_fragment = parent.PaintFragment()) {
- if (NGPaintFragment* first_line = paint_fragment->FirstLineBox()) {
- first_line->is_dirty_inline_ = true;
- return;
- }
- }
-}
-
-void NGPaintFragment::MarkContainingLineBoxDirty() {
- DCHECK(RuntimeEnabledFeatures::LayoutNGLineCacheEnabled());
- DCHECK(PhysicalFragment().IsInline() || PhysicalFragment().IsLineBox());
- for (NGPaintFragment* fragment :
- NGPaintFragmentTraversal::InclusiveAncestorsOf(*this)) {
- if (fragment->is_dirty_inline_)
- return;
- fragment->is_dirty_inline_ = true;
- if (fragment->PhysicalFragment().IsLineBox())
- return;
- }
- NOTREACHED() << this; // Should have a line box ancestor.
-}
-
-bool NGPaintFragment::TryMarkFirstLineBoxDirtyFor(
- const LayoutObject& layout_object) {
- if (!layout_object.IsInLayoutNGInlineFormattingContext())
- return false;
- // Once we reuse lines below dirty lines, we should mark lines for all
- // inline fragments.
- if (NGPaintFragment* const fragment = layout_object.FirstInlineFragment()) {
- fragment->MarkContainingLineBoxDirty();
- return true;
- }
- return false;
-}
-
-bool NGPaintFragment::TryMarkLastLineBoxDirtyFor(
- const LayoutObject& layout_object) {
- if (!layout_object.IsInLayoutNGInlineFormattingContext())
- return false;
- // Once we reuse lines below dirty lines, we should mark lines for all
- // inline fragments.
- if (NGPaintFragment* const fragment = layout_object.FirstInlineFragment()) {
- fragment->LastForSameLayoutObject()->MarkContainingLineBoxDirty();
- return true;
- }
- return false;
-}
-
void NGPaintFragment::SetShouldDoFullPaintInvalidationRecursively() {
if (LayoutObject* layout_object = GetMutableLayoutObject()) {
layout_object->StyleRef().ClearCachedPseudoElementStyles();
@@ -1039,6 +936,25 @@ PositionWithAffinity NGPaintFragment::PositionForPointInInlineLevelBox(
return child_position.value();
}
+ if (PhysicalFragment().IsLineBox()) {
+ // There are no inline items to hit in this line box, e.g. <span> with
+ // size and border. We try in lines before |this| line in the block.
+ // See editing/selection/last-empty-inline.html
+ NGInlineCursor cursor(*Parent());
+ cursor.MoveTo(*this);
+ const PhysicalOffset point_in_line = point - OffsetInContainerBlock();
+ for (;;) {
+ cursor.MoveToPreviousLine();
+ if (!cursor)
+ break;
+ const NGPaintFragment& line = *cursor.CurrentPaintFragment();
+ const PhysicalOffset adjusted_point =
+ point_in_line + line.OffsetInContainerBlock();
+ if (auto position = line.PositionForPointInInlineLevelBox(adjusted_point))
+ return position;
+ }
+ }
+
return PositionWithAffinity();
}
diff --git a/chromium/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.h b/chromium/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.h
index fd197b7cd86..383c5d217f3 100644
--- a/chromium/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.h
+++ b/chromium/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.h
@@ -218,10 +218,6 @@ class CORE_EXPORT NGPaintFragment : public RefCounted<NGPaintFragment>,
// in DOM tree.
PositionWithAffinity PositionForPoint(const PhysicalOffset&) const;
- // Returns true when associated fragment of |layout_object| has line box.
- static bool TryMarkFirstLineBoxDirtyFor(const LayoutObject& layout_object);
- static bool TryMarkLastLineBoxDirtyFor(const LayoutObject& layout_object);
-
// A range of fragments for |FragmentsFor()|.
class TraverseNextForSameLayoutObject {
STATIC_ONLY(TraverseNextForSameLayoutObject);
@@ -259,19 +255,6 @@ class CORE_EXPORT NGPaintFragment : public RefCounted<NGPaintFragment>,
void ClearAssociationWithLayoutObject();
- // Called when lines containing |child| is dirty.
- static void DirtyLinesFromChangedChild(LayoutObject* child);
-
- // Mark this line box was changed, in order to re-use part of an inline
- // formatting context.
- void MarkLineBoxDirty() {
- DCHECK(PhysicalFragment().IsLineBox());
- is_dirty_inline_ = true;
- }
-
- // Mark the line box that contains this fragment dirty.
- void MarkContainingLineBoxDirty();
-
// Computes LocalVisualRect for an inline LayoutObject. Returns nullopt if the
// LayoutObject is not in LayoutNG inline formatting context.
static base::Optional<PhysicalRect> LocalVisualRectFor(const LayoutObject&);
diff --git a/chromium/third_party/blink/renderer/core/paint/ng/ng_paint_fragment_test.cc b/chromium/third_party/blink/renderer/core/paint/ng/ng_paint_fragment_test.cc
index d778705c23d..35d01701447 100644
--- a/chromium/third_party/blink/renderer/core/paint/ng/ng_paint_fragment_test.cc
+++ b/chromium/third_party/blink/renderer/core/paint/ng/ng_paint_fragment_test.cc
@@ -704,22 +704,6 @@ TEST_F(NGPaintFragmentTest, OutOfFlow) {
EXPECT_EQ(1u, lines[0]->Children().size());
}
-TEST_F(NGPaintFragmentTest, MarkLineBoxesDirtyByRemoveBr) {
- if (RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled())
- return;
- if (!RuntimeEnabledFeatures::LayoutNGLineCacheEnabled())
- return;
- SetBodyInnerHTML(
- "<div id=container>line 1<br>line 2<br id=target>line 3<br>"
- "</div>");
- Element& target = *GetDocument().getElementById("target");
- target.remove();
- const NGPaintFragment& container = *GetPaintFragmentByElementId("container");
- EXPECT_FALSE(container.FirstChild()->IsDirty());
- EXPECT_TRUE(ToList(container.Children())[1]->IsDirty());
- EXPECT_FALSE(ToList(container.Children())[2]->IsDirty());
-}
-
static const char* inline_child_data[] = {
"<span id='child'>XXX</span>",
"<span id='child' style='background: yellow'>XXX</span>",
@@ -760,194 +744,4 @@ TEST_P(InlineChildTest, RemoveInlineChild) {
EXPECT_EQ(linebox.Children().size(), 2u);
}
-TEST_F(NGPaintFragmentTest, MarkLineBoxesDirtyByRemoveChild) {
- if (RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled())
- return;
- if (!RuntimeEnabledFeatures::LayoutNGLineCacheEnabled())
- return;
- SetBodyInnerHTML(
- "<div id=container>line 1<br><b id=target>line 2</b><br>line 3<br>"
- "</div>");
- Element& target = *GetDocument().getElementById("target");
- target.remove();
- const NGPaintFragment& container = *GetPaintFragmentByElementId("container");
- auto lines = ToList(container.Children());
- EXPECT_TRUE(lines[0]->IsDirty());
- EXPECT_FALSE(lines[1]->IsDirty());
- EXPECT_FALSE(lines[2]->IsDirty());
-}
-
-TEST_F(NGPaintFragmentTest, MarkLineBoxesDirtyByRemoveSpanWithBr) {
- if (RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled())
- return;
- if (!RuntimeEnabledFeatures::LayoutNGLineCacheEnabled())
- return;
- SetBodyInnerHTML(
- "<div id=container>line 1<br>line 2<span id=target><br></span>line 3<br>"
- "</div>");
- // |target| is a culled inline box. There is no fragment in fragment tree.
- Element& target = *GetDocument().getElementById("target");
- target.remove();
- const NGPaintFragment& container = *GetPaintFragmentByElementId("container");
- EXPECT_FALSE(container.FirstChild()->IsDirty());
- EXPECT_TRUE(ToList(container.Children())[1]->IsDirty());
- EXPECT_FALSE(ToList(container.Children())[2]->IsDirty());
-}
-
-// "ByInsert" tests are disabled, because they require |UpdateStyleAndLayout()|
-// to update |IsDirty|, but NGPaintFragment maybe re-used during the layout. In
-// such case, the result is not deterministic.
-TEST_F(NGPaintFragmentTest, DISABLED_MarkLineBoxesDirtyByInsertAtStart) {
- if (RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled())
- return;
- if (!RuntimeEnabledFeatures::LayoutNGLineCacheEnabled())
- return;
- SetBodyInnerHTML(
- "<div id=container>line 1<br><b id=target>line 2</b><br>line 3<br>"
- "</div>");
- const NGPaintFragment& container = *GetPaintFragmentByElementId("container");
- const scoped_refptr<const NGPaintFragment> line1 = container.FirstChild();
- ASSERT_TRUE(line1->PhysicalFragment().IsLineBox()) << line1;
- const scoped_refptr<const NGPaintFragment> line2 =
- ToList(container.Children())[1];
- ASSERT_TRUE(line2->PhysicalFragment().IsLineBox()) << line2;
- const scoped_refptr<const NGPaintFragment> line3 =
- ToList(container.Children())[2];
- ASSERT_TRUE(line3->PhysicalFragment().IsLineBox()) << line3;
- Element& target = *GetDocument().getElementById("target");
- target.parentNode()->insertBefore(Text::Create(GetDocument(), "XYZ"),
- &target);
- GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest);
-
- EXPECT_TRUE(line1->IsDirty());
- EXPECT_FALSE(line2->IsDirty());
- EXPECT_FALSE(line3->IsDirty());
-}
-
-// "ByInsert" tests are disabled, because they require |UpdateStyleAndLayout()|
-// to update |IsDirty|, but NGPaintFragment maybe re-used during the layout. In
-// such case, the result is not deterministic.
-TEST_F(NGPaintFragmentTest, DISABLED_MarkLineBoxesDirtyByInsertAtLast) {
- if (RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled())
- return;
- if (!RuntimeEnabledFeatures::LayoutNGLineCacheEnabled())
- return;
- SetBodyInnerHTML(
- "<div id=container>line 1<br><b id=target>line 2</b><br>line 3<br>"
- "</div>");
- const NGPaintFragment& container = *GetPaintFragmentByElementId("container");
- const scoped_refptr<const NGPaintFragment> line1 = container.FirstChild();
- ASSERT_TRUE(line1->PhysicalFragment().IsLineBox()) << line1;
- const scoped_refptr<const NGPaintFragment> line2 =
- ToList(container.Children())[1];
- ASSERT_TRUE(line2->PhysicalFragment().IsLineBox()) << line2;
- const scoped_refptr<const NGPaintFragment> line3 =
- ToList(container.Children())[2];
- ASSERT_TRUE(line3->PhysicalFragment().IsLineBox()) << line3;
- Element& target = *GetDocument().getElementById("target");
- target.parentNode()->appendChild(Text::Create(GetDocument(), "XYZ"));
- GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest);
-
- EXPECT_FALSE(line1->IsDirty());
- EXPECT_FALSE(line2->IsDirty());
- EXPECT_TRUE(line3->IsDirty());
-}
-
-// "ByInsert" tests are disabled, because they require |UpdateStyleAndLayout()|
-// to update |IsDirty|, but NGPaintFragment maybe re-used during the layout. In
-// such case, the result is not deterministic.
-TEST_F(NGPaintFragmentTest, DISABLED_MarkLineBoxesDirtyByInsertAtMiddle) {
- if (RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled())
- return;
- if (!RuntimeEnabledFeatures::LayoutNGLineCacheEnabled())
- return;
- SetBodyInnerHTML(
- "<div id=container>line 1<br><b id=target>line 2</b><br>line 3<br>"
- "</div>");
- const NGPaintFragment& container = *GetPaintFragmentByElementId("container");
- const scoped_refptr<const NGPaintFragment> line1 = container.FirstChild();
- ASSERT_TRUE(line1->PhysicalFragment().IsLineBox()) << line1;
- const scoped_refptr<const NGPaintFragment> line2 =
- ToList(container.Children())[1];
- ASSERT_TRUE(line2->PhysicalFragment().IsLineBox()) << line2;
- const scoped_refptr<const NGPaintFragment> line3 =
- ToList(container.Children())[2];
- ASSERT_TRUE(line3->PhysicalFragment().IsLineBox()) << line3;
- Element& target = *GetDocument().getElementById("target");
- target.parentNode()->insertBefore(Text::Create(GetDocument(), "XYZ"),
- target.nextSibling());
- GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest);
-
- EXPECT_TRUE(line1->IsDirty());
- EXPECT_FALSE(line2->IsDirty());
- EXPECT_FALSE(line3->IsDirty());
-}
-
-TEST_F(NGPaintFragmentTest, MarkLineBoxesDirtyByTextSetData) {
- if (RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled())
- return;
- if (!RuntimeEnabledFeatures::LayoutNGLineCacheEnabled())
- return;
- SetBodyInnerHTML(
- "<div id=container>line 1<br><b id=target>line 2</b><br>line "
- "3<br></div>");
- Element& target = *GetDocument().getElementById("target");
- To<Text>(*target.firstChild()).setData("abc");
- const NGPaintFragment& container = *GetPaintFragmentByElementId("container");
- auto lines = ToList(container.Children());
- // TODO(kojii): Currently we don't optimzie for <br>. We can do this, then
- // lines[0] should not be dirty.
- EXPECT_TRUE(lines[0]->IsDirty());
-}
-
-TEST_F(NGPaintFragmentTest, MarkLineBoxesDirtyWrappedLine) {
- if (RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled())
- return;
- if (!RuntimeEnabledFeatures::LayoutNGLineCacheEnabled())
- return;
- SetBodyInnerHTML(R"HTML(
- <style>
- #container {
- font-size: 10px;
- width: 10ch;
- }
- </style>
- <div id=container>
- 1234567
- 123456<span id="target">7</span>
- </div>)HTML");
- Element& target = *GetDocument().getElementById("target");
- target.remove();
-
- const NGPaintFragment& container = *GetPaintFragmentByElementId("container");
- const NGPaintFragment& line0 = *container.FirstChild();
- const NGPaintFragment& line1 = *line0.NextSibling();
- EXPECT_FALSE(line0.IsDirty());
- EXPECT_TRUE(line1.IsDirty());
-}
-
-TEST_F(NGPaintFragmentTest, MarkLineBoxesDirtyInsideInlineBlock) {
- if (RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled())
- return;
- if (!RuntimeEnabledFeatures::LayoutNGLineCacheEnabled())
- return;
- SetBodyInnerHTML(R"HTML(
- <div id=container>
- <div id="inline-block" style="display: inline-block">
- <span id="target">DELETE ME</span>
- </div>
- </div>)HTML");
- Element& target = *GetDocument().getElementById("target");
- target.remove();
-
- const NGPaintFragment& container = *GetPaintFragmentByElementId("container");
- const NGPaintFragment& line0 = *container.FirstChild();
- EXPECT_FALSE(line0.IsDirty());
-
- const NGPaintFragment& inline_block =
- *GetPaintFragmentByElementId("inline-block");
- const NGPaintFragment& inner_line0 = *inline_block.FirstChild();
- EXPECT_TRUE(inner_line0.IsDirty());
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/object_painter_base.cc b/chromium/third_party/blink/renderer/core/paint/object_painter_base.cc
index 096fd2913e1..78936e5ee6b 100644
--- a/chromium/third_party/blink/renderer/core/paint/object_painter_base.cc
+++ b/chromium/third_party/blink/renderer/core/paint/object_painter_base.cc
@@ -98,8 +98,8 @@ void PaintComplexOutline(GraphicsContext& graphics_context,
// Construct a clockwise path along the outer edge of the outline.
SkRegion region;
- uint16_t width = style.OutlineWidth();
- int outset = style.OutlineOffset() + style.OutlineWidth();
+ uint16_t width = style.OutlineWidthInt();
+ int outset = style.OutlineOffsetInt() + style.OutlineWidthInt();
for (auto& r : rects) {
IntRect rect = r;
rect.Inflate(outset);
@@ -111,13 +111,26 @@ void PaintComplexOutline(GraphicsContext& graphics_context,
Vector<OutlineEdgeInfo, 4> edges;
- SkPath::Iter iter(path, false);
- SkPoint points[4];
+ SkPath::RawIter iter(path);
+ SkPoint points[4], first_point, last_point;
wtf_size_t count = 0;
for (SkPath::Verb verb = iter.next(points); verb != SkPath::kDone_Verb;
verb = iter.next(points)) {
+ // Keep track of the first and last point of each contour (started with
+ // kMove_Verb) so we can add the closing-line on kClose_Verb.
+ if (verb == SkPath::kMove_Verb) {
+ first_point = points[0];
+ last_point = first_point; // this gets reset after each line, but we
+ // initialize it here
+ } else if (verb == SkPath::kClose_Verb) {
+ // create an artificial line to close the contour
+ verb = SkPath::kLine_Verb;
+ points[0] = last_point;
+ points[1] = first_point;
+ }
if (verb != SkPath::kLine_Verb)
continue;
+ last_point = points[1];
edges.Grow(++count);
OutlineEdgeInfo& edge = edges.back();
@@ -192,10 +205,10 @@ void PaintSingleRectangleOutline(const PaintInfo& paint_info,
DCHECK(!style.OutlineStyleIsAuto());
PhysicalRect inner(rect);
- inner.Inflate(LayoutUnit(style.OutlineOffset()));
+ inner.Inflate(LayoutUnit(style.OutlineOffsetInt()));
PhysicalRect outer(inner);
- outer.Inflate(LayoutUnit(style.OutlineWidth()));
- const BorderEdge common_edge_info(style.OutlineWidth(), color,
+ outer.Inflate(LayoutUnit(style.OutlineWidthInt()));
+ const BorderEdge common_edge_info(style.OutlineWidthInt(), color,
style.OutlineStyle());
BoxBorderPainter(style, outer, inner, common_edge_info)
.PaintBorder(paint_info, outer);
@@ -550,9 +563,7 @@ void ObjectPainterBase::PaintOutlineRects(
float border_radius = GetFocusRingBorderRadius(style);
paint_info.context.DrawFocusRing(
pixel_snapped_outline_rects, style.GetOutlineStrokeWidthForFocusRing(),
- style.OutlineOffset(), style.GetDefaultOffsetForFocusRing(),
- border_radius, min_border_width, color,
- LayoutTheme::GetTheme().IsFocusRingOutset());
+ style.OutlineOffsetInt(), border_radius, min_border_width, color);
return;
}
diff --git a/chromium/third_party/blink/renderer/core/paint/paint_and_raster_invalidation_test.cc b/chromium/third_party/blink/renderer/core/paint/paint_and_raster_invalidation_test.cc
index 773e223519d..34461098c5c 100644
--- a/chromium/third_party/blink/renderer/core/paint/paint_and_raster_invalidation_test.cc
+++ b/chromium/third_party/blink/renderer/core/paint/paint_and_raster_invalidation_test.cc
@@ -81,7 +81,7 @@ TEST_P(PaintAndRasterInvalidationTest, TrackingForTracing) {
.View()
->GetPaintArtifactCompositor()
->RootLayer()
- ->children()[0]
+ ->children()[1]
.get()
: GetLayoutView().Layer()->GraphicsLayerBacking()->CcLayer();
diff --git a/chromium/third_party/blink/renderer/core/paint/paint_controller_paint_test.cc b/chromium/third_party/blink/renderer/core/paint/paint_controller_paint_test.cc
index cafc50592fd..593e66c86fc 100644
--- a/chromium/third_party/blink/renderer/core/paint/paint_controller_paint_test.cc
+++ b/chromium/third_party/blink/renderer/core/paint/paint_controller_paint_test.cc
@@ -238,10 +238,7 @@ TEST_P(PaintControllerPaintTestForCAP, BlockScrollingNonLayeredContents) {
EXPECT_THAT(
RootPaintController().PaintChunks(),
ElementsAre(
- IsPaintChunk(0, 1,
- PaintChunk::Id(ViewScrollingBackgroundClient(),
- DisplayItem::kDocumentBackground),
- GetLayoutView().FirstFragment().ContentsProperties()),
+ IsPaintChunk(0, 0), IsPaintChunk(0, 1), // LayoutView chunks.
IsPaintChunk(
1, 1,
PaintChunk::Id(*container.Layer(), DisplayItem::kLayerChunk),
@@ -270,10 +267,7 @@ TEST_P(PaintControllerPaintTestForCAP, BlockScrollingNonLayeredContents) {
EXPECT_THAT(
RootPaintController().PaintChunks(),
ElementsAre(
- IsPaintChunk(0, 1,
- PaintChunk::Id(ViewScrollingBackgroundClient(),
- DisplayItem::kDocumentBackground),
- GetLayoutView().FirstFragment().ContentsProperties()),
+ IsPaintChunk(0, 0), IsPaintChunk(0, 1), // LayoutView chunks.
IsPaintChunk(
1, 1,
PaintChunk::Id(*container.Layer(), DisplayItem::kLayerChunk),
@@ -400,10 +394,7 @@ TEST_P(PaintControllerPaintTestForCAP, NonStackingScrollHitTestOrder) {
EXPECT_THAT(
RootPaintController().PaintChunks(),
ElementsAre(
- IsPaintChunk(0, 1,
- PaintChunk::Id(ViewScrollingBackgroundClient(),
- DisplayItem::kDocumentBackground),
- GetLayoutView().FirstFragment().ContentsProperties()),
+ IsPaintChunk(0, 0), IsPaintChunk(0, 1), // LayoutView chunks.
IsPaintChunk(
1, 2,
PaintChunk::Id(*neg_z_child.Layer(), DisplayItem::kLayerChunk),
@@ -480,10 +471,7 @@ TEST_P(PaintControllerPaintTestForCAP, StackingScrollHitTestOrder) {
EXPECT_THAT(
RootPaintController().PaintChunks(),
ElementsAre(
- IsPaintChunk(0, 1,
- PaintChunk::Id(ViewScrollingBackgroundClient(),
- DisplayItem::kDocumentBackground),
- GetLayoutView().FirstFragment().ContentsProperties()),
+ IsPaintChunk(0, 0), IsPaintChunk(0, 1), // LayoutView chunks.
IsPaintChunk(
1, 2,
PaintChunk::Id(*container.Layer(), DisplayItem::kLayerChunk),
@@ -553,10 +541,7 @@ TEST_P(PaintControllerPaintTestForCAP,
EXPECT_THAT(
RootPaintController().PaintChunks(),
ElementsAre(
- IsPaintChunk(0, 1,
- PaintChunk::Id(ViewScrollingBackgroundClient(),
- DisplayItem::kDocumentBackground),
- GetLayoutView().FirstFragment().ContentsProperties()),
+ IsPaintChunk(0, 0), IsPaintChunk(0, 1), // LayoutView chunks.
IsPaintChunk(
1, 2,
PaintChunk::Id(*neg_z_child.Layer(), DisplayItem::kLayerChunk),
diff --git a/chromium/third_party/blink/renderer/core/paint/paint_layer.cc b/chromium/third_party/blink/renderer/core/paint/paint_layer.cc
index 0d52eb19e02..5d77cf4adbb 100644
--- a/chromium/third_party/blink/renderer/core/paint/paint_layer.cc
+++ b/chromium/third_party/blink/renderer/core/paint/paint_layer.cc
@@ -48,6 +48,7 @@
#include "base/allocator/partition_allocator/partition_alloc.h"
#include "base/containers/adapters.h"
+#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/renderer/core/animation/scroll_timeline.h"
#include "third_party/blink/renderer/core/css/css_property_names.h"
@@ -181,6 +182,8 @@ PaintLayer::PaintLayer(LayoutBoxModelObject& layout_object)
descendant_needs_compositing_layer_assignment_(false),
has_self_painting_layer_descendant_(false),
needs_reorder_overlay_overflow_controls_(false),
+ static_inline_edge_(InlineEdge::kInlineStart),
+ static_block_edge_(BlockEdge::kBlockStart),
#if DCHECK_IS_ON()
layer_list_mutation_allowed_(true),
#endif
@@ -221,10 +224,8 @@ PaintLayer::~PaintLayer() {
// Child layers will be deleted by their corresponding layout objects, so
// we don't need to delete them ourselves.
- {
- DisableCompositingQueryAsserts disabler;
+ if (HasCompositedLayerMapping())
ClearCompositedLayerMapping(true);
- }
// Reset this flag before disposing scrollable_area_ to prevent
// PaintLayerScrollableArea::WillRemoveScrollbar() from dirtying the z-order
@@ -262,6 +263,11 @@ PaintLayerCompositor* PaintLayer::Compositor() const {
}
void PaintLayer::ContentChanged(ContentChangeType change_type) {
+ // Content changes in CAP are reflected in changes to what is painted, nothing
+ // to do here.
+ if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
+ return;
+
// updateLayerCompositingState will query compositingReasons for accelerated
// overflow scrolling. This is tripped by
// web_tests/compositing/content-changed-chicken-egg.html
@@ -368,6 +374,7 @@ bool PaintLayer::FixedToViewport() const {
}
bool PaintLayer::ScrollsWithRespectTo(const PaintLayer* other) const {
+ DCHECK(!RuntimeEnabledFeatures::CompositeAfterPaintEnabled());
if (FixedToViewport() != other->FixedToViewport())
return true;
// If either element sticks we cannot trivially determine that the layers do
@@ -640,8 +647,18 @@ void PaintLayer::UpdateDescendantDependentFlags() {
bool can_contain_abs =
GetLayoutObject().CanContainAbsolutePositionObjects();
- for (PaintLayer* child = FirstChild(); child;
- child = child->NextSibling()) {
+ auto* first_child = [this]() -> PaintLayer* {
+ if (GetLayoutObject().PrePaintBlockedByDisplayLock(
+ DisplayLockLifecycleTarget::kChildren)) {
+ GetLayoutObject()
+ .GetDisplayLockContext()
+ ->NotifyCompositingDescendantDependentFlagUpdateWasBlocked();
+ return nullptr;
+ }
+ return FirstChild();
+ }();
+
+ for (PaintLayer* child = first_child; child; child = child->NextSibling()) {
const ComputedStyle& child_style = child->GetLayoutObject().StyleRef();
child->UpdateDescendantDependentFlags();
@@ -1177,7 +1194,7 @@ void* PaintLayer::operator new(size_t sz) {
}
void PaintLayer::operator delete(void* ptr) {
- base::PartitionFree(ptr);
+ WTF::Partitions::LayoutPartition()->Free(ptr);
}
void PaintLayer::AddChild(PaintLayer* child, PaintLayer* before_child) {
@@ -1633,8 +1650,9 @@ void PaintLayer::CollectFragments(
// The inherited offset_from_root does not include any pagination offsets.
// In the presence of fragmentation, we cannot use it.
bool offset_from_root_can_be_used = offset_from_root && !is_fragmented;
+ wtf_size_t physical_fragment_idx = 0u;
for (auto* fragment_data = &first_fragment_data; fragment_data;
- fragment_data = fragment_data->NextFragment()) {
+ fragment_data = fragment_data->NextFragment(), physical_fragment_idx++) {
const FragmentData* root_fragment_data;
if (root_layer == this) {
root_fragment_data = fragment_data;
@@ -1691,12 +1709,10 @@ void PaintLayer::CollectFragments(
fragment.fragment_data = fragment_data;
if (GetLayoutObject().CanTraversePhysicalFragments()) {
- if (const auto* block = DynamicTo<LayoutBlock>(&GetLayoutObject())) {
- fragment.physical_fragment = block->CurrentFragment();
+ if (const LayoutBox* layout_box = ToLayoutBoxOrNull(GetLayoutObject())) {
+ fragment.physical_fragment =
+ layout_box->GetPhysicalFragment(physical_fragment_idx);
DCHECK(fragment.physical_fragment);
-
- // TODO(mstensho): Implement support for multiple fragments per node.
- DCHECK(!fragment_data->NextFragment());
}
}
@@ -2578,6 +2594,34 @@ PhysicalRect PaintLayer::BoundingBoxForCompositingOverlapTest() const {
bounding_box = PhysicalRect::EnclosingRect(
style.BackdropFilter().MapRect(FloatRect(bounding_box)));
}
+
+ if (base::FeatureList::IsEnabled(features::kMaxOverlapBoundsForFixed) &&
+ !bounding_box.IsEmpty()) {
+ if (FixedToViewport()) {
+ DCHECK_EQ(style.GetPosition(), EPosition::kFixed);
+ // Note that we only expand the bounding box for overlap testing when the
+ // fixed's containing block is the viewport. This keeps us from expanding
+ // the bounds when the fixed is a child of an ancestor with transform,
+ // filters, etc. and the fixed is no longer scroll position dependent.
+
+ // Expand the bounding box by the amount that scrolling the
+ // viewport can expand the area that this fixed-pos element could
+ // cover. Compute how much we could still scroll in each direction.
+ // |max_scroll_delta| is the amount we could still scroll in
+ // increasing offset direction. |min_scroll_delta| is the amount we
+ // can still scroll in a decreasing scroll offset direction.
+ PaintLayerScrollableArea* scrollable_area =
+ GetLayoutObject().View()->GetScrollableArea();
+ ScrollOffset current_scroll_offset = scrollable_area->GetScrollOffset();
+ ScrollOffset max_scroll_delta =
+ scrollable_area->MaximumScrollOffset() - current_scroll_offset;
+ ScrollOffset min_scroll_delta =
+ current_scroll_offset - scrollable_area->MinimumScrollOffset();
+ bounding_box.Expand(LayoutRectOutsets(
+ min_scroll_delta.Height(), max_scroll_delta.Width(),
+ max_scroll_delta.Height(), min_scroll_delta.Width()));
+ }
+ }
return bounding_box;
}
@@ -2762,26 +2806,24 @@ void PaintLayer::EnsureCompositedLayerMapping() {
}
void PaintLayer::ClearCompositedLayerMapping(bool layer_being_destroyed) {
- if (!HasCompositedLayerMapping())
- return;
+ DCHECK(HasCompositedLayerMapping());
+ DCHECK(!RuntimeEnabledFeatures::CompositeAfterPaintEnabled());
+ DisableCompositingQueryAsserts disabler;
if (layer_being_destroyed) {
- if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
- // The visual rects will be in a different coordinate space after losing
- // their compositing container. Clear them before prepaint to avoid
- // spurious layout shift reports from LayoutShiftTracker.
- // If the PaintLayer were not being destroyed, this would happen during
- // the compositing update (PaintLayerCompositor::UpdateIfNeeded).
- // TODO: LayoutShiftTracker's reliance on having visual rects cleared
- // before prepaint in the case of compositing changes is not ideal, and
- // will not work with CompositeAfterPaint. Some transform tree changes may
- // still produce incorrect behavior from LayoutShiftTracker (see
- // discussion on review thread of http://crrev.com/c/1636403).
- if (Compositor()) {
- Compositor()
- ->ForceRecomputeVisualRectsIncludingNonCompositingDescendants(
- layout_object_);
- }
+ // The visual rects will be in a different coordinate space after losing
+ // their compositing container. Clear them before prepaint to avoid
+ // spurious layout shift reports from LayoutShiftTracker.
+ // If the PaintLayer were not being destroyed, this would happen during
+ // the compositing update (PaintLayerCompositor::UpdateIfNeeded).
+ // TODO: LayoutShiftTracker's reliance on having visual rects cleared
+ // before prepaint in the case of compositing changes is not ideal, and
+ // will not work with CompositeAfterPaint. Some transform tree changes may
+ // still produce incorrect behavior from LayoutShiftTracker (see
+ // discussion on review thread of http://crrev.com/c/1636403).
+ if (Compositor()) {
+ Compositor()->ForceRecomputeVisualRectsIncludingNonCompositingDescendants(
+ layout_object_);
}
} else {
// We need to make sure our decendants get a geometry update. In principle,
@@ -2866,16 +2908,9 @@ bool PaintLayer::CompositesWithTransform() const {
return TransformAncestor() || Transform();
}
-bool PaintLayer::CompositesWithOpacity() const {
- return OpacityAncestor() || GetLayoutObject().StyleRef().HasOpacity();
-}
-
bool PaintLayer::BackgroundIsKnownToBeOpaqueInRect(
const PhysicalRect& local_rect,
bool should_check_children) const {
- if (PaintsWithTransparency(kGlobalPaintNormalPhase))
- return false;
-
// We can't use hasVisibleContent(), because that will be true if our
// layoutObject is hidden, but some child is visible and that child doesn't
// cover the entire rect.
@@ -2929,6 +2964,9 @@ bool PaintLayer::ChildBackgroundIsKnownToBeOpaqueInRect(
if (!child_layer->CanUseConvertToLayerCoords())
continue;
+ if (child_layer->PaintsWithTransparency(kGlobalPaintNormalPhase))
+ continue;
+
PhysicalOffset child_offset;
PhysicalRect child_local_rect(local_rect);
child_layer->ConvertToLayerCoords(this, child_offset);
@@ -3154,7 +3192,7 @@ void PaintLayer::StyleDidChange(StyleDifference diff,
if (diff.CompositingReasonsChanged()) {
SetNeedsCompositingInputsUpdate();
- } else {
+ } else if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
// For querying stale GetCompositingState().
DisableCompositingQueryAsserts disable;
@@ -3325,8 +3363,11 @@ void PaintLayer::RemoveAncestorOverflowLayer(const PaintLayer* removed_layer) {
// constrained by the root.
if (AncestorOverflowLayer()->IsRootLayer() &&
GetLayoutObject().StyleRef().HasStickyConstrainedPosition()) {
- if (LocalFrameView* frame_view = GetLayoutObject().GetFrameView())
- frame_view->RemoveViewportConstrainedObject(GetLayoutObject());
+ if (LocalFrameView* frame_view = GetLayoutObject().GetFrameView()) {
+ frame_view->RemoveViewportConstrainedObject(
+ GetLayoutObject(),
+ LocalFrameView::ViewportConstrainedType::kSticky);
+ }
}
if (PaintLayerScrollableArea* ancestor_scrollable_area =
@@ -3479,13 +3520,15 @@ void PaintLayer::DirtyStackingContextZOrderLists() {
if (!stacking_context)
return;
- // This invalidation code intentionally refers to stale state.
- DisableCompositingQueryAsserts disabler;
+ if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
+ // This invalidation code intentionally refers to stale state.
+ DisableCompositingQueryAsserts disabler;
- // Changes of stacking may result in graphics layers changing size
- // due to new contents painting into them.
- if (auto* mapping = stacking_context->GetCompositedLayerMapping())
- mapping->SetNeedsGraphicsLayerUpdate(kGraphicsLayerUpdateSubtree);
+ // Changes of stacking may result in graphics layers changing size
+ // due to new contents painting into them.
+ if (auto* mapping = stacking_context->GetCompositedLayerMapping())
+ mapping->SetNeedsGraphicsLayerUpdate(kGraphicsLayerUpdateSubtree);
+ }
if (stacking_context->StackingNode())
stacking_context->StackingNode()->DirtyZOrderLists();
diff --git a/chromium/third_party/blink/renderer/core/paint/paint_layer.h b/chromium/third_party/blink/renderer/core/paint/paint_layer.h
index 98a46602c6d..641f83bf27a 100644
--- a/chromium/third_party/blink/renderer/core/paint/paint_layer.h
+++ b/chromium/third_party/blink/renderer/core/paint/paint_layer.h
@@ -51,6 +51,7 @@
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/layout/hit_testing_transform_state.h"
#include "third_party/blink/renderer/core/layout/layout_box.h"
+#include "third_party/blink/renderer/core/layout/ng/geometry/ng_static_position.h"
#include "third_party/blink/renderer/core/paint/clip_rects_cache.h"
#include "third_party/blink/renderer/core/paint/paint_layer_clipper.h"
#include "third_party/blink/renderer/core/paint/paint_layer_fragment.h"
@@ -492,6 +493,31 @@ class CORE_EXPORT PaintLayer : public DisplayItemClient {
static_block_position_ = position;
}
+ using InlineEdge = NGLogicalStaticPosition::InlineEdge;
+ using BlockEdge = NGLogicalStaticPosition::BlockEdge;
+ InlineEdge StaticInlineEdge() const {
+ return static_cast<InlineEdge>(static_inline_edge_);
+ }
+ BlockEdge StaticBlockEdge() const {
+ return static_cast<BlockEdge>(static_block_edge_);
+ }
+
+ void SetStaticPositionFromNG(const NGLogicalStaticPosition& position) {
+ static_inline_position_ = position.offset.inline_offset;
+ static_block_position_ = position.offset.block_offset;
+ static_inline_edge_ = position.inline_edge;
+ static_block_edge_ = position.block_edge;
+ }
+
+ NGLogicalStaticPosition GetStaticPosition() const {
+ NGLogicalStaticPosition position;
+ position.offset.inline_offset = static_inline_position_;
+ position.offset.block_offset = static_block_position_;
+ position.inline_edge = StaticInlineEdge();
+ position.block_edge = StaticBlockEdge();
+ return position;
+ }
+
PhysicalOffset SubpixelAccumulation() const;
void SetSubpixelAccumulation(const PhysicalOffset&);
@@ -604,9 +630,6 @@ class CORE_EXPORT PaintLayer : public DisplayItemClient {
// Returns true if the element or any ancestor is transformed.
bool CompositesWithTransform() const;
- // Returns true if the element or any ancestor has non 1 opacity.
- bool CompositesWithOpacity() const;
-
bool PaintsWithTransform(GlobalPaintFlags) const;
bool PaintsIntoOwnBacking(GlobalPaintFlags) const;
bool PaintsIntoOwnOrGroupedBacking(GlobalPaintFlags) const;
@@ -789,8 +812,6 @@ class CORE_EXPORT PaintLayer : public DisplayItemClient {
IntRect unclipped_absolute_bounding_box;
const LayoutBoxModelObject* clipping_container = nullptr;
-
- bool is_under_position_sticky = false;
};
bool NeedsVisualOverflowRecalc() const {
return needs_visual_overflow_recalc_;
@@ -1348,6 +1369,8 @@ class CORE_EXPORT PaintLayer : public DisplayItemClient {
unsigned has_self_painting_layer_descendant_ : 1;
unsigned needs_reorder_overlay_overflow_controls_ : 1;
+ unsigned static_inline_edge_ : 2;
+ unsigned static_block_edge_ : 2;
#if DCHECK_IS_ON()
mutable unsigned layer_list_mutation_allowed_ : 1;
diff --git a/chromium/third_party/blink/renderer/core/paint/paint_layer_painter.cc b/chromium/third_party/blink/renderer/core/paint/paint_layer_painter.cc
index 9017869339e..09b97a19387 100644
--- a/chromium/third_party/blink/renderer/core/paint/paint_layer_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/paint_layer_painter.cc
@@ -49,7 +49,7 @@ static ShouldRespectOverflowClipType ShouldRespectOverflowClip(
}
bool PaintLayerPainter::PaintedOutputInvisible(const ComputedStyle& style) {
- if (style.HasBackdropFilter())
+ if (style.HasNonInitialBackdropFilter())
return false;
// Always paint when 'will-change: opacity' is present. Reduces jank for
diff --git a/chromium/third_party/blink/renderer/core/paint/paint_layer_painter_test.cc b/chromium/third_party/blink/renderer/core/paint/paint_layer_painter_test.cc
index c191b7a6e9a..220ec52886c 100644
--- a/chromium/third_party/blink/renderer/core/paint/paint_layer_painter_test.cc
+++ b/chromium/third_party/blink/renderer/core/paint/paint_layer_painter_test.cc
@@ -98,30 +98,60 @@ TEST_P(PaintLayerPainterTest, CachedSubsequenceAndChunksWithBackgrounds) {
IsSameId(GetDisplayItemClientFromLayoutObject(filler2),
kBackgroundType)));
- EXPECT_SUBSEQUENCE(*container1_layer, 1, 2);
- EXPECT_SUBSEQUENCE(*filler1_layer, 2, 3);
- EXPECT_SUBSEQUENCE(*container2_layer, 3, 4);
- EXPECT_SUBSEQUENCE(*filler2_layer, 4, 5);
-
// Check that new paint chunks were forced for the layers.
- EXPECT_THAT(
- RootPaintController().PaintChunks(),
- ElementsAre(
- IsPaintChunk(0, 1),
- IsPaintChunk(
- 1, 3,
- PaintChunk::Id(*container1_layer, DisplayItem::kLayerChunk),
- chunk_state, nullptr, IntRect(0, 0, 200, 200)),
- IsPaintChunk(
- 3, 4, PaintChunk::Id(*filler1_layer, DisplayItem::kLayerChunk),
- chunk_state, nullptr, IntRect(0, 200, 20, 20)),
- IsPaintChunk(
- 4, 6,
- PaintChunk::Id(*container2_layer, DisplayItem::kLayerChunk),
- chunk_state, nullptr, IntRect(0, 220, 200, 200)),
- IsPaintChunk(
- 6, 7, PaintChunk::Id(*filler2_layer, DisplayItem::kLayerChunk),
- chunk_state, nullptr, IntRect(0, 420, 20, 20))));
+ if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
+ EXPECT_SUBSEQUENCE(*container1_layer, 2, 3);
+ EXPECT_SUBSEQUENCE(*filler1_layer, 3, 4);
+ EXPECT_SUBSEQUENCE(*container2_layer, 4, 5);
+ EXPECT_SUBSEQUENCE(*filler2_layer, 5, 6);
+
+ EXPECT_THAT(
+ RootPaintController().PaintChunks(),
+ ElementsAre(
+ IsPaintChunk(0, 0), IsPaintChunk(0, 1), // LayoutView chunks.
+ IsPaintChunk(
+ 1, 3,
+ PaintChunk::Id(*container1_layer, DisplayItem::kLayerChunk),
+ chunk_state, nullptr, IntRect(0, 0, 200, 200)),
+ IsPaintChunk(
+ 3, 4,
+ PaintChunk::Id(*filler1_layer, DisplayItem::kLayerChunk),
+ chunk_state, nullptr, IntRect(0, 200, 20, 20)),
+ IsPaintChunk(
+ 4, 6,
+ PaintChunk::Id(*container2_layer, DisplayItem::kLayerChunk),
+ chunk_state, nullptr, IntRect(0, 220, 200, 200)),
+ IsPaintChunk(
+ 6, 7,
+ PaintChunk::Id(*filler2_layer, DisplayItem::kLayerChunk),
+ chunk_state, nullptr, IntRect(0, 420, 20, 20))));
+ } else {
+ EXPECT_SUBSEQUENCE(*container1_layer, 1, 2);
+ EXPECT_SUBSEQUENCE(*filler1_layer, 2, 3);
+ EXPECT_SUBSEQUENCE(*container2_layer, 3, 4);
+ EXPECT_SUBSEQUENCE(*filler2_layer, 4, 5);
+
+ EXPECT_THAT(
+ RootPaintController().PaintChunks(),
+ ElementsAre(
+ IsPaintChunk(0, 1), // LayoutView.
+ IsPaintChunk(
+ 1, 3,
+ PaintChunk::Id(*container1_layer, DisplayItem::kLayerChunk),
+ chunk_state, nullptr, IntRect(0, 0, 200, 200)),
+ IsPaintChunk(
+ 3, 4,
+ PaintChunk::Id(*filler1_layer, DisplayItem::kLayerChunk),
+ chunk_state, nullptr, IntRect(0, 200, 20, 20)),
+ IsPaintChunk(
+ 4, 6,
+ PaintChunk::Id(*container2_layer, DisplayItem::kLayerChunk),
+ chunk_state, nullptr, IntRect(0, 220, 200, 200)),
+ IsPaintChunk(
+ 6, 7,
+ PaintChunk::Id(*filler2_layer, DisplayItem::kLayerChunk),
+ chunk_state, nullptr, IntRect(0, 420, 20, 20))));
+ }
};
check_results();
@@ -176,9 +206,9 @@ TEST_P(PaintLayerPainterTest, CachedSubsequenceAndChunksWithoutBackgrounds) {
auto* inner_content_layer = ToLayoutBoxModelObject(inner_content)->Layer();
auto* filler_layer = ToLayoutBoxModelObject(filler)->Layer();
- EXPECT_SUBSEQUENCE(*container_layer, 1, 5);
- EXPECT_SUBSEQUENCE(*content_layer, 3, 4);
- EXPECT_SUBSEQUENCE(*filler_layer, 4, 5);
+ EXPECT_SUBSEQUENCE(*container_layer, 2, 6);
+ EXPECT_SUBSEQUENCE(*content_layer, 4, 5);
+ EXPECT_SUBSEQUENCE(*filler_layer, 5, 6);
auto container_properties =
container->FirstFragment().LocalBorderBoxProperties();
@@ -190,7 +220,7 @@ TEST_P(PaintLayerPainterTest, CachedSubsequenceAndChunksWithoutBackgrounds) {
EXPECT_THAT(
RootPaintController().PaintChunks(),
ElementsAre(
- IsPaintChunk(0, 1),
+ IsPaintChunk(0, 0), IsPaintChunk(0, 1), // LayoutView chunks.
IsPaintChunk(
1, 1, PaintChunk::Id(*container_layer, DisplayItem::kLayerChunk),
container_properties, nullptr, IntRect(0, 0, 150, 150)),
@@ -216,14 +246,14 @@ TEST_P(PaintLayerPainterTest, CachedSubsequenceAndChunksWithoutBackgrounds) {
IsSameId(GetDisplayItemClientFromLayoutObject(inner_content),
kBackgroundType)));
- EXPECT_SUBSEQUENCE(*container_layer, 1, 6);
- EXPECT_SUBSEQUENCE(*content_layer, 3, 5);
- EXPECT_SUBSEQUENCE(*filler_layer, 5, 6);
+ EXPECT_SUBSEQUENCE(*container_layer, 2, 7);
+ EXPECT_SUBSEQUENCE(*content_layer, 4, 6);
+ EXPECT_SUBSEQUENCE(*filler_layer, 6, 7);
EXPECT_THAT(
RootPaintController().PaintChunks(),
ElementsAre(
- IsPaintChunk(0, 1),
+ IsPaintChunk(0, 0), IsPaintChunk(0, 1), // LayoutView chunks.
IsPaintChunk(
1, 1, PaintChunk::Id(*container_layer, DisplayItem::kLayerChunk),
container_properties, nullptr, IntRect(0, 0, 150, 150)),
@@ -570,35 +600,75 @@ TEST_P(PaintLayerPainterTest, HintedPaintChunksWithBackgrounds) {
IsSameId(content2b, kBackgroundType),
IsSameId(content2a, kBackgroundType)));
- EXPECT_THAT(
- RootPaintController().PaintChunks(),
- ElementsAre(
- IsPaintChunk(0, 1,
- PaintChunk::Id(ViewScrollingBackgroundClient(),
- kDocumentBackgroundType),
- chunk_state),
- // Includes |container1| and |content1a|.
- IsPaintChunk(
- 1, 3,
- PaintChunk::Id(*container1->Layer(), DisplayItem::kLayerChunk),
- chunk_state, nullptr, IntRect(0, 0, 800, 150)),
- // Includes |content1b| which overflows |container1|.
- IsPaintChunk(
- 3, 4,
- PaintChunk::Id(*content1b->Layer(), DisplayItem::kLayerChunk),
- chunk_state, nullptr, IntRect(0, 100, 800, 100)),
- IsPaintChunk(
- 4, 5,
- PaintChunk::Id(*container2->Layer(), DisplayItem::kLayerChunk),
- chunk_state, nullptr, IntRect(0, 150, 800, 200)),
- IsPaintChunk(
- 5, 6,
- PaintChunk::Id(*content2b->Layer(), DisplayItem::kLayerChunk),
- chunk_state, nullptr, IntRect(0, 250, 800, 100)),
- IsPaintChunk(
- 6, 7,
- PaintChunk::Id(*content2a->Layer(), DisplayItem::kLayerChunk),
- chunk_state, nullptr, IntRect(0, 150, 800, 100))));
+ if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
+ HitTestData scroll_hit_test;
+ scroll_hit_test.scroll_translation = &chunk_state.Transform();
+ scroll_hit_test.scroll_hit_test_rect = IntRect(0, 0, 800, 600);
+ EXPECT_THAT(
+ RootPaintController().PaintChunks(),
+ ElementsAre(
+ IsPaintChunk(
+ 0, 0,
+ PaintChunk::Id(GetLayoutView(), DisplayItem::kScrollHitTest),
+ GetLayoutView().FirstFragment().LocalBorderBoxProperties(),
+ &scroll_hit_test),
+ IsPaintChunk(0, 1,
+ PaintChunk::Id(ViewScrollingBackgroundClient(),
+ kDocumentBackgroundType),
+ chunk_state),
+ // Includes |container1| and |content1a|.
+ IsPaintChunk(
+ 1, 3,
+ PaintChunk::Id(*container1->Layer(), DisplayItem::kLayerChunk),
+ chunk_state, nullptr, IntRect(0, 0, 800, 150)),
+ // Includes |content1b| which overflows |container1|.
+ IsPaintChunk(
+ 3, 4,
+ PaintChunk::Id(*content1b->Layer(), DisplayItem::kLayerChunk),
+ chunk_state, nullptr, IntRect(0, 100, 800, 100)),
+ IsPaintChunk(
+ 4, 5,
+ PaintChunk::Id(*container2->Layer(), DisplayItem::kLayerChunk),
+ chunk_state, nullptr, IntRect(0, 150, 800, 200)),
+ IsPaintChunk(
+ 5, 6,
+ PaintChunk::Id(*content2b->Layer(), DisplayItem::kLayerChunk),
+ chunk_state, nullptr, IntRect(0, 250, 800, 100)),
+ IsPaintChunk(
+ 6, 7,
+ PaintChunk::Id(*content2a->Layer(), DisplayItem::kLayerChunk),
+ chunk_state, nullptr, IntRect(0, 150, 800, 100))));
+ } else {
+ EXPECT_THAT(
+ RootPaintController().PaintChunks(),
+ ElementsAre(
+ IsPaintChunk(0, 1,
+ PaintChunk::Id(ViewScrollingBackgroundClient(),
+ kDocumentBackgroundType),
+ chunk_state),
+ // Includes |container1| and |content1a|.
+ IsPaintChunk(
+ 1, 3,
+ PaintChunk::Id(*container1->Layer(), DisplayItem::kLayerChunk),
+ chunk_state, nullptr, IntRect(0, 0, 800, 150)),
+ // Includes |content1b| which overflows |container1|.
+ IsPaintChunk(
+ 3, 4,
+ PaintChunk::Id(*content1b->Layer(), DisplayItem::kLayerChunk),
+ chunk_state, nullptr, IntRect(0, 100, 800, 100)),
+ IsPaintChunk(
+ 4, 5,
+ PaintChunk::Id(*container2->Layer(), DisplayItem::kLayerChunk),
+ chunk_state, nullptr, IntRect(0, 150, 800, 200)),
+ IsPaintChunk(
+ 5, 6,
+ PaintChunk::Id(*content2b->Layer(), DisplayItem::kLayerChunk),
+ chunk_state, nullptr, IntRect(0, 250, 800, 100)),
+ IsPaintChunk(
+ 6, 7,
+ PaintChunk::Id(*content2a->Layer(), DisplayItem::kLayerChunk),
+ chunk_state, nullptr, IntRect(0, 150, 800, 100))));
+ }
}
TEST_P(PaintLayerPainterTest, HintedPaintChunksWithoutBackgrounds) {
@@ -629,9 +699,17 @@ TEST_P(PaintLayerPainterTest, HintedPaintChunksWithoutBackgrounds) {
ElementsAre(IsSameId(&ViewScrollingBackgroundClient(),
kDocumentBackgroundType)));
+ HitTestData scroll_hit_test;
+ scroll_hit_test.scroll_translation = &chunk_state.Transform();
+ scroll_hit_test.scroll_hit_test_rect = IntRect(0, 0, 800, 600);
EXPECT_THAT(
RootPaintController().PaintChunks(),
ElementsAre(
+ IsPaintChunk(
+ 0, 0,
+ PaintChunk::Id(GetLayoutView(), DisplayItem::kScrollHitTest),
+ GetLayoutView().FirstFragment().LocalBorderBoxProperties(),
+ &scroll_hit_test),
IsPaintChunk(0, 1,
PaintChunk::Id(ViewScrollingBackgroundClient(),
kDocumentBackgroundType),
diff --git a/chromium/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc b/chromium/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc
index 01c3537f381..3255f724c37 100644
--- a/chromium/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc
+++ b/chromium/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc
@@ -1002,6 +1002,9 @@ void PaintLayerScrollableArea::UpdateAfterLayout() {
if (NeedsScrollbarReconstruction()) {
SetHasHorizontalScrollbar(false);
SetHasVerticalScrollbar(false);
+ // In case that DelayScrollOffsetClampScope prevented destruction of the
+ // scrollbars.
+ scrollbar_manager_.DestroyDetachedScrollbars();
}
UpdateScrollDimensions();
@@ -2376,14 +2379,20 @@ void PaintLayerScrollableArea::UpdateCompositingLayersAfterScroll() {
// If we have fixed elements and we scroll the root layer we might
// change compositing since the fixed elements might now overlap a
// composited layer.
- if (!base::FeatureList::IsEnabled(
- features::kAssumeOverlapAfterFixedOrStickyPosition)) {
- if (Layer()->IsRootLayer()) {
- LocalFrame* frame = GetLayoutBox()->GetFrame();
- if (frame && frame->View() &&
- frame->View()->HasViewportConstrainedObjects()) {
+ if (Layer()->IsRootLayer()) {
+ LocalFrame* frame = GetLayoutBox()->GetFrame();
+ if (frame && frame->View()) {
+ LocalFrameView* view = frame->View();
+ // When kMaxOverlapBoundsForFixed is enabled, the maximum possible
+ // overlap (for all possible scroll offsets) of the fixed content has
+ // been included in the overlap test, so we can skip the compositing
+ // update on scroll changes for fixed content.
+ bool requires_compositing_inputs_update =
+ !base::FeatureList::IsEnabled(features::kMaxOverlapBoundsForFixed)
+ ? view->HasViewportConstrainedObjects()
+ : view->HasStickyViewportConstrainedObject();
+ if (requires_compositing_inputs_update)
Layer()->SetNeedsCompositingInputsUpdate();
- }
}
}
} else {
@@ -2459,8 +2468,7 @@ bool PaintLayerScrollableArea::ComputeNeedsCompositedScrolling(
auto old_background_paint_location = box->GetBackgroundPaintLocation();
non_composited_main_thread_scrolling_reasons_ = 0;
auto new_background_paint_location =
- box->ComputeBackgroundPaintLocationIfComposited(
- &non_composited_main_thread_scrolling_reasons_);
+ box->ComputeBackgroundPaintLocationIfComposited();
bool needs_composited_scrolling = ComputeNeedsCompositedScrollingInternal(
new_background_paint_location, force_prefer_compositing_to_lcd_text);
if (!needs_composited_scrolling)
@@ -2507,42 +2515,39 @@ bool PaintLayerScrollableArea::ComputeNeedsCompositedScrollingInternal(
bool needs_composited_scrolling = true;
- // TODO(flackr): Allow integer transforms as long as all of the ancestor
- // transforms are also integer.
- bool background_supports_lcd_text =
- box->StyleRef().IsStackingContext() &&
- (background_paint_location_if_composited &
- kBackgroundPaintInScrollingContents) &&
- layer_->BackgroundIsKnownToBeOpaqueInRect(box->PhysicalPaddingBoxRect(),
- true) &&
- !layer_->CompositesWithTransform() && !layer_->CompositesWithOpacity();
-
if (!force_prefer_compositing_to_lcd_text &&
!box->GetDocument()
.GetSettings()
- ->GetPreferCompositingToLCDTextEnabled() &&
- !background_supports_lcd_text) {
- if (layer_->CompositesWithOpacity()) {
- non_composited_main_thread_scrolling_reasons_ |=
- cc::MainThreadScrollingReason::kHasOpacityAndLCDText;
- }
+ ->GetPreferCompositingToLCDTextEnabled()) {
+ // TODO(crbug.com/1025927): We may remove this condition.
if (layer_->CompositesWithTransform()) {
non_composited_main_thread_scrolling_reasons_ |=
cc::MainThreadScrollingReason::kHasTransformAndLCDText;
+ needs_composited_scrolling = false;
}
if (!layer_->BackgroundIsKnownToBeOpaqueInRect(
box->PhysicalPaddingBoxRect(), true)) {
non_composited_main_thread_scrolling_reasons_ |=
cc::MainThreadScrollingReason::kBackgroundNotOpaqueInRectAndLCDText;
+ needs_composited_scrolling = false;
}
if (!box->StyleRef().IsStackingContext()) {
non_composited_main_thread_scrolling_reasons_ |=
cc::MainThreadScrollingReason::kIsNotStackingContextAndLCDText;
+ needs_composited_scrolling = false;
+ }
+ if (!(background_paint_location_if_composited &
+ kBackgroundPaintInScrollingContents) &&
+ box->StyleRef().HasBackground()) {
+ non_composited_main_thread_scrolling_reasons_ |=
+ cc::MainThreadScrollingReason::kCantPaintScrollingBackground;
+ needs_composited_scrolling = false;
}
-
- needs_composited_scrolling = false;
}
+ // TODO(crbug.com/645957): We may remove this condition. This is also
+ // duplicate and inconsistent with the condition in
+ // LayoutBoxModelObject::ComputeBackgroundPaintLocationIfComposited().
if (box->HasClip() || layer_->HasDescendantWithClipPath() ||
!!layer_->ClipPathAncestor()) {
non_composited_main_thread_scrolling_reasons_ |=
@@ -3164,11 +3169,15 @@ PaintLayerScrollableArea::ScrollingBackgroundDisplayItemClient::VisualRect()
if (const auto* document_element = document.documentElement()) {
if (const auto* document_element_object =
document_element->GetLayoutObject()) {
- TransformationMatrix matrix;
- document_element_object->GetTransformFromContainer(
- box, PhysicalOffset(), matrix);
- if (matrix.IsInvertible())
- result.Unite(matrix.Inverse().MapRect(result));
+ const PropertyTreeState& document_element_state =
+ document_element_object->FirstFragment().LocalBorderBoxProperties();
+ const PropertyTreeState& view_contents_state =
+ box->FirstFragment().ContentsProperties();
+ IntRect result_in_view = result;
+ GeometryMapper::SourceToDestinationRect(
+ view_contents_state.Transform(), document_element_state.Transform(),
+ result_in_view);
+ result.Unite(result_in_view);
}
}
}
diff --git a/chromium/third_party/blink/renderer/core/paint/paint_layer_scrollable_area_test.cc b/chromium/third_party/blink/renderer/core/paint/paint_layer_scrollable_area_test.cc
index da749e252a3..000716d5f62 100644
--- a/chromium/third_party/blink/renderer/core/paint/paint_layer_scrollable_area_test.cc
+++ b/chromium/third_party/blink/renderer/core/paint/paint_layer_scrollable_area_test.cc
@@ -208,6 +208,14 @@ TEST_P(PaintLayerScrollableAreaTest,
border: 5px dashed black;'>
<div class='spacer'></div>
</div>
+ <div id='box-shadow' class='scroller'
+ style='background: white; box-shadow: 10px 10px black'>
+ <div class='spacer'></div>
+ </div>
+ <div id='inset-box-shadow' class='scroller'
+ style='background: white; box-shadow: 10px 10px black inset'>
+ <div class='spacer'></div>
+ </div>
)HTML");
// #scroller1 can paint background into scrolling contents layer even with a
@@ -309,6 +317,16 @@ TEST_P(PaintLayerScrollableAreaTest,
EXPECT_EQ(
kBackgroundPaintInGraphicsLayer | kBackgroundPaintInScrollingContents,
GetBackgroundPaintLocation("scroller18"));
+
+ // Background with normal (non-inset) box shadow can be painted in the
+ // scrolling contents layer.
+ EXPECT_EQ(kBackgroundPaintInScrollingContents,
+ GetBackgroundPaintLocation("box-shadow"));
+
+ // Background with inset box shadow can only be painted in the main graphics
+ // layer because the shadow can't scroll.
+ EXPECT_EQ(kBackgroundPaintInGraphicsLayer,
+ GetBackgroundPaintLocation("inset-box-shadow"));
}
TEST_P(PaintLayerScrollableAreaTest, OpaqueContainedLayersPromoted) {
@@ -452,9 +470,8 @@ TEST_P(PaintLayerScrollableAreaTest, OnlyNonTransformedOpaqueLayersPromoted) {
EXPECT_FALSE(UsesCompositedScrolling(scroller->GetLayoutObject()));
}
-// Test that opacity applied to the scroller or an ancestor (pre-CAP only) will
-// cause the scrolling contents layer to not be promoted.
-TEST_P(PaintLayerScrollableAreaTest, OnlyOpaqueLayersPromoted) {
+TEST_P(PaintLayerScrollableAreaTest,
+ PromoteLayerRegardlessOfSelfAndAncestorOpacity) {
SetBodyInnerHTML(R"HTML(
<style>
#scroller { overflow: scroll; height: 200px; width: 200px; background:
@@ -475,12 +492,7 @@ TEST_P(PaintLayerScrollableAreaTest, OnlyOpaqueLayersPromoted) {
// Change the parent to be partially translucent.
parent->setAttribute(html_names::kStyleAttr, "opacity: 0.5;");
UpdateAllLifecyclePhasesForTest();
- // TODO(crbug.com/1025927): In CompositeAfterPaint mode, ancestor opacity
- // is not checked.
- if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
- EXPECT_TRUE(UsesCompositedScrolling(scroller->GetLayoutObject()));
- else
- EXPECT_FALSE(UsesCompositedScrolling(scroller->GetLayoutObject()));
+ EXPECT_TRUE(UsesCompositedScrolling(scroller->GetLayoutObject()));
// Change the parent to be opaque again.
parent->setAttribute(html_names::kStyleAttr, "opacity: 1;");
@@ -492,7 +504,7 @@ TEST_P(PaintLayerScrollableAreaTest, OnlyOpaqueLayersPromoted) {
// Make the scroller translucent.
scroller->setAttribute(html_names::kStyleAttr, "opacity: 0.5");
UpdateAllLifecyclePhasesForTest();
- EXPECT_FALSE(UsesCompositedScrolling(scroller->GetLayoutObject()));
+ EXPECT_TRUE(UsesCompositedScrolling(scroller->GetLayoutObject()));
}
// Test that will-change: transform applied to the scroller will cause the
@@ -892,6 +904,87 @@ TEST_P(PaintLayerScrollableAreaTest, ScrollDoesNotInvalidate) {
}
TEST_P(PaintLayerScrollableAreaTest,
+ ScrollWithFixedNeedsCompositingInputsUpdate) {
+ base::test::ScopedFeatureList feature_list;
+ feature_list.InitWithFeatureState(blink::features::kMaxOverlapBoundsForFixed,
+ false);
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ * {
+ margin: 0;
+ }
+ body {
+ height: 610px;
+ width: 820px;
+ }
+ #fixed {
+ height: 10px;
+ left: 50px;
+ position: fixed;
+ top: 50px;
+ width: 10px;
+ }
+ </style>
+ <div id=fixed></div>
+ )HTML");
+
+ auto* scrollable_area = GetLayoutView().GetScrollableArea();
+ EXPECT_EQ(FloatSize(0, 0), scrollable_area->GetScrollOffset());
+
+ // Changing the scroll offset requires a compositing inputs update when
+ // kMaxOverlapBoundsForFixed is disabled as changing the scroll offset can
+ // require updates to overlap testing.
+ scrollable_area->SetScrollOffset(ScrollOffset(0, 1),
+ mojom::blink::ScrollType::kProgrammatic);
+ if (GetParam() & kCompositeAfterPaint) {
+ // CAP doesn't request compositing inputs update on scroll offset changes.
+ EXPECT_FALSE(scrollable_area->Layer()->NeedsCompositingInputsUpdate());
+ } else {
+ EXPECT_TRUE(scrollable_area->Layer()->NeedsCompositingInputsUpdate());
+ }
+ UpdateAllLifecyclePhasesForTest();
+ EXPECT_EQ(FloatSize(0, 1), scrollable_area->GetScrollOffset());
+}
+
+TEST_P(PaintLayerScrollableAreaTest,
+ ScrollWithFixedDoesNotNeedCompositingInputsUpdate) {
+ base::test::ScopedFeatureList feature_list;
+ feature_list.InitWithFeatureState(blink::features::kMaxOverlapBoundsForFixed,
+ true);
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ * {
+ margin: 0;
+ }
+ body {
+ height: 610px;
+ width: 820px;
+ }
+ #fixed {
+ height: 10px;
+ left: 50px;
+ position: fixed;
+ top: 50px;
+ width: 10px;
+ }
+ </style>
+ <div id=fixed></div>
+ )HTML");
+
+ auto* scrollable_area = GetLayoutView().GetScrollableArea();
+ EXPECT_EQ(FloatSize(0, 0), scrollable_area->GetScrollOffset());
+
+ // Changing the scroll offset should not require compositing inputs update
+ // even though fixed-pos content is present as fixed bounds is already
+ // expanded to include all possible scroll offsets.
+ scrollable_area->SetScrollOffset(ScrollOffset(0, 1),
+ mojom::blink::ScrollType::kProgrammatic);
+ EXPECT_FALSE(scrollable_area->Layer()->NeedsCompositingInputsUpdate());
+ UpdateAllLifecyclePhasesForTest();
+ EXPECT_EQ(FloatSize(0, 1), scrollable_area->GetScrollOffset());
+}
+
+TEST_P(PaintLayerScrollableAreaTest,
ScrollWithLocalAttachmentBackgroundInScrollingContents) {
SetBodyInnerHTML(R"HTML(
<style>
@@ -1486,15 +1579,18 @@ TEST_P(PaintLayerScrollableAreaTest, SetSnapContainerDataNeedsUpdate) {
class ScrollTimelineForTest : public ScrollTimeline {
public:
- ScrollTimelineForTest(
- Document* document,
- Element* scroll_source,
- CSSPrimitiveValue* start_scroll_offset =
- CSSNumericLiteralValue::Create(10.0,
- CSSPrimitiveValue::UnitType::kPixels),
- CSSPrimitiveValue* end_scroll_offset =
- CSSNumericLiteralValue::Create(90.0,
- CSSPrimitiveValue::UnitType::kPixels))
+ ScrollTimelineForTest(Document* document,
+ Element* scroll_source,
+ ScrollTimelineOffset* start_scroll_offset =
+ MakeGarbageCollected<ScrollTimelineOffset>(
+ CSSNumericLiteralValue::Create(
+ 10.0,
+ CSSPrimitiveValue::UnitType::kPixels)),
+ ScrollTimelineOffset* end_scroll_offset =
+ MakeGarbageCollected<ScrollTimelineOffset>(
+ CSSNumericLiteralValue::Create(
+ 90.0,
+ CSSPrimitiveValue::UnitType::kPixels)))
: ScrollTimeline(document,
scroll_source,
ScrollTimeline::Vertical,
diff --git a/chromium/third_party/blink/renderer/core/paint/paint_layer_test.cc b/chromium/third_party/blink/renderer/core/paint/paint_layer_test.cc
index f0dc94a3304..0a92e59cf2f 100644
--- a/chromium/third_party/blink/renderer/core/paint/paint_layer_test.cc
+++ b/chromium/third_party/blink/renderer/core/paint/paint_layer_test.cc
@@ -4,7 +4,9 @@
#include "third_party/blink/renderer/core/paint/paint_layer.h"
+#include "base/test/scoped_feature_list.h"
#include "testing/gmock/include/gmock/gmock.h"
+#include "third_party/blink/public/common/features.h"
#include "third_party/blink/renderer/core/dom/pseudo_element.h"
#include "third_party/blink/renderer/core/html/html_iframe_element.h"
#include "third_party/blink/renderer/core/layout/layout_box_model_object.h"
@@ -2615,4 +2617,271 @@ TEST_P(PaintLayerTest, InlineWithBackdropFilterHasPaintLayer) {
EXPECT_NE(nullptr, paint_layer);
}
+TEST_P(PaintLayerTest, FixedDoesNotUseExpandedBoundingBoxForOverlap) {
+ // TODO(samfort): Remove this test after kMaxOverlapBoundsForFixed ships.
+ base::test::ScopedFeatureList feature_list;
+ feature_list.InitWithFeatureState(blink::features::kMaxOverlapBoundsForFixed,
+ false);
+
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ * {
+ margin: 0;
+ }
+ body {
+ height: 610px;
+ width: 820px;
+ }
+ #fixed {
+ height: 10px;
+ left: 50px;
+ position: fixed;
+ top: 50px;
+ width: 10px;
+ }
+ </style>
+ <div id=fixed></div>
+ )HTML");
+
+ PaintLayer* fixed =
+ ToLayoutBoxModelObject(GetLayoutObjectByElementId("fixed"))->Layer();
+ EXPECT_EQ(fixed->BoundingBoxForCompositingOverlapTest(),
+ PhysicalRect(0, 0, 10, 10));
+
+ // Modify the scroll offset and ensure that the bounding box is still the
+ // same.
+ GetDocument().View()->LayoutViewport()->SetScrollOffset(
+ ScrollOffset(10, 10), mojom::blink::ScrollType::kProgrammatic);
+ UpdateAllLifecyclePhasesForTest();
+
+ EXPECT_EQ(fixed->BoundingBoxForCompositingOverlapTest(),
+ PhysicalRect(0, 0, 10, 10));
+}
+
+TEST_P(PaintLayerTest, FixedUsesExpandedBoundingBoxForOverlap) {
+ base::test::ScopedFeatureList feature_list;
+ feature_list.InitWithFeatureState(blink::features::kMaxOverlapBoundsForFixed,
+ true);
+
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ * {
+ margin: 0;
+ }
+ body {
+ height: 610px;
+ width: 820px;
+ }
+ #fixed {
+ height: 10px;
+ left: 50px;
+ position: fixed;
+ top: 50px;
+ width: 10px;
+ }
+ </style>
+ <div id=fixed></div>
+ )HTML");
+
+ PaintLayer* fixed =
+ ToLayoutBoxModelObject(GetLayoutObjectByElementId("fixed"))->Layer();
+ EXPECT_EQ(fixed->BoundingBoxForCompositingOverlapTest(),
+ PhysicalRect(0, 0, 30, 20));
+
+ // Modify the viewport scroll offset and ensure that the bounding box is still
+ // adjusted by the new amount the viewport can scroll in any direction.
+ GetDocument().View()->LayoutViewport()->SetScrollOffset(
+ ScrollOffset(10, 10), mojom::blink::ScrollType::kProgrammatic);
+ UpdateAllLifecyclePhasesForTest();
+
+ EXPECT_EQ(fixed->BoundingBoxForCompositingOverlapTest(),
+ PhysicalRect(-10, -10, 30, 20));
+}
+
+TEST_P(PaintLayerTest, FixedInScrollerUsesExpandedBoundingBoxForOverlap) {
+ base::test::ScopedFeatureList feature_list;
+ feature_list.InitWithFeatureState(blink::features::kMaxOverlapBoundsForFixed,
+ true);
+
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ * {
+ margin: 0;
+ }
+ body {
+ height: 610px;
+ width: 820px;
+ }
+ #scroller {
+ height: 100px;
+ left: 100px;
+ overflow: scroll;
+ position: absolute;
+ top: 100px;
+ width: 100px;
+ }
+ #spacer {
+ height: 500px;
+ }
+ #fixed {
+ height: 10px;
+ left: 50px;
+ position: fixed;
+ top: 50px;
+ width: 10px;
+ }
+ </style>
+ <div id=scroller>
+ <div id=fixed></div>
+ <div id=spacer></div>
+ </div>
+ )HTML");
+
+ PaintLayer* fixed =
+ ToLayoutBoxModelObject(GetLayoutObjectByElementId("fixed"))->Layer();
+ EXPECT_EQ(fixed->BoundingBoxForCompositingOverlapTest(),
+ PhysicalRect(0, 0, 30, 20));
+
+ // Modify the inner scroll offset and ensure that the bounding box is still
+ // the same.
+ PaintLayerScrollableArea* scrollable_area =
+ ToLayoutBoxModelObject(GetLayoutObjectByElementId("scroller"))
+ ->Layer()
+ ->GetScrollableArea();
+ scrollable_area->ScrollToAbsolutePosition(FloatPoint(10, 10));
+ UpdateAllLifecyclePhasesForTest();
+
+ EXPECT_EQ(fixed->BoundingBoxForCompositingOverlapTest(),
+ PhysicalRect(0, 0, 30, 20));
+
+ // Modify the viewport scroll offset and ensure that the bounding box is still
+ // adjusted by the newamount the viewport can scroll in any direction.
+ GetDocument().View()->LayoutViewport()->SetScrollOffset(
+ ScrollOffset(10, 10), mojom::blink::ScrollType::kProgrammatic);
+ UpdateAllLifecyclePhasesForTest();
+
+ EXPECT_EQ(fixed->BoundingBoxForCompositingOverlapTest(),
+ PhysicalRect(-10, -10, 30, 20));
+}
+
+TEST_P(PaintLayerTest, FixedUnderTransformDoesNotExpandBoundingBoxForOverlap) {
+ base::test::ScopedFeatureList feature_list;
+ feature_list.InitWithFeatureState(blink::features::kMaxOverlapBoundsForFixed,
+ true);
+
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ .anim {
+ animation: pulse 5s infinite;
+ }
+ @keyframes pulse {
+ 0% { opacity: 0.1; }
+ 100% { opacity: 0.9; }
+ }
+ .xform {
+ height: 100px;
+ left: 100px;
+ position: absolute;
+ top: 100px;
+ transform: rotate(20deg);
+ width: 100px;
+ }
+ .fixed {
+ height: 50px;
+ left: 25px;
+ position: fixed;
+ top: 25px;
+ width: 50px;
+ }
+ .spacer {
+ height: 2000px;
+ }
+ </style>
+ <div id=fixed-cb class=xform>
+ <div id=fixed class='fixed anim'></div>
+ </div>
+ <div class=spacer></div>
+ )HTML");
+
+ // The animation is to cause the fixed to be composited. However, even with
+ // fixed composited, it shouldn't have expanded bounds because its containing
+ // block isn't the viewport.
+ PaintLayer* fixed =
+ ToLayoutBoxModelObject(GetLayoutObjectByElementId("fixed"))->Layer();
+ EXPECT_EQ(fixed->BoundingBoxForCompositingOverlapTest(),
+ PhysicalRect(0, 0, 50, 50));
+}
+
+TEST_P(PaintLayerTest, NestedFixedUsesExpandedBoundingBoxForOverlap) {
+ base::test::ScopedFeatureList feature_list;
+ feature_list.InitWithFeatureState(blink::features::kMaxOverlapBoundsForFixed,
+ true);
+
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ * {
+ margin: 0;
+ }
+ body {
+ height: 610px;
+ width: 820px;
+ }
+ #iframe1 {
+ height: 100px;
+ left: 50px;
+ position: fixed;
+ top: 50px;
+ width: 100px;
+ }
+ </style>
+ <iframe id=iframe1></iframe>
+ )HTML");
+ SetChildFrameHTML(R"HTML(
+ <style>
+ * {
+ margin: 0;
+ }
+ body {
+ height: 500px;
+ width: 500px;
+ }
+ #fixed {
+ height: 10px;
+ left: 50px;
+ position: fixed;
+ top: 50px;
+ width: 10px;
+ }
+ </style>
+ <div id=fixed></div>
+ )HTML");
+ UpdateAllLifecyclePhasesForTest();
+
+ PaintLayer* fixed =
+ ToLayoutBoxModelObject(
+ ChildDocument().getElementById("fixed")->GetLayoutObject())
+ ->Layer();
+ EXPECT_EQ(fixed->BoundingBoxForCompositingOverlapTest(),
+ PhysicalRect(0, 0, 410, 410));
+
+ // Modify the top-most viewport's scroll offset and ensure that the bounding
+ // box is still the same. This shows that we're not considering the wrong
+ // viewport's scroll offset when computing the bounding box.
+ GetDocument().View()->LayoutViewport()->SetScrollOffset(
+ ScrollOffset(10, 10), mojom::blink::ScrollType::kProgrammatic);
+ UpdateAllLifecyclePhasesForTest();
+
+ EXPECT_EQ(fixed->BoundingBoxForCompositingOverlapTest(),
+ PhysicalRect(0, 0, 410, 410));
+
+ // Now modify the iframe's scroll offset. This one should affect the fixed's
+ // bounding box.
+ ChildDocument().View()->LayoutViewport()->SetScrollOffset(
+ ScrollOffset(10, 10), mojom::blink::ScrollType::kProgrammatic);
+ UpdateAllLifecyclePhasesForTest();
+
+ EXPECT_EQ(fixed->BoundingBoxForCompositingOverlapTest(),
+ PhysicalRect(-10, -10, 410, 410));
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc b/chromium/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc
index 6810fb3e4f7..5249eba7361 100644
--- a/chromium/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc
+++ b/chromium/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc
@@ -260,6 +260,12 @@ class FragmentPaintPropertyTreeBuilder {
full_context_.clip_changed |= cleared;
}
+ CompositorElementId GetCompositorElementId(
+ CompositorElementIdNamespace namespace_id) const {
+ return CompositorElementIdFromUniqueObjectId(fragment_data_.UniqueId(),
+ namespace_id);
+ }
+
const LayoutObject& object_;
NGPrePaintInfo* pre_paint_info_;
// The tree builder context for the whole object.
@@ -534,6 +540,10 @@ void FragmentPaintPropertyTreeBuilder::UpdateStickyTranslation() {
const auto& box_model = ToLayoutBoxModelObject(object_);
TransformPaintPropertyNode::State state{
FloatSize(box_model.StickyPositionOffset())};
+ // TODO(wangxianzhu): Not using GetCompositorElementId() here because
+ // sticky elements don't work properly under multicol for now, to keep
+ // consistency with CompositorElementIdFromUniqueObjectId() below.
+ // This will be fixed by LayoutNG block fragments.
state.compositor_element_id = CompositorElementIdFromUniqueObjectId(
box_model.UniqueId(),
CompositorElementIdNamespace::kStickyTranslation);
@@ -692,11 +702,12 @@ static CompositingReasons CompositingReasonsForTransformProperty() {
// property instead of creating all nodes and only create a transform/
// effect/filter node if needed.
reasons |= CompositingReason::kComboActiveAnimation;
- // We also need to create transform node if the opacity node is created for
- // will-change:opacity to avoid raster invalidation (caused by otherwise a
- // created/deleted effect node) when we start/stop an opacity animation.
- // https://crbug.com/942681
+ // We also need to create a transform node if will-change creates other nodes,
+ // to avoid raster invalidation caused by creating/deleting those nodes when
+ // starting/stopping an animation. See: https://crbug.com/942681.
reasons |= CompositingReason::kWillChangeOpacity;
+ reasons |= CompositingReason::kWillChangeFilter;
+ reasons |= CompositingReason::kWillChangeBackdropFilter;
return reasons;
}
@@ -801,8 +812,8 @@ void FragmentPaintPropertyTreeBuilder::UpdateTransform() {
object_.HasHiddenBackface()
? TransformPaintPropertyNode::BackfaceVisibility::kHidden
: TransformPaintPropertyNode::BackfaceVisibility::kVisible;
- state.compositor_element_id = CompositorElementIdFromUniqueObjectId(
- object_.UniqueId(), CompositorElementIdNamespace::kPrimaryTransform);
+ state.compositor_element_id = GetCompositorElementId(
+ CompositorElementIdNamespace::kPrimaryTransform);
TransformPaintPropertyNode::AnimationState animation_state;
animation_state.is_running_animation_on_compositor =
@@ -865,13 +876,13 @@ static CompositingReasons CompositingReasonsForEffectProperty() {
// property instead of creating all nodes and only create a transform/
// effect/filter node if needed.
reasons |= CompositingReason::kComboActiveAnimation;
- // We also need to create effect node if the transform node is created for
- // will-change:transform to avoid raster invalidation (caused by otherwise a
- // created/deleted effect node) when we start/stop a transform animation.
- // https://crbug.com/942681
+ // We also need to create an effect node if will-change creates other nodes,
+ // to avoid raster invalidation caused by creating/deleting those nodes when
+ // starting/stopping an animation. See: https://crbug.com/942681.
// In CompositeAfterPaint, this also avoids decomposition of the effect when
// the object is forced compositing with will-change:transform.
reasons |= CompositingReason::kWillChangeTransform;
+ reasons |= CompositingReason::kWillChangeFilter;
return reasons;
}
@@ -1045,8 +1056,8 @@ void FragmentPaintPropertyTreeBuilder::UpdateEffect() {
CompositorElementId mask_compositor_element_id;
if (mask_clip || has_spv1_composited_clip_path) {
- mask_compositor_element_id = CompositorElementIdFromUniqueObjectId(
- object_.UniqueId(), CompositorElementIdNamespace::kEffectMask);
+ mask_compositor_element_id =
+ GetCompositorElementId(CompositorElementIdNamespace::kEffectMask);
}
EffectPaintPropertyNode::State state;
@@ -1083,15 +1094,15 @@ void FragmentPaintPropertyTreeBuilder::UpdateEffect() {
full_context_.direct_compositing_reasons &
CompositingReasonsForEffectProperty();
if (state.direct_compositing_reasons) {
- state.compositor_element_id = CompositorElementIdFromUniqueObjectId(
- object_.UniqueId(), CompositorElementIdNamespace::kPrimaryEffect);
+ state.compositor_element_id = GetCompositorElementId(
+ CompositorElementIdNamespace::kPrimaryEffect);
} else {
// The effect node CompositorElementId is used to uniquely identify
// renderpasses so even if we don't need one for animations we still
// need to set an id. Using kPrimary avoids confusing cc::Animation
// into thinking the element has been composited for animations.
- state.compositor_element_id = CompositorElementIdFromUniqueObjectId(
- object_.UniqueId(), CompositorElementIdNamespace::kPrimary);
+ state.compositor_element_id =
+ GetCompositorElementId(CompositorElementIdNamespace::kPrimary);
}
// TODO(crbug.com/900241): Remove these setters when we can use
@@ -1148,10 +1159,8 @@ void FragmentPaintPropertyTreeBuilder::UpdateEffect() {
clip_path_state.local_transform_space = context_.current.transform;
clip_path_state.output_clip = output_clip;
clip_path_state.blend_mode = SkBlendMode::kDstIn;
- clip_path_state.compositor_element_id =
- CompositorElementIdFromUniqueObjectId(
- object_.UniqueId(),
- CompositorElementIdNamespace::kEffectClipPath);
+ clip_path_state.compositor_element_id = GetCompositorElementId(
+ CompositorElementIdNamespace::kEffectClipPath);
OnUpdate(
properties_->UpdateClipPath(parent, std::move(clip_path_state)));
} else {
@@ -1189,14 +1198,15 @@ static CompositingReasons CompositingReasonsForFilterProperty() {
// property instead of creating all nodes and only create a transform/
// effect/filter node if needed.
reasons |= CompositingReason::kComboActiveAnimation;
- // We also need to create filter node if the transform/effect node is
- // created for will-change:transform/opacity to avoid raster invalidation
- // (caused by otherwise a created/deleted filter node) when we start/stop a
- // transform/opacity animation. https://crbug.com/942681
+
+ // We also need to create a filter node if will-change creates other nodes,
+ // to avoid raster invalidation caused by creating/deleting those nodes when
+ // starting/stopping an animation. See: https://crbug.com/942681.
// In CompositeAfterPaint, this also avoids decomposition of the filter when
- // the object is forced compositing with will-change:transform/opacity.
+ // the object is forced compositing with will-change.
reasons |= CompositingReason::kWillChangeTransform |
- CompositingReason::kWillChangeOpacity;
+ CompositingReason::kWillChangeOpacity |
+ CompositingReason::kWillChangeBackdropFilter;
return reasons;
}
@@ -1265,8 +1275,8 @@ void FragmentPaintPropertyTreeBuilder::UpdateFilter() {
state.direct_compositing_reasons =
full_context_.direct_compositing_reasons &
CompositingReasonsForFilterProperty();
- state.compositor_element_id = CompositorElementIdFromUniqueObjectId(
- object_.UniqueId(), CompositorElementIdNamespace::kEffectFilter);
+ state.compositor_element_id =
+ GetCompositorElementId(CompositorElementIdNamespace::kEffectFilter);
// TODO(crbug.com/900241): Remove the setter when we can use
// state.direct_compositing_reasons to check for active animations.
@@ -2250,6 +2260,11 @@ void FragmentPaintPropertyTreeBuilder::UpdatePaintOffset() {
// offset transform for paint_offset_root.
!context_.current.paint_offset_root->PaintingLayer()
->EnclosingPaginationLayer()) {
+ if (object_.StyleRef().GetPosition() == EPosition::kAbsolute)
+ context_.current = context_.absolute_position;
+ else if (object_.StyleRef().GetPosition() == EPosition::kFixed)
+ context_.current = context_.fixed_position;
+
// Set fragment visual paint offset.
PhysicalOffset paint_offset = PaintOffsetInPaginationContainer(
object_, *enclosing_pagination_layer);
@@ -3004,6 +3019,7 @@ PaintPropertyTreeBuilder::ContextForFragment(
// This will be used in the loop finding matching fragment from ancestor flow
// threads after no matching from parent_fragments.
LayoutUnit logical_top_in_containing_flow_thread;
+ bool crossed_flow_thread = false;
if (object_.IsLayoutFlowThread()) {
const auto& flow_thread = ToLayoutFlowThread(object_);
@@ -3022,6 +3038,7 @@ PaintPropertyTreeBuilder::ContextForFragment(
return context;
}
}
+ crossed_flow_thread = true;
} else {
bool parent_is_under_same_flow_thread;
auto* pagination_layer =
@@ -3054,6 +3071,7 @@ PaintPropertyTreeBuilder::ContextForFragment(
}
logical_top_in_containing_flow_thread = logical_top_in_flow_thread;
+ crossed_flow_thread = !parent_is_under_same_flow_thread;
}
// Found no matching parent fragment. Use parent_fragments[0] to inherit
@@ -3073,19 +3091,41 @@ PaintPropertyTreeBuilder::ContextForFragment(
// For each case, we need to adjust context.current.clip. For now it's the
// first parent fragment's FragmentClip which is not the correct clip for
// object_.
+ const ClipPaintPropertyNode* found_clip = nullptr;
for (const auto* container = object_.Container(); container;
container = container->Container()) {
if (!container->FirstFragment().HasLocalBorderBoxProperties())
continue;
- for (const auto* fragment = &container->FirstFragment(); fragment;
- fragment = fragment->NextFragment()) {
- if (fragment->LogicalTopInFlowThread() ==
- logical_top_in_containing_flow_thread) {
- // Found a matching fragment in an ancestor container. Use the
- // container's content clip as the clip state.
- context.current.clip = &fragment->PostOverflowClip();
- return context;
+ const FragmentData* container_fragment = &container->FirstFragment();
+ while (container_fragment->LogicalTopInFlowThread() <
+ logical_top_in_containing_flow_thread &&
+ container_fragment->NextFragment())
+ container_fragment = container_fragment->NextFragment();
+
+ if (container_fragment->LogicalTopInFlowThread() ==
+ logical_top_in_containing_flow_thread) {
+ // Found a matching fragment in an ancestor container. Use the
+ // container's content clip as the clip state.
+ found_clip = &container_fragment->PostOverflowClip();
+ break;
+ }
+
+ // We didn't find corresponding fragment in the container because the
+ // fragment fully overflows the container. If the container has overflow
+ // clip, then this fragment should be under |container_fragment|.
+ // This works only when the current fragment and the overflow clip are under
+ // the same flow thread. In other cases, we just leave it broken, which will
+ // be fixed by LayoutNG block fragments hopefully.
+ if (!crossed_flow_thread) {
+ if (const auto* container_properties =
+ container_fragment->PaintProperties()) {
+ if (const auto* overflow_clip = container_properties->OverflowClip()) {
+ context.logical_top_in_flow_thread =
+ container_fragment->LogicalTopInFlowThread();
+ found_clip = overflow_clip;
+ break;
+ }
}
}
@@ -3094,6 +3134,7 @@ PaintPropertyTreeBuilder::ContextForFragment(
FragmentLogicalTopInParentFlowThread(
ToLayoutFlowThread(*container),
logical_top_in_containing_flow_thread);
+ crossed_flow_thread = true;
}
}
@@ -3101,7 +3142,15 @@ PaintPropertyTreeBuilder::ContextForFragment(
// because logical_top_in_containing_flow_thread will be zero when we traverse
// across the top-level flow thread and it should match the first fragment of
// a non-fragmented ancestor container.
- NOTREACHED();
+ DCHECK(found_clip);
+
+ if (!crossed_flow_thread)
+ context.fragment_clip = base::nullopt;
+ context.current.clip = found_clip;
+ if (object_.StyleRef().GetPosition() == EPosition::kAbsolute)
+ context.absolute_position.clip = found_clip;
+ else if (object_.StyleRef().GetPosition() == EPosition::kFixed)
+ context.fixed_position.clip = found_clip;
return context;
}
@@ -3178,8 +3227,16 @@ void PaintPropertyTreeBuilder::CreateFragmentContextsInFlowThread(
}
// Match to parent fragments from the same containing flow thread.
- new_fragment_contexts.push_back(
- ContextForFragment(fragment_clip, logical_top_in_flow_thread));
+ auto fragment_context =
+ ContextForFragment(fragment_clip, logical_top_in_flow_thread);
+ // ContextForFragment may override logical_top_in_flow_thread.
+ logical_top_in_flow_thread = fragment_context.logical_top_in_flow_thread;
+ // Avoid fragment with duplicated overridden logical_top_in_flow_thread.
+ if (new_fragment_contexts.size() &&
+ new_fragment_contexts.back().logical_top_in_flow_thread ==
+ logical_top_in_flow_thread)
+ break;
+ new_fragment_contexts.push_back(fragment_context);
if (current_fragment_data) {
if (!current_fragment_data->NextFragment())
diff --git a/chromium/third_party/blink/renderer/core/paint/paint_property_tree_builder_test.cc b/chromium/third_party/blink/renderer/core/paint/paint_property_tree_builder_test.cc
index 1805b3db5f4..b72bed915f5 100644
--- a/chromium/third_party/blink/renderer/core/paint/paint_property_tree_builder_test.cc
+++ b/chromium/third_party/blink/renderer/core/paint/paint_property_tree_builder_test.cc
@@ -4322,11 +4322,34 @@ TEST_P(PaintPropertyTreeBuilderTest, LayerUnderOverflowClipUnderMultiColumn) {
EXPECT_EQ(1u, NumFragments(GetLayoutObjectByElementId("layer")));
}
-TEST_P(PaintPropertyTreeBuilderTest, CompositedUnderMultiColumn) {
- // TODO(crbug.com/1064341): This test crashes in CompositeAfterPaint. Fix it.
- if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
- return;
+TEST_P(PaintPropertyTreeBuilderTest, OverflowClipUnderMultiColumn) {
+ SetBodyInnerHTML(R"HTML(
+ <style>body { margin: 0; }</style>
+ <div style='columns: 4; height: 100px; column-fill: auto; column-gap: 0'>
+ <div id='clip' style='height: 200px; overflow: hidden'>
+ <div id='child1' style='height: 400px'></div>
+ <div id='child2' style='height: 400px'></div>
+ </div>
+ </div>
+ )HTML");
+
+ const auto* clip = GetLayoutObjectByElementId("clip");
+ ASSERT_EQ(2u, NumFragments(clip));
+ EXPECT_EQ(LayoutUnit(), FragmentAt(clip, 0).LogicalTopInFlowThread());
+ EXPECT_EQ(LayoutUnit(100), FragmentAt(clip, 1).LogicalTopInFlowThread());
+ const auto* child1 = GetLayoutObjectByElementId("child1");
+ ASSERT_EQ(2u, NumFragments(child1));
+ EXPECT_EQ(LayoutUnit(), FragmentAt(child1, 0).LogicalTopInFlowThread());
+ EXPECT_EQ(PhysicalOffset(), FragmentAt(child1, 0).PaintOffset());
+ EXPECT_EQ(LayoutUnit(100), FragmentAt(child1, 1).LogicalTopInFlowThread());
+ EXPECT_EQ(PhysicalOffset(200, -100), FragmentAt(child1, 1).PaintOffset());
+ const auto* child2 = GetLayoutObjectByElementId("child2");
+ ASSERT_EQ(1u, NumFragments(child2));
+ EXPECT_EQ(LayoutUnit(100), FragmentAt(child2, 0).LogicalTopInFlowThread());
+ EXPECT_EQ(PhysicalOffset(200, 300), FragmentAt(child2, 0).PaintOffset());
+}
+TEST_P(PaintPropertyTreeBuilderTest, CompositedUnderMultiColumn) {
SetBodyInnerHTML(R"HTML(
<style>body { margin: 0; }</style>
<div id='multicol' style='columns:3; column-fill:auto; column-gap: 0;
@@ -4475,10 +4498,6 @@ TEST_P(PaintPropertyTreeBuilderTest, FrameUnderMulticol) {
}
TEST_P(PaintPropertyTreeBuilderTest, CompositedMulticolFrameUnderMulticol) {
- // TODO(crbug.com/1064341): This test crashes in CompositeAfterPaint. Fix it.
- if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
- return;
-
SetBodyInnerHTML(R"HTML(
<style>body { margin: 0 }</style>
<div style='columns: 3; column-gap: 0; column-fill: auto;
@@ -5627,10 +5646,6 @@ TEST_P(PaintPropertyTreeBuilderTest, CompositedLayerSkipsFragmentClip) {
}
TEST_P(PaintPropertyTreeBuilderTest, CompositedLayerUnderClipUnderMulticol) {
- // TODO(crbug.com/1064341): This test crashes in CompositeAfterPaint. Fix it.
- if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
- return;
-
SetBodyInnerHTML(R"HTML(
<div id="multicol" style="columns: 2">
<div id="clip" style="height: 100px; overflow: hidden">
@@ -6744,4 +6759,48 @@ TEST_P(PaintPropertyTreeBuilderTest, CompositedInline) {
EXPECT_TRUE(properties->Transform()->HasDirectCompositingReasons());
}
+TEST_P(PaintPropertyTreeBuilderTest, OutOfFlowContainedInMulticol) {
+ SetBodyInnerHTML(R"HTML(
+ <div id="columns" style="columns: 2; height: 100px">
+ <div id="relative"
+ style="position: relative; height: 200px; transform: translateX(0)">
+ <div style="overflow: scroll">
+ <div id="absolute"
+ style="position: absolute; width: 100%; height: 200px"></div>
+ <div id="fixed"
+ style="position: fixed; width: 100%; height: 200px"></div>
+ </div>
+ </div>
+ </div>
+ )HTML");
+
+ const auto* flow_thread =
+ GetLayoutObjectByElementId("columns")->SlowFirstChild();
+ ASSERT_EQ(2u, NumFragments(flow_thread));
+ const auto* relative = GetLayoutObjectByElementId("relative");
+ ASSERT_EQ(2u, NumFragments(relative));
+ const auto* absolute = GetLayoutObjectByElementId("absolute");
+ ASSERT_EQ(2u, NumFragments(absolute));
+ const auto* fixed = GetLayoutObjectByElementId("fixed");
+ ASSERT_EQ(2u, NumFragments(fixed));
+
+ // For now we use the container's first fragment's transform as the parent of
+ // the transforms of all fragments of out-of-flow descendants.
+ const auto* relative_transform =
+ FragmentAt(relative, 0).PaintProperties()->Transform();
+ for (unsigned i = 0; i < NumFragments(flow_thread); i++) {
+ SCOPED_TRACE(testing::Message() << "Fragment " << i);
+ const auto* fragment_clip =
+ FragmentAt(flow_thread, i).PaintProperties()->FragmentClip();
+ const auto& absolute_properties =
+ FragmentAt(absolute, i).LocalBorderBoxProperties();
+ const auto& fixed_properties =
+ FragmentAt(fixed, i).LocalBorderBoxProperties();
+ EXPECT_EQ(fragment_clip, &absolute_properties.Clip());
+ EXPECT_EQ(fragment_clip, &fixed_properties.Clip());
+ EXPECT_EQ(relative_transform, &absolute_properties.Transform());
+ EXPECT_EQ(relative_transform, &fixed_properties.Transform());
+ }
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/paint_timing.cc b/chromium/third_party/blink/renderer/core/paint/paint_timing.cc
index 6e7140526b6..f3ea3825c3b 100644
--- a/chromium/third_party/blink/renderer/core/paint/paint_timing.cc
+++ b/chromium/third_party/blink/renderer/core/paint/paint_timing.cc
@@ -21,6 +21,7 @@
#include "third_party/blink/renderer/core/timing/dom_window_performance.h"
#include "third_party/blink/renderer/core/timing/window_performance.h"
#include "third_party/blink/renderer/platform/instrumentation/histogram.h"
+#include "third_party/blink/renderer/platform/instrumentation/resource_coordinator/document_resource_coordinator.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
#include "third_party/blink/renderer/platform/scheduler/public/frame_scheduler.h"
#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
@@ -168,12 +169,11 @@ void PaintTiming::SetFirstContentfulPaint(base::TimeTicks stamp) {
void PaintTiming::RegisterNotifySwapTime(PaintEvent event) {
RegisterNotifySwapTime(
- event, CrossThreadBindOnce(&PaintTiming::ReportSwapTime,
- WrapCrossThreadWeakPersistent(this), event));
+ CrossThreadBindOnce(&PaintTiming::ReportSwapTime,
+ WrapCrossThreadWeakPersistent(this), event));
}
-void PaintTiming::RegisterNotifySwapTime(PaintEvent event,
- ReportTimeCallback callback) {
+void PaintTiming::RegisterNotifySwapTime(ReportTimeCallback callback) {
// ReportSwapTime will queue a swap-promise, the callback is called when the
// compositor submission of the current render frame completes or fails to
// happen.
@@ -245,6 +245,12 @@ void PaintTiming::SetFirstContentfulPaintSwap(base::TimeTicks stamp) {
if (interactive_detector) {
interactive_detector->OnFirstContentfulPaint(first_contentful_paint_swap_);
}
+ auto* coordinator = GetSupplementable()->GetResourceCoordinator();
+ if (coordinator && GetFrame() && GetFrame()->IsMainFrame()) {
+ PerformanceTiming* timing = performance->timing();
+ base::TimeDelta fcp = stamp - timing->NavigationStartAsMonotonicTime();
+ coordinator->OnFirstContentfulPaint(fcp);
+ }
}
void PaintTiming::SetFirstImagePaintSwap(base::TimeTicks stamp) {
diff --git a/chromium/third_party/blink/renderer/core/paint/paint_timing.h b/chromium/third_party/blink/renderer/core/paint/paint_timing.h
index 61e4358f997..cf47d323ac1 100644
--- a/chromium/third_party/blink/renderer/core/paint/paint_timing.h
+++ b/chromium/third_party/blink/renderer/core/paint/paint_timing.h
@@ -97,7 +97,7 @@ class CORE_EXPORT PaintTiming final : public GarbageCollected<PaintTiming>,
return *fmp_detector_;
}
- void RegisterNotifySwapTime(PaintEvent, ReportTimeCallback);
+ void RegisterNotifySwapTime(ReportTimeCallback);
void ReportSwapTime(PaintEvent, WebSwapResult, base::TimeTicks timestamp);
void ReportSwapResultHistogram(WebSwapResult);
diff --git a/chromium/third_party/blink/renderer/core/paint/paint_timing_detector.cc b/chromium/third_party/blink/renderer/core/paint/paint_timing_detector.cc
index a5940c4d407..60f259f22eb 100644
--- a/chromium/third_party/blink/renderer/core/paint/paint_timing_detector.cc
+++ b/chromium/third_party/blink/renderer/core/paint/paint_timing_detector.cc
@@ -63,8 +63,6 @@ bool IsBackgroundImageContentful(const LayoutObject& object,
} // namespace
-bool IgnorePaintTimingScope::should_ignore_ = false;
-
PaintTimingDetector::PaintTimingDetector(LocalFrameView* frame_view)
: frame_view_(frame_view),
text_paint_timing_detector_(
@@ -200,8 +198,10 @@ void PaintTimingDetector::OnInputOrScroll() {
void PaintTimingDetector::NotifyInputEvent(WebInputEvent::Type type) {
// A single keyup event should be ignored. It could be caused by user actions
// such as refreshing via Ctrl+R.
- if (type == WebInputEvent::kMouseMove || type == WebInputEvent::kMouseEnter ||
- type == WebInputEvent::kMouseLeave || type == WebInputEvent::kKeyUp ||
+ if (type == WebInputEvent::Type::kMouseMove ||
+ type == WebInputEvent::Type::kMouseEnter ||
+ type == WebInputEvent::Type::kMouseLeave ||
+ type == WebInputEvent::Type::kKeyUp ||
WebInputEvent::IsPinchGestureEventType(type)) {
return;
}
diff --git a/chromium/third_party/blink/renderer/core/paint/paint_timing_detector.h b/chromium/third_party/blink/renderer/core/paint/paint_timing_detector.h
index 82391ba7022..c4329f86b54 100644
--- a/chromium/third_party/blink/renderer/core/paint/paint_timing_detector.h
+++ b/chromium/third_party/blink/renderer/core/paint/paint_timing_detector.h
@@ -11,6 +11,7 @@
#include "third_party/blink/renderer/core/layout/layout_box_model_object.h"
#include "third_party/blink/renderer/core/paint/paint_timing_visualizer.h"
#include "third_party/blink/renderer/core/scroll/scroll_types.h"
+#include "third_party/blink/renderer/platform/graphics/paint/ignore_paint_timing_scope.h"
#include "third_party/blink/renderer/platform/heap/member.h"
#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
@@ -273,22 +274,6 @@ class ScopedPaintTimingDetectorBlockPaintHook {
DISALLOW_COPY_AND_ASSIGN(ScopedPaintTimingDetectorBlockPaintHook);
};
-// Creates a scope to ignore paint timing, e.g. when we are painting contents
-// under opacity:0.
-class IgnorePaintTimingScope {
- STACK_ALLOCATED();
-
- public:
- IgnorePaintTimingScope() : auto_reset_(&should_ignore_, true) {}
- ~IgnorePaintTimingScope() = default;
-
- static bool ShouldIgnore() { return should_ignore_; }
-
- private:
- base::AutoReset<bool> auto_reset_;
- static bool should_ignore_;
-};
-
// static
inline void PaintTimingDetector::NotifyTextPaint(
const IntRect& text_visual_rect) {
diff --git a/chromium/third_party/blink/renderer/core/paint/pre_paint_tree_walk.cc b/chromium/third_party/blink/renderer/core/paint/pre_paint_tree_walk.cc
index 4fffe2ebb46..18e6d7aa22b 100644
--- a/chromium/third_party/blink/renderer/core/paint/pre_paint_tree_walk.cc
+++ b/chromium/third_party/blink/renderer/core/paint/pre_paint_tree_walk.cc
@@ -17,7 +17,9 @@
#include "third_party/blink/renderer/core/layout/layout_shift_tracker.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.h"
+#include "third_party/blink/renderer/core/layout/ng/ng_block_break_token.h"
#include "third_party/blink/renderer/core/layout/ng/ng_fragment_child_iterator.h"
+#include "third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.h"
#include "third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h"
#include "third_party/blink/renderer/core/page/chrome_client.h"
#include "third_party/blink/renderer/core/page/page.h"
@@ -38,16 +40,42 @@ namespace {
// allowed to clear old FragmentData objects.
NGPrePaintInfo SetupFragmentData(const NGFragmentChildIterator& iterator,
bool allow_reset) {
+ // TODO(crbug.com/1043787): What's here is mostly gross, and we need to come
+ // up with something better. The way FragmentData works (and is stored)
+ // vs. the way NGPhysicalFragment works is less than ideal.
+ //
+ // There's essentially a 1:1 correspondence between a block-level
+ // NGPhysicalBoxFragment and FragmentData, but there's no direct link between
+ // them, so we have to do some work. In the future we might want to make
+ // FragmentData part of NGPhysicalBoxFragment objects, to simplify this, and
+ // to get rid of O(n^2) performance complexity (where n is the number of
+ // fragments generated by a node). Note that this performance complexity also
+ // exists in the legacy engine.
+ //
+ // For inline-level nodes, it gets a bit more complicated. There's one
+ // FragmentData object per fragmentainer said node occurs in. The offset and
+ // invalidation rectangle in each FragmentData will be a union of all the
+ // fragments generated by the node (one per line box, typically) in that
+ // fragmentainer. This also matches how we do it in legacy layout. It's
+ // considered too expensive to have one FragmentData object per line for each
+ // text node or non-atomic inline.
DCHECK(iterator->GetLayoutObject());
const LayoutObject& object = *iterator->GetLayoutObject();
FragmentData* fragment_data = &object.GetMutableForPainting().FirstFragment();
- // TODO(crbug.com/1043787): Add support for block fragmentation. Furthermore,
- // what's here is mostly gross, and we need to come up with something
- // better. The way FragmentData works (and is stored) vs. the way
- // NGPhysicalFragment works is less than ideal.
- fragment_data->ClearNextFragment();
+ const auto* incoming_break_token = iterator->BlockBreakToken();
+ const NGPhysicalBoxFragment* box_fragment = iterator->BoxFragment();
+
+ // The need for paint properties is the same across all fragments, so if the
+ // first FragmentData needs it, so do all the others.
+ bool needs_paint_properties = fragment_data->PaintProperties();
+
if (const NGFragmentItem* fragment_item = iterator->FragmentItem()) {
- // We're in an inline formatting context.
+ // We're in an inline formatting context. The consumed block-size stored in
+ // the incoming break token will be stored in FragmentData objects to
+ // identify each portion for a given fragmentainer.
+ LayoutUnit consumed_block_size;
+ if (incoming_break_token)
+ consumed_block_size = incoming_break_token->ConsumedBlockSize();
if (fragment_item->IsFirstForNode()) {
// This is the first fragment generated for the node (i.e. we're on the
// first line and first fragmentainer (column) that this node occurs
@@ -55,13 +83,60 @@ NGPrePaintInfo SetupFragmentData(const NGFragmentChildIterator& iterator,
// fragments may have changed since last time). All the other fragments
// will be visited in due course.
if (allow_reset && !object.IsBox()) {
- // For text and non-atomic inlines we now reset the visual rect. The
- // visual rect will be set and expanded, as we visit each individual
- // fragment.
+ // For text and non-atomic inlines, we now remove additional
+ // FragmentData objects, and reset the visual rect. The visual rect will
+ // be set and expanded, as we visit each individual fragment.
+ fragment_data->ClearNextFragment();
fragment_data->SetVisualRect(IntRect());
}
+ fragment_data->SetLogicalTopInFlowThread(consumed_block_size);
+ } else {
+ // This is not the first fragment. Now see if we can find a FragmentData
+ // with the right consumed block-size (or flow thread logical top). If
+ // not, we'll have to create one now.
+ while (consumed_block_size > fragment_data->LogicalTopInFlowThread()) {
+ FragmentData* next_fragment_data = fragment_data->NextFragment();
+ if (!next_fragment_data) {
+ fragment_data = &fragment_data->EnsureNextFragment();
+ fragment_data->SetLogicalTopInFlowThread(consumed_block_size);
+ break;
+ }
+ fragment_data = next_fragment_data;
+ }
+ DCHECK_EQ(fragment_data->LogicalTopInFlowThread(), consumed_block_size);
+ }
+ } else {
+ // The fragment is block-level.
+ if (IsResumingLayout(incoming_break_token)) {
+ // This isn't the first fragment for the node. We now need to walk past
+ // all prededing fragments to figure out which FragmentData to return (or
+ // create, if it doesn't already exist).
+ const LayoutBox& layout_box = ToLayoutBox(object);
+ for (wtf_size_t idx = 0;; idx++) {
+ DCHECK_LT(idx, layout_box.PhysicalFragmentCount());
+ if (layout_box.GetPhysicalFragment(idx) == box_fragment)
+ break;
+ FragmentData* next = fragment_data->NextFragment();
+ if (!next) {
+ DCHECK_EQ(layout_box.GetPhysicalFragment(idx + 1), box_fragment);
+ fragment_data = &fragment_data->EnsureNextFragment();
+ break;
+ }
+ fragment_data = next;
+ }
+ fragment_data->SetLogicalTopInFlowThread(
+ incoming_break_token->ConsumedBlockSize());
+ }
+ if (!box_fragment->BreakToken()) {
+ // We have reached the end. There may be more data entries that were
+ // needed in the previous layout, but not any more. Clear them.
+ fragment_data->ClearNextFragment();
}
}
+
+ if (needs_paint_properties)
+ fragment_data->EnsurePaintProperties();
+
return NGPrePaintInfo(iterator, *fragment_data);
}
@@ -467,21 +542,42 @@ void PrePaintTreeWalk::WalkNGChildren(const LayoutObject* parent,
if (const auto* fragment_item = (*iterator)->FragmentItem()) {
// Line boxes are not interesting. They have no paint effects. Descend
// directly into children.
- bool descend_directly = fragment_item->Type() == NGFragmentItem::kLine;
- if (!descend_directly && fragment_item->IsInlineBox() &&
- !fragment_item->BoxFragment()) {
- // Likewise for culled inlines.
- descend_directly = true;
- object->GetMutableForPainting().ClearPaintFlags();
- }
- if (descend_directly) {
+ if (fragment_item->Type() == NGFragmentItem::kLine) {
WalkChildren(/* parent */ nullptr, iterator);
continue;
}
+ } else if (!object) {
+ // A column doesn't paint anything itself. Just include its offset and
+ // descend into children.
+ DCHECK((*iterator)->BoxFragment()->IsColumnBox());
+ PhysicalOffset offset = (*iterator)->Link().offset;
+ PaintPropertyTreeBuilderFragmentContext::ContainingBlockContext*
+ fragment_context = nullptr;
+ if (context_storage_.back().tree_builder_context) {
+ PaintPropertyTreeBuilderContext& tree_builder_context =
+ context_storage_.back().tree_builder_context.value();
+ fragment_context = &tree_builder_context.fragments[0].current;
+ fragment_context->paint_offset += offset;
+ }
+ WalkChildren(/* parent */ nullptr, iterator);
+ if (fragment_context)
+ fragment_context->paint_offset -= offset;
+ continue;
}
- DCHECK(object);
Walk(*object, iterator);
}
+
+ const LayoutBlockFlow* parent_block = DynamicTo<LayoutBlockFlow>(parent);
+ if (!parent_block || !parent_block->MultiColumnFlowThread())
+ return;
+ // Multicol containers only contain special legacy children invisible to
+ // LayoutNG, so we need to clean them manually.
+ for (const LayoutObject* child = parent->SlowFirstChild(); child;
+ child = child->NextSibling()) {
+ DCHECK(child->IsLayoutFlowThread() || child->IsLayoutMultiColumnSet() ||
+ child->IsLayoutMultiColumnSpannerPlaceholder());
+ child->GetMutableForPainting().ClearPaintFlags();
+ }
}
void PrePaintTreeWalk::WalkLegacyChildren(const LayoutObject& object) {
@@ -495,6 +591,7 @@ void PrePaintTreeWalk::WalkLegacyChildren(const LayoutObject& object) {
DCHECK_EQ(layout_box->PhysicalFragmentCount(), 1u);
const NGPhysicalBoxFragment& fragment =
To<NGPhysicalBoxFragment>(*layout_box->GetPhysicalFragment(0));
+ DCHECK(!fragment.BreakToken());
NGFragmentChildIterator child_iterator(fragment);
WalkNGChildren(&object, &child_iterator);
return;
@@ -507,6 +604,19 @@ void PrePaintTreeWalk::WalkLegacyChildren(const LayoutObject& object) {
child->GetMutableForPainting().ClearPaintFlags();
continue;
}
+ // Skip out-of-flow positioned children lest they be walked twice. If |this|
+ // is an NG object, but it still walks its children the legacy way (this may
+ // happen to table-cells; see LayoutObject::CanTraversePhysicalFragments()),
+ // we're either going to handle it in the code below after the loop - if
+ // |this| is actually the containing block. Otherwise it will be handled by
+ // some ancestor - either in the same code below (if it's a legacy-walking
+ // object) or via regular child fragment traversal. If we walk it here as
+ // well, we'd end up walking it twice. This is both bad for performance, and
+ // also correctness, as fragment items are sensitive to how they're walked
+ // (see SetupFragmentData()).
+ if (UNLIKELY(RuntimeEnabledFeatures::LayoutNGFragmentTraversalEnabled() &&
+ child->IsOutOfFlowPositioned() && object.IsLayoutNGObject()))
+ continue;
Walk(*child, /* iterator */ nullptr);
}
@@ -592,6 +702,8 @@ void PrePaintTreeWalk::Walk(const LayoutObject& object,
physical_fragment = (*iterator)->BoxFragment();
if (const auto* fragment_item = (*iterator)->FragmentItem())
is_last_fragment = fragment_item->IsLastForNode();
+ else if (physical_fragment)
+ is_last_fragment = !physical_fragment->BreakToken();
}
// We need to be careful not to have a reference to the parent context, since
diff --git a/chromium/third_party/blink/renderer/core/paint/scoped_svg_paint_state.cc b/chromium/third_party/blink/renderer/core/paint/scoped_svg_paint_state.cc
index cf1ec8de0e0..f302470dafb 100644
--- a/chromium/third_party/blink/renderer/core/paint/scoped_svg_paint_state.cc
+++ b/chromium/third_party/blink/renderer/core/paint/scoped_svg_paint_state.cc
@@ -27,10 +27,40 @@
#include "third_party/blink/renderer/core/layout/svg/layout_svg_resource_filter.h"
#include "third_party/blink/renderer/core/layout/svg/svg_resources.h"
#include "third_party/blink/renderer/core/layout/svg/svg_resources_cache.h"
+#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
#include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h"
+#include "third_party/blink/renderer/platform/graphics/paint/paint_controller.h"
namespace blink {
+SVGFilterRecordingContext::SVGFilterRecordingContext(
+ const PaintInfo& initial_paint_info)
+ // Create a new controller and context so the contents of the filter can be
+ // drawn and cached.
+ : paint_controller_(std::make_unique<PaintController>()),
+ context_(std::make_unique<GraphicsContext>(*paint_controller_)),
+ paint_info_(*context_, initial_paint_info) {
+ // Use initial_paint_info's current paint chunk properties so that any new
+ // chunk created during painting the content will be in the correct state.
+ paint_controller_->UpdateCurrentPaintChunkProperties(
+ nullptr, initial_paint_info.context.GetPaintController()
+ .CurrentPaintChunkProperties());
+ // Because we cache the filter contents and do not invalidate on paint
+ // invalidation rect changes, we need to paint the entire filter region so
+ // elements outside the initial paint (due to scrolling, etc) paint.
+ paint_info_.ApplyInfiniteCullRect();
+}
+
+SVGFilterRecordingContext::~SVGFilterRecordingContext() = default;
+
+sk_sp<PaintRecord> SVGFilterRecordingContext::GetPaintRecord(
+ const PaintInfo& initial_paint_info) {
+ paint_controller_->CommitNewDisplayItems();
+ return paint_controller_->GetPaintArtifact().GetPaintRecord(
+ initial_paint_info.context.GetPaintController()
+ .CurrentPaintChunkProperties());
+}
+
static void PaintFilteredContent(GraphicsContext& context,
const LayoutObject& object,
const DisplayItemClient& display_item_client,
@@ -171,7 +201,7 @@ bool ScopedSVGPaintState::ApplyFilterIfNecessary(SVGResources* resources) {
if (!filter)
return true;
filter->ClearInvalidationMask();
- filter_data_ = SVGFilterPainter(*filter).PrepareEffect(object_);
+ filter_data_ = SVGResources::GetClient(object_)->UpdateFilterData();
// If we have no filter data (== the filter was invalid) or if we
// don't need to update the source graphics, we can short-circuit
// here.
diff --git a/chromium/third_party/blink/renderer/core/paint/scoped_svg_paint_state.h b/chromium/third_party/blink/renderer/core/paint/scoped_svg_paint_state.h
index 8d467e7b4a2..2cbc04609d5 100644
--- a/chromium/third_party/blink/renderer/core/paint/scoped_svg_paint_state.h
+++ b/chromium/third_party/blink/renderer/core/paint/scoped_svg_paint_state.h
@@ -26,18 +26,21 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_SCOPED_SVG_PAINT_STATE_H_
#include <memory>
+#include "base/macros.h"
#include "third_party/blink/renderer/core/paint/clip_path_clipper.h"
#include "third_party/blink/renderer/core/paint/object_paint_properties.h"
#include "third_party/blink/renderer/core/paint/paint_info.h"
-#include "third_party/blink/renderer/core/paint/svg_filter_painter.h"
#include "third_party/blink/renderer/core/paint/svg_mask_painter.h"
#include "third_party/blink/renderer/platform/graphics/paint/scoped_paint_chunk_properties.h"
#include "third_party/blink/renderer/platform/transforms/affine_transform.h"
+#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
namespace blink {
class FilterData;
+class GraphicsContext;
class LayoutObject;
+class PaintController;
class SVGResources;
// Hooks up the correct paint property transform node.
@@ -76,6 +79,23 @@ class ScopedSVGTransformState {
base::Optional<ScopedPaintChunkProperties> transform_property_scope_;
};
+class SVGFilterRecordingContext {
+ USING_FAST_MALLOC(SVGFilterRecordingContext);
+
+ public:
+ explicit SVGFilterRecordingContext(const PaintInfo&);
+ ~SVGFilterRecordingContext();
+
+ const PaintInfo& GetPaintInfo() const { return paint_info_; }
+ sk_sp<PaintRecord> GetPaintRecord(const PaintInfo&);
+
+ private:
+ std::unique_ptr<PaintController> paint_controller_;
+ std::unique_ptr<GraphicsContext> context_;
+ PaintInfo paint_info_;
+ DISALLOW_COPY_AND_ASSIGN(SVGFilterRecordingContext);
+};
+
class ScopedSVGPaintState {
STACK_ALLOCATED();
diff --git a/chromium/third_party/blink/renderer/core/paint/scrollable_area_painter.cc b/chromium/third_party/blink/renderer/core/paint/scrollable_area_painter.cc
index df26ad02982..83dcd2c8bc4 100644
--- a/chromium/third_party/blink/renderer/core/paint/scrollable_area_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/scrollable_area_painter.cc
@@ -172,12 +172,12 @@ void ScrollableAreaPainter::PaintOverflowControls(
if (GetScrollableArea().HorizontalScrollbar() &&
!GetScrollableArea().GraphicsLayerForHorizontalScrollbar()) {
PaintScrollbar(context, *GetScrollableArea().HorizontalScrollbar(),
- paint_info.GetCullRect(), paint_offset);
+ paint_offset, paint_info.GetCullRect());
}
if (GetScrollableArea().VerticalScrollbar() &&
!GetScrollableArea().GraphicsLayerForVerticalScrollbar()) {
PaintScrollbar(context, *GetScrollableArea().VerticalScrollbar(),
- paint_info.GetCullRect(), paint_offset);
+ paint_offset, paint_info.GetCullRect());
}
if (!GetScrollableArea().GraphicsLayerForScrollCorner()) {
@@ -192,8 +192,8 @@ void ScrollableAreaPainter::PaintOverflowControls(
void ScrollableAreaPainter::PaintScrollbar(GraphicsContext& context,
Scrollbar& scrollbar,
- const CullRect& cull_rect,
- const IntPoint& paint_offset) {
+ const IntPoint& paint_offset,
+ const CullRect& cull_rect) {
// TODO(crbug.com/1020913): We should not round paint_offset but should
// consider subpixel accumulation when painting scrollbars.
IntRect rect = scrollbar.FrameRect();
@@ -201,8 +201,17 @@ void ScrollableAreaPainter::PaintScrollbar(GraphicsContext& context,
if (!cull_rect.Intersects(rect))
return;
- if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled() ||
- scrollbar.IsCustomScrollbar()) {
+ if (scrollbar.IsCustomScrollbar()) {
+ scrollbar.Paint(context, paint_offset);
+
+ // Prevent composited scroll hit test on the custom scrollbar which always
+ // need main thread scrolling.
+ context.GetPaintController().RecordScrollHitTestData(
+ scrollbar, DisplayItem::kCustomScrollbarHitTest, nullptr, rect);
+ return;
+ }
+
+ if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
scrollbar.Paint(context, paint_offset);
return;
}
diff --git a/chromium/third_party/blink/renderer/core/paint/scrollable_area_painter.h b/chromium/third_party/blink/renderer/core/paint/scrollable_area_painter.h
index 9b702249b5a..e8c6e487da4 100644
--- a/chromium/third_party/blink/renderer/core/paint/scrollable_area_painter.h
+++ b/chromium/third_party/blink/renderer/core/paint/scrollable_area_painter.h
@@ -29,6 +29,10 @@ class ScrollableAreaPainter {
: scrollable_area_(&paint_layer_scrollable_area) {}
void PaintOverflowControls(const PaintInfo&, const IntPoint& paint_offset);
+ void PaintScrollbar(GraphicsContext&,
+ Scrollbar&,
+ const IntPoint& paint_offset,
+ const CullRect&);
void PaintResizer(GraphicsContext&,
const IntPoint& paint_offset,
const CullRect&);
@@ -44,10 +48,6 @@ class ScrollableAreaPainter {
private:
void DrawPlatformResizerImage(GraphicsContext&,
const IntRect& resizer_corner_rect);
- void PaintScrollbar(GraphicsContext&,
- Scrollbar&,
- const CullRect&,
- const IntPoint& paint_offset);
PaintLayerScrollableArea& GetScrollableArea() const;
const DisplayItemClient& DisplayItemClientForCorner() const;
diff --git a/chromium/third_party/blink/renderer/core/paint/svg_filter_painter.cc b/chromium/third_party/blink/renderer/core/paint/svg_filter_painter.cc
deleted file mode 100644
index 47552d0011e..00000000000
--- a/chromium/third_party/blink/renderer/core/paint/svg_filter_painter.cc
+++ /dev/null
@@ -1,76 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/core/paint/svg_filter_painter.h"
-
-#include <utility>
-
-#include "third_party/blink/renderer/core/layout/svg/layout_svg_resource_filter.h"
-#include "third_party/blink/renderer/core/layout/svg/svg_resources.h"
-#include "third_party/blink/renderer/core/paint/filter_effect_builder.h"
-#include "third_party/blink/renderer/core/svg/graphics/filters/svg_filter_builder.h"
-#include "third_party/blink/renderer/core/svg/svg_filter_element.h"
-#include "third_party/blink/renderer/platform/graphics/filters/filter.h"
-#include "third_party/blink/renderer/platform/graphics/filters/source_graphic.h"
-#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
-#include "third_party/blink/renderer/platform/graphics/paint/paint_controller.h"
-
-namespace blink {
-
-SVGFilterRecordingContext::SVGFilterRecordingContext(
- const PaintInfo& initial_paint_info)
- // Create a new context so the contents of the filter can be drawn and
- // cached.
- : paint_controller_(std::make_unique<PaintController>()),
- context_(std::make_unique<GraphicsContext>(*paint_controller_)),
- paint_info_(*context_, initial_paint_info) {
- // Use initial_paint_info's current paint chunk properties so that any new
- // chunk created during painting the content will be in the correct state.
- paint_controller_->UpdateCurrentPaintChunkProperties(
- nullptr, initial_paint_info.context.GetPaintController()
- .CurrentPaintChunkProperties());
- // Because we cache the filter contents and do not invalidate on paint
- // invalidation rect changes, we need to paint the entire filter region so
- // elements outside the initial paint (due to scrolling, etc) paint.
- paint_info_.ApplyInfiniteCullRect();
-}
-
-SVGFilterRecordingContext::~SVGFilterRecordingContext() = default;
-
-sk_sp<PaintRecord> SVGFilterRecordingContext::GetPaintRecord(
- const PaintInfo& initial_paint_info) {
- paint_controller_->CommitNewDisplayItems();
- return paint_controller_->GetPaintArtifact().GetPaintRecord(
- initial_paint_info.context.GetPaintController()
- .CurrentPaintChunkProperties());
-}
-
-FilterData* SVGFilterPainter::PrepareEffect(const LayoutObject& object) {
- SVGElementResourceClient* client = SVGResources::GetClient(object);
- if (FilterData* filter_data = client->GetFilterData()) {
- // If the filterData already exists we do not need to record the content
- // to be filtered. This can occur if the content was previously recorded
- // or we are in a cycle.
- filter_data->UpdateStateOnPrepare();
- return filter_data;
- }
-
- auto* node_map = MakeGarbageCollected<SVGFilterGraphNodeMap>();
- FilterEffectBuilder builder(SVGResources::ReferenceBoxForEffects(object), 1);
- Filter* filter = builder.BuildReferenceFilter(
- To<SVGFilterElement>(*filter_.GetElement()), nullptr, node_map);
- if (!filter || !filter->LastEffect())
- return nullptr;
-
- IntRect source_region = EnclosingIntRect(object.StrokeBoundingBox());
- filter->GetSourceGraphic()->SetSourceRect(source_region);
-
- auto* filter_data =
- MakeGarbageCollected<FilterData>(filter->LastEffect(), node_map);
- // TODO(pdr): Can this be moved out of painter?
- client->SetFilterData(filter_data);
- return filter_data;
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/svg_filter_painter.h b/chromium/third_party/blink/renderer/core/paint/svg_filter_painter.h
deleted file mode 100644
index f38d6937347..00000000000
--- a/chromium/third_party/blink/renderer/core/paint/svg_filter_painter.h
+++ /dev/null
@@ -1,54 +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_CORE_PAINT_SVG_FILTER_PAINTER_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_SVG_FILTER_PAINTER_H_
-
-#include <memory>
-#include "base/macros.h"
-#include "third_party/blink/renderer/core/paint/paint_info.h"
-#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
-
-namespace blink {
-
-class FilterData;
-class GraphicsContext;
-class LayoutObject;
-class LayoutSVGResourceFilter;
-class PaintController;
-
-class SVGFilterRecordingContext {
- USING_FAST_MALLOC(SVGFilterRecordingContext);
-
- public:
- explicit SVGFilterRecordingContext(const PaintInfo&);
- ~SVGFilterRecordingContext();
-
- const PaintInfo& GetPaintInfo() const { return paint_info_; }
- sk_sp<PaintRecord> GetPaintRecord(const PaintInfo&);
-
- private:
- std::unique_ptr<PaintController> paint_controller_;
- std::unique_ptr<GraphicsContext> context_;
- PaintInfo paint_info_;
- DISALLOW_COPY_AND_ASSIGN(SVGFilterRecordingContext);
-};
-
-class SVGFilterPainter {
- STACK_ALLOCATED();
-
- public:
- SVGFilterPainter(LayoutSVGResourceFilter& filter) : filter_(filter) {}
-
- // Returns the FilterData for the filter effect, or null if the
- // filter is invalid.
- FilterData* PrepareEffect(const LayoutObject&);
-
- private:
- LayoutSVGResourceFilter& filter_;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_SVG_FILTER_PAINTER_H_
diff --git a/chromium/third_party/blink/renderer/core/paint/text_paint_timing_detector_test.cc b/chromium/third_party/blink/renderer/core/paint/text_paint_timing_detector_test.cc
index 9cec3867170..ff95b06c384 100644
--- a/chromium/third_party/blink/renderer/core/paint/text_paint_timing_detector_test.cc
+++ b/chromium/third_party/blink/renderer/core/paint/text_paint_timing_detector_test.cc
@@ -112,7 +112,7 @@ class TextPaintTimingDetectorTest : public testing::Test {
}
void SimulateKeyUp() {
- GetPaintTimingDetector().NotifyInputEvent(WebInputEvent::kKeyUp);
+ GetPaintTimingDetector().NotifyInputEvent(WebInputEvent::Type::kKeyUp);
}
void InvokeCallback() {
diff --git a/chromium/third_party/blink/renderer/core/paint/text_painter_base.cc b/chromium/third_party/blink/renderer/core/paint/text_painter_base.cc
index e6b2b918f1f..813881f8a8c 100644
--- a/chromium/third_party/blink/renderer/core/paint/text_painter_base.cc
+++ b/chromium/third_party/blink/renderer/core/paint/text_painter_base.cc
@@ -290,10 +290,11 @@ static ResolvedUnderlinePosition ResolveUnderlinePosition(
// vertical text.
switch (baseline_type) {
case kAlphabeticBaseline:
- if (!(style.TextUnderlinePosition() & kTextUnderlinePositionUnder)) {
- return ResolvedUnderlinePosition::kRoman;
- }
- return ResolvedUnderlinePosition::kUnder;
+ if (style.TextUnderlinePosition() & kTextUnderlinePositionUnder)
+ return ResolvedUnderlinePosition::kUnder;
+ if (style.TextUnderlinePosition() & kTextUnderlinePositionFromFont)
+ return ResolvedUnderlinePosition::kNearAlphabeticBaselineFromFont;
+ return ResolvedUnderlinePosition::kNearAlphabeticBaselineAuto;
case kIdeographicBaseline:
// Compute language-appropriate default underline position.
// https://drafts.csswg.org/css-text-decor-3/#default-stylesheet
@@ -310,7 +311,7 @@ static ResolvedUnderlinePosition ResolveUnderlinePosition(
return ResolvedUnderlinePosition::kUnder;
}
NOTREACHED();
- return ResolvedUnderlinePosition::kRoman;
+ return ResolvedUnderlinePosition::kNearAlphabeticBaselineAuto;
}
static bool ShouldSetDecorationAntialias(const ComputedStyle& style) {
@@ -325,24 +326,17 @@ static bool ShouldSetDecorationAntialias(const ComputedStyle& style) {
float ComputeDecorationThickness(const ComputedStyle* style,
const SimpleFontData* font_data) {
- // Set the thick of the line to be 10% (or something else ?)of the computed
- // font size and not less than 1px. Using computedFontSize should take care
- // of zoom as well.
-
- // Update Underline thickness, in case we have Faulty Font Metrics calculating
- // underline thickness by old method.
- float text_decoration_thickness = 0.0;
- int font_height_int = 0;
- if (font_data) {
- text_decoration_thickness =
- font_data->GetFontMetrics().UnderlineThickness();
- font_height_int = font_data->GetFontMetrics().Height();
- }
- if ((text_decoration_thickness == 0.f) ||
- (text_decoration_thickness >= (font_height_int >> 1))) {
- text_decoration_thickness = std::max(1.f, style->ComputedFontSize() / 10.f);
- }
- return text_decoration_thickness;
+ // TODO(https://crbug.com/785230): Implement text-decoration-thickness setting
+ // and the from-font keyword here. We previously tried reading
+ // font_data->FontMetrics().UnderlineThickness() here but that never returned
+ // anything other than 0. Removed no-op implementation until we implement
+ // from-font behavior here. Keep font_data argument for now as this will be
+ // needed for the from-font implementation.
+
+ // Set the thickness of the line to be 10% (or something else ?)of the
+ // computed font size and not less than 1px. Using computedFontSize should
+ // take care of zoom as well.
+ return std::max(1.f, style->ComputedFontSize() / 10.f);
}
} // anonymous namespace
@@ -370,7 +364,10 @@ void TextPainterBase::ComputeDecorationInfo(
? decoration_info.font_data->GetFontMetrics().FloatAscent()
: 0;
- if (decoration_info.underline_position == ResolvedUnderlinePosition::kRoman) {
+ if ((decoration_info.underline_position ==
+ ResolvedUnderlinePosition::kNearAlphabeticBaselineAuto) ||
+ decoration_info.underline_position ==
+ ResolvedUnderlinePosition::kNearAlphabeticBaselineFromFont) {
decoration_info.thickness = ComputeDecorationThickness(
decoration_info.style, decoration_info.font_data);
} else {
diff --git a/chromium/third_party/blink/renderer/core/paint/url_metadata_utils.cc b/chromium/third_party/blink/renderer/core/paint/url_metadata_utils.cc
new file mode 100644
index 00000000000..834cee7e8c2
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/paint/url_metadata_utils.cc
@@ -0,0 +1,28 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/paint/url_metadata_utils.h"
+
+#include "third_party/blink/renderer/core/layout/geometry/physical_offset.h"
+#include "third_party/blink/renderer/core/layout/layout_object.h"
+#include "third_party/blink/renderer/core/paint/object_painter.h"
+#include "third_party/blink/renderer/core/paint/paint_info.h"
+
+namespace blink {
+
+void AddURLRectsForInlineChildrenRecursively(
+ const LayoutObject& layout_object,
+ const PaintInfo& paint_info,
+ const PhysicalOffset& paint_offset) {
+ for (LayoutObject* child = layout_object.SlowFirstChild(); child;
+ child = child->NextSibling()) {
+ if (!child->IsLayoutInline() ||
+ ToLayoutBoxModelObject(child)->HasSelfPaintingLayer())
+ continue;
+ ObjectPainter(*child).AddURLRectIfNeeded(paint_info, paint_offset);
+ AddURLRectsForInlineChildrenRecursively(*child, paint_info, paint_offset);
+ }
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/url_metadata_utils.h b/chromium/third_party/blink/renderer/core/paint/url_metadata_utils.h
new file mode 100644
index 00000000000..0fc0f1ecaaf
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/paint/url_metadata_utils.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_CORE_PAINT_URL_METADATA_UTILS_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_URL_METADATA_UTILS_H_
+
+namespace blink {
+
+class LayoutObject;
+struct PaintInfo;
+struct PhysicalOffset;
+
+// Traverses |layout_object| recursively to add URLs and Rects.
+void AddURLRectsForInlineChildrenRecursively(
+ const LayoutObject& layout_object,
+ const PaintInfo& paint_info,
+ const PhysicalOffset& paint_offset);
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_URL_METADATA_UTILS_H_
diff --git a/chromium/third_party/blink/renderer/core/paint/video_painter_test.cc b/chromium/third_party/blink/renderer/core/paint/video_painter_test.cc
index 954e9b4fb13..0c436ef3b43 100644
--- a/chromium/third_party/blink/renderer/core/paint/video_painter_test.cc
+++ b/chromium/third_party/blink/renderer/core/paint/video_painter_test.cc
@@ -168,8 +168,8 @@ TEST_P(VideoPaintPreviewTest, URLIsRecordedWhenPaintingPreview) {
GetLocalMainFrame().CapturePaintPreview(WebRect(bounds()), canvas);
ASSERT_EQ(1lu, tracker.GetLinks().size());
- EXPECT_EQ("http://test.com/", tracker.GetLinks()[0].url);
- EXPECT_EQ(gfx::Rect(300, 300), tracker.GetLinks()[0].rect);
+ EXPECT_EQ("http://test.com/", tracker.GetLinks()[0]->url);
+ EXPECT_EQ(gfx::Rect(300, 300), tracker.GetLinks()[0]->rect);
}
} // namespace
diff --git a/chromium/third_party/blink/renderer/core/paint/view_painter.cc b/chromium/third_party/blink/renderer/core/paint/view_painter.cc
index 1ce2481e0a0..1c0acf43c74 100644
--- a/chromium/third_party/blink/renderer/core/paint/view_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/view_painter.cc
@@ -19,6 +19,7 @@
#include "third_party/blink/renderer/core/paint/paint_layer.h"
#include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
#include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h"
+#include "third_party/blink/renderer/platform/graphics/paint/geometry_mapper.h"
#include "third_party/blink/renderer/platform/graphics/paint/scoped_paint_chunk_properties.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
@@ -70,9 +71,28 @@ void ViewPainter::PaintBoxDecorationBackground(const PaintInfo& paint_info) {
return;
bool has_touch_action_rect = layout_view_.HasEffectiveAllowedTouchAction();
+ bool painting_scrolling_background =
+ BoxDecorationData::IsPaintingScrollingBackground(paint_info,
+ layout_view_);
bool paints_scroll_hit_test =
- layout_view_.GetScrollableArea() &&
- layout_view_.GetScrollableArea()->ScrollsOverflow();
+ !painting_scrolling_background &&
+ layout_view_.FirstFragment().PaintProperties()->Scroll();
+ if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
+ // Pre-CompositeAfterPaint, there is no need to emit scroll hit test
+ // display items for composited scrollers because these display items are
+ // only used to create non-fast scrollable regions for non-composited
+ // scrollers. With CompositeAfterPaint, we always paint the scroll hit
+ // test display items but ignore the non-fast region if the scroll was
+ // composited in PaintArtifactCompositor::UpdateNonFastScrollableRegions.
+ if (layout_view_.HasLayer() &&
+ layout_view_.Layer()->GetCompositedLayerMapping() &&
+ layout_view_.Layer()
+ ->GetCompositedLayerMapping()
+ ->HasScrollingLayer()) {
+ paints_scroll_hit_test = false;
+ }
+ }
+
if (!layout_view_.HasBoxDecorationBackground() && !has_touch_action_rect &&
!paints_scroll_hit_test)
return;
@@ -89,9 +109,6 @@ void ViewPainter::PaintBoxDecorationBackground(const PaintInfo& paint_info) {
const DisplayItemClient* background_client = &layout_view_;
- bool painting_scrolling_background =
- BoxDecorationData::IsPaintingScrollingBackground(paint_info,
- layout_view_);
if (painting_scrolling_background) {
// Layout overflow, combined with the visible content size.
auto document_rect = layout_view_.DocumentRect();
@@ -173,6 +190,7 @@ void ViewPainter::PaintBoxDecorationBackground(const PaintInfo& paint_info) {
if (should_paint_background) {
PaintRootElementGroup(paint_info, pixel_snapped_background_rect,
+ root_element_background_painting_state,
*background_client, painted_separate_backdrop,
painted_separate_effect);
}
@@ -183,28 +201,11 @@ void ViewPainter::PaintBoxDecorationBackground(const PaintInfo& paint_info) {
*background_client);
}
- bool needs_scroll_hit_test = true;
- if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
- // Pre-CompositeAfterPaint, there is no need to emit scroll hit test
- // display items for composited scrollers because these display items are
- // only used to create non-fast scrollable regions for non-composited
- // scrollers. With CompositeAfterPaint, we always paint the scroll hit
- // test display items but ignore the non-fast region if the scroll was
- // composited in PaintArtifactCompositor::UpdateNonFastScrollableRegions.
- if (layout_view_.HasLayer() &&
- layout_view_.Layer()->GetCompositedLayerMapping() &&
- layout_view_.Layer()
- ->GetCompositedLayerMapping()
- ->HasScrollingLayer()) {
- needs_scroll_hit_test = false;
- }
- }
-
// Record the scroll hit test after the non-scrolling background so
// background squashing is not affected. Hit test order would be equivalent
// if this were immediately before the non-scrolling background.
- if (paints_scroll_hit_test && !painting_scrolling_background &&
- needs_scroll_hit_test) {
+ if (paints_scroll_hit_test) {
+ DCHECK(!painting_scrolling_background);
BoxPainter(layout_view_)
.RecordScrollHitTestData(paint_info, *background_client);
}
@@ -228,6 +229,7 @@ void ViewPainter::PaintBoxDecorationBackground(const PaintInfo& paint_info) {
void ViewPainter::PaintRootElementGroup(
const PaintInfo& paint_info,
const IntRect& pixel_snapped_background_rect,
+ const PropertyTreeState& background_paint_state,
const DisplayItemClient& background_client,
bool painted_separate_backdrop,
bool painted_separate_effect) {
@@ -270,28 +272,34 @@ void ViewPainter::PaintRootElementGroup(
// Compute the enclosing rect of the view, in root element space.
//
// For background colors we can simply paint the document rect in the default
- // space. However for background image, the root element transform applies.
- // The strategy is to apply root element transform on the context and issue
- // draw commands in the local space, therefore we need to apply inverse
- // transform on the document rect to get to the root element space.
- // Local / scroll positioned background images will be painted into scrolling
- // contents layer with root layer scrolling. Therefore we need to switch both
- // the pixel_snapped_background_rect and context to documentElement visual
- // space.
+ // space. However, for background image, the root element paint offset and
+ // transforms apply. The strategy is to issue draw commands in the root
+ // element's local space, which requires mapping the document background rect.
bool background_renderable = true;
- bool root_element_has_transform = false;
IntRect paint_rect = pixel_snapped_background_rect;
+ // Offset for BackgroundImageGeometry to offset the image's origin. This makes
+ // background tiling start at the root element's origin instead of the view.
+ // This is different from the offset for painting, which is in |paint_rect|.
+ LayoutPoint background_image_offset;
if (!root_object || !root_object->IsBox()) {
background_renderable = false;
} else {
- root_element_has_transform = root_object->StyleRef().HasTransform();
- TransformationMatrix transform;
- root_object->GetTransformFromContainer(root_object->View(),
- PhysicalOffset(), transform);
- if (!transform.IsInvertible())
- background_renderable = false;
- else
- paint_rect = transform.Inverse().MapRect(pixel_snapped_background_rect);
+ const auto& view_contents_state =
+ layout_view_.FirstFragment().ContentsProperties();
+ if (view_contents_state != background_paint_state) {
+ GeometryMapper::SourceToDestinationRect(
+ view_contents_state.Transform(), background_paint_state.Transform(),
+ paint_rect);
+ if (paint_rect.IsEmpty())
+ background_renderable = false;
+ // With transforms, paint offset is encoded in paint property nodes but we
+ // can use the |paint_rect|'s adjusted location as the offset from the
+ // view to the root element.
+ background_image_offset = paint_rect.Location();
+ } else {
+ background_image_offset =
+ -root_object->FirstFragment().PaintOffset().ToLayoutPoint();
+ }
}
bool should_clear_canvas =
@@ -368,18 +376,13 @@ void ViewPainter::PaintRootElementGroup(
context.FillRect(paint_rect, Color(), SkBlendMode::kClear);
}
- BackgroundImageGeometry geometry(layout_view_, root_element_has_transform);
+ BackgroundImageGeometry geometry(layout_view_, background_image_offset);
BoxModelObjectPainter box_model_painter(layout_view_);
for (const auto* fill_layer : base::Reversed(reversed_paint_list)) {
DCHECK(fill_layer->Clip() == EFillBox::kBorder);
-
- PhysicalRect painting_rect(paint_rect);
- if (!BackgroundImageGeometry::ShouldUseFixedAttachment(*fill_layer))
- painting_rect.Move(root_object->FirstFragment().PaintOffset());
-
box_model_painter.PaintFillLayer(paint_info, Color(), *fill_layer,
- painting_rect, kBackgroundBleedNone,
- geometry);
+ PhysicalRect(paint_rect),
+ kBackgroundBleedNone, geometry);
}
if (should_draw_background_in_separate_buffer && !painted_separate_effect)
diff --git a/chromium/third_party/blink/renderer/core/paint/view_painter.h b/chromium/third_party/blink/renderer/core/paint/view_painter.h
index 921839b76f8..09da628103d 100644
--- a/chromium/third_party/blink/renderer/core/paint/view_painter.h
+++ b/chromium/third_party/blink/renderer/core/paint/view_painter.h
@@ -30,6 +30,7 @@ class ViewPainter {
void PaintRootElementGroup(const PaintInfo&,
const IntRect& pixel_snapped_background_rect,
+ const PropertyTreeState& background_paint_state,
const DisplayItemClient& background_client,
bool painted_separate_backdrop,
bool painted_separate_effect);
diff --git a/chromium/third_party/blink/renderer/core/probe/core_probes.h b/chromium/third_party/blink/renderer/core/probe/core_probes.h
index bc9b68a0873..b38af6b0299 100644
--- a/chromium/third_party/blink/renderer/core/probe/core_probes.h
+++ b/chromium/third_party/blink/renderer/core/probe/core_probes.h
@@ -101,22 +101,22 @@ inline CoreProbeSink* ToCoreProbeSink(LocalFrame* frame) {
return frame ? frame->GetProbeSink() : nullptr;
}
+inline CoreProbeSink* ToCoreProbeSink(ExecutionContext* context) {
+ return context ? context->GetProbeSink() : nullptr;
+}
+
inline CoreProbeSink* ToCoreProbeSink(Document& document) {
- return document.GetProbeSink();
+ return ToCoreProbeSink(document.GetExecutionContext());
}
inline CoreProbeSink* ToCoreProbeSink(Document* document) {
- return document ? ToCoreProbeSink(*document) : nullptr;
+ return document ? ToCoreProbeSink(document->GetExecutionContext()) : nullptr;
}
inline CoreProbeSink* ToCoreProbeSink(CoreProbeSink* sink) {
return sink;
}
-inline CoreProbeSink* ToCoreProbeSink(ExecutionContext* context) {
- return context ? context->GetProbeSink() : nullptr;
-}
-
inline CoreProbeSink* ToCoreProbeSink(Node* node) {
return node ? ToCoreProbeSink(node->GetDocument()) : nullptr;
}
diff --git a/chromium/third_party/blink/renderer/core/probe/core_probes.json5 b/chromium/third_party/blink/renderer/core/probe/core_probes.json5
index f75394cfce1..e1c6bec6800 100644
--- a/chromium/third_party/blink/renderer/core/probe/core_probes.json5
+++ b/chromium/third_party/blink/renderer/core/probe/core_probes.json5
@@ -107,6 +107,7 @@
probes: [
"ApplyAcceptLanguageOverride",
"ApplyUserAgentOverride",
+ "ApplyUserAgentMetadataOverride",
"FrameStartedLoading",
"PrepareRequest",
]
@@ -124,7 +125,9 @@
},
InspectorMediaAgent: {
probes: [
+ "PlayerErrorsRaised",
"PlayerEventsAdded",
+ "PlayerMessagesLogged",
"PlayerPropertiesChanged",
"PlayersCreated"
]
@@ -163,6 +166,7 @@
"WillSendRequest",
"WillSendNavigationRequest",
"WillSendWebSocketHandshakeRequest",
+ "SetDevToolsIds",
]
},
InspectorPageAgent: {
diff --git a/chromium/third_party/blink/renderer/core/probe/core_probes.pidl b/chromium/third_party/blink/renderer/core/probe/core_probes.pidl
index c4d4e21f0d1..495e90dc865 100644
--- a/chromium/third_party/blink/renderer/core/probe/core_probes.pidl
+++ b/chromium/third_party/blink/renderer/core/probe/core_probes.pidl
@@ -88,6 +88,7 @@ interface CoreProbes {
void DidResizeMainFrame(LocalFrame*);
void ApplyAcceptLanguageOverride(ExecutionContext*, String* accept_language);
void ApplyUserAgentOverride(CoreProbeSink*, String* user_agent);
+ void ApplyUserAgentMetadataOverride(CoreProbeSink*, base::Optional<blink::UserAgentMetadata>* ua_metadata_override);
void DidBlockRequest(CoreProbeSink*, const ResourceRequest&, DocumentLoader*, const KURL& fetch_context_url, const FetchInitiatorInfo&, ResourceRequestBlockedReason, ResourceType);
void DidChangeResourcePriority(LocalFrame*, DocumentLoader*, uint64_t identifier, ResourceLoadPriority load_priority);
void PrepareRequest(CoreProbeSink*, DocumentLoader*, ResourceRequest&, const FetchInitiatorInfo&, ResourceType);
@@ -121,7 +122,7 @@ interface CoreProbes {
void FrameOwnerContentUpdated([Keep] LocalFrame*, HTMLFrameOwnerElement*);
void FrameStartedLoading([Keep] LocalFrame*);
void FrameStoppedLoading([Keep] LocalFrame*);
- void FrameRequestedNavigation(LocalFrame*, Frame* target_frame, const KURL& url, ClientNavigationReason reason);
+ void FrameRequestedNavigation(LocalFrame*, Frame* target_frame, const KURL& url, ClientNavigationReason reason, NavigationPolicy policy);
void FrameScheduledNavigation([Keep] LocalFrame*, const KURL& url, base::TimeDelta delay, ClientNavigationReason reason);
void FrameClearedScheduledNavigation([Keep] LocalFrame*);
void DidCreateWebSocket([Keep] ExecutionContext*, uint64_t identifier, const KURL& request_url, const String& protocol);
@@ -174,7 +175,10 @@ interface CoreProbes {
void NodeCreated([Keep] Node* node);
void PortalRemoteFrameCreated(Document*, HTMLPortalElement* portal_element);
void FileChooserOpened([Keep] LocalFrame* frame, HTMLInputElement* element, bool* intercepted);
- void PlayerEventsAdded(LocalFrame* frame, String player_id, const Vector<InspectorPlayerEvent>& events);
- void PlayerPropertiesChanged(LocalFrame* frame, String player_id, const Vector<InspectorPlayerProperty>& properties);
- void PlayersCreated(LocalFrame* frame, const Vector<WebString>& players);
+ void PlayerErrorsRaised(ExecutionContext* context, String player_id, const Vector<InspectorPlayerError>& errors);
+ void PlayerEventsAdded(ExecutionContext* context, String player_id, const Vector<InspectorPlayerEvent>& events);
+ void PlayerMessagesLogged(ExecutionContext* context, String player_id, const Vector<InspectorPlayerMessage>& messages);
+ void PlayerPropertiesChanged(ExecutionContext* context, String player_id, const Vector<InspectorPlayerProperty>& properties);
+ void PlayersCreated(ExecutionContext* context, const Vector<WebString>& players);
+ void SetDevToolsIds(CoreProbeSink*, ResourceRequest& request);
}
diff --git a/chromium/third_party/blink/renderer/core/resize_observer/resize_observation.cc b/chromium/third_party/blink/renderer/core/resize_observer/resize_observation.cc
index f6eb3c33a46..27293da6a2b 100644
--- a/chromium/third_party/blink/renderer/core/resize_observer/resize_observation.cc
+++ b/chromium/third_party/blink/renderer/core/resize_observer/resize_observation.cc
@@ -4,8 +4,10 @@
#include "third_party/blink/renderer/core/resize_observer/resize_observation.h"
#include "third_party/blink/renderer/core/display_lock/display_lock_utilities.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/layout/adjust_for_absolute_zoom.h"
#include "third_party/blink/renderer/core/layout/layout_box.h"
+#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/core/resize_observer/resize_observer.h"
#include "third_party/blink/renderer/core/resize_observer/resize_observer_box_options.h"
#include "third_party/blink/renderer/core/svg/svg_element.h"
@@ -77,7 +79,8 @@ LayoutSize ResizeObservation::ComputeTargetSize() const {
case ResizeObserverBoxOptions::DevicePixelContentBox: {
LayoutSize paint_offset =
layout_object->FirstFragment().PaintOffset().ToLayoutSize();
- return LayoutSize(
+
+ LayoutSize device_pixel_content_box_size(
SnapSizeToPixel(layout_box->ContentLogicalWidth(),
style.IsHorizontalWritingMode()
? paint_offset.Width()
@@ -86,6 +89,15 @@ LayoutSize ResizeObservation::ComputeTargetSize() const {
style.IsHorizontalWritingMode()
? paint_offset.Height()
: paint_offset.Width()));
+
+ // Get Device Scale Factor for cases where use-zoom-for-dsf is
+ // disabled. This is 1 if use-zoom-for-dsf is enabled.
+ float device_scale_factor = layout_object->GetFrame()
+ ->GetPage()
+ ->DeviceScaleFactorDeprecated();
+ device_pixel_content_box_size.Scale(device_scale_factor);
+
+ return device_pixel_content_box_size;
}
default:
NOTREACHED();
diff --git a/chromium/third_party/blink/renderer/core/resize_observer/resize_observer.cc b/chromium/third_party/blink/renderer/core/resize_observer/resize_observer.cc
index 2290704ac1d..cb90e34bb18 100644
--- a/chromium/third_party/blink/renderer/core/resize_observer/resize_observer.cc
+++ b/chromium/third_party/blink/renderer/core/resize_observer/resize_observer.cc
@@ -7,6 +7,7 @@
#include "third_party/blink/renderer/bindings/core/v8/v8_resize_observer_callback.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_resize_observer_options.h"
#include "third_party/blink/renderer/core/dom/element.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
#include "third_party/blink/renderer/core/layout/adjust_for_absolute_zoom.h"
#include "third_party/blink/renderer/core/layout/layout_object.h"
@@ -21,32 +22,38 @@ constexpr const char* kBoxOptionContentBox = "content-box";
constexpr const char* kBoxOptionDevicePixelContentBox =
"device-pixel-content-box";
-ResizeObserver* ResizeObserver::Create(Document& document,
+ResizeObserver* ResizeObserver::Create(ScriptState* script_state,
V8ResizeObserverCallback* callback) {
- return MakeGarbageCollected<ResizeObserver>(callback, document);
+ return MakeGarbageCollected<ResizeObserver>(
+ callback, LocalDOMWindow::From(script_state));
}
-ResizeObserver* ResizeObserver::Create(Document& document, Delegate* delegate) {
- return MakeGarbageCollected<ResizeObserver>(delegate, document);
+ResizeObserver* ResizeObserver::Create(LocalDOMWindow* window,
+ Delegate* delegate) {
+ return MakeGarbageCollected<ResizeObserver>(delegate, window);
}
ResizeObserver::ResizeObserver(V8ResizeObserverCallback* callback,
- Document& document)
- : ExecutionContextClient(document.ToExecutionContext()),
+ LocalDOMWindow* window)
+ : ExecutionContextClient(window),
callback_(callback),
skipped_observations_(false) {
DCHECK(callback_);
- controller_ = &document.EnsureResizeObserverController();
- controller_->AddObserver(*this);
+ if (window) {
+ controller_ = ResizeObserverController::From(*window);
+ controller_->AddObserver(*this);
+ }
}
-ResizeObserver::ResizeObserver(Delegate* delegate, Document& document)
- : ExecutionContextClient(document.ToExecutionContext()),
+ResizeObserver::ResizeObserver(Delegate* delegate, LocalDOMWindow* window)
+ : ExecutionContextClient(window),
delegate_(delegate),
skipped_observations_(false) {
DCHECK(delegate_);
- controller_ = &document.EnsureResizeObserverController();
- controller_->AddObserver(*this);
+ if (window) {
+ controller_ = ResizeObserverController::From(*window);
+ controller_->AddObserver(*this);
+ }
}
ResizeObserverBoxOptions ResizeObserver::ParseBoxOptions(
diff --git a/chromium/third_party/blink/renderer/core/resize_observer/resize_observer.h b/chromium/third_party/blink/renderer/core/resize_observer/resize_observer.h
index 8e8dd97ea24..18af42d6c8e 100644
--- a/chromium/third_party/blink/renderer/core/resize_observer/resize_observer.h
+++ b/chromium/third_party/blink/renderer/core/resize_observer/resize_observer.h
@@ -14,13 +14,14 @@
namespace blink {
-class Document;
class Element;
+class LocalDOMWindow;
class ResizeObserverController;
class ResizeObserverEntry;
class ResizeObservation;
-class V8ResizeObserverCallback;
class ResizeObserverOptions;
+class ScriptState;
+class V8ResizeObserverCallback;
// ResizeObserver represents ResizeObserver javascript api:
// https://github.com/WICG/ResizeObserver/
@@ -41,11 +42,11 @@ class CORE_EXPORT ResizeObserver final
virtual void Trace(Visitor* visitor) {}
};
- static ResizeObserver* Create(Document&, V8ResizeObserverCallback*);
- static ResizeObserver* Create(Document&, Delegate*);
+ static ResizeObserver* Create(ScriptState*, V8ResizeObserverCallback*);
+ static ResizeObserver* Create(LocalDOMWindow*, Delegate*);
- ResizeObserver(V8ResizeObserverCallback*, Document&);
- ResizeObserver(Delegate*, Document&);
+ ResizeObserver(V8ResizeObserverCallback*, LocalDOMWindow*);
+ ResizeObserver(Delegate*, LocalDOMWindow*);
~ResizeObserver() override = default;
// API methods
diff --git a/chromium/third_party/blink/renderer/core/resize_observer/resize_observer.idl b/chromium/third_party/blink/renderer/core/resize_observer/resize_observer.idl
index f6e0e947513..6537789bb6c 100644
--- a/chromium/third_party/blink/renderer/core/resize_observer/resize_observer.idl
+++ b/chromium/third_party/blink/renderer/core/resize_observer/resize_observer.idl
@@ -12,7 +12,7 @@ callback ResizeObserverCallback = void (sequence<ResizeObserverEntry> entries, R
Exposed=Window,
ActiveScriptWrappable
] interface ResizeObserver {
- [CallWith=Document, MeasureAs=ResizeObserver_Constructor] constructor(ResizeObserverCallback callback);
+ [CallWith=ScriptState, MeasureAs=ResizeObserver_Constructor] constructor(ResizeObserverCallback callback);
[RuntimeEnabled=ResizeObserverUpdates] void observe(Element target, ResizeObserverOptions options);
void observe(Element target);
void unobserve(Element target);
diff --git a/chromium/third_party/blink/renderer/core/resize_observer/resize_observer_controller.cc b/chromium/third_party/blink/renderer/core/resize_observer/resize_observer_controller.cc
index 4a7aa879403..51bba948c6d 100644
--- a/chromium/third_party/blink/renderer/core/resize_observer/resize_observer_controller.cc
+++ b/chromium/third_party/blink/renderer/core/resize_observer/resize_observer_controller.cc
@@ -4,10 +4,29 @@
#include "third_party/blink/renderer/core/resize_observer/resize_observer_controller.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/resize_observer/resize_observer.h"
namespace blink {
+const char ResizeObserverController::kSupplementName[] =
+ "ResizeObserverController";
+
+ResizeObserverController* ResizeObserverController::From(
+ LocalDOMWindow& window) {
+ auto* controller = FromIfExists(window);
+ if (!controller) {
+ controller = MakeGarbageCollected<ResizeObserverController>();
+ Supplement<LocalDOMWindow>::ProvideTo(window, controller);
+ }
+ return controller;
+}
+
+ResizeObserverController* ResizeObserverController::FromIfExists(
+ LocalDOMWindow& window) {
+ return Supplement<LocalDOMWindow>::From<ResizeObserverController>(window);
+}
+
ResizeObserverController::ResizeObserverController() = default;
void ResizeObserverController::AddObserver(ResizeObserver& observer) {
@@ -53,6 +72,7 @@ void ResizeObserverController::ClearObservations() {
}
void ResizeObserverController::Trace(Visitor* visitor) {
+ Supplement<LocalDOMWindow>::Trace(visitor);
visitor->Trace(observers_);
}
diff --git a/chromium/third_party/blink/renderer/core/resize_observer/resize_observer_controller.h b/chromium/third_party/blink/renderer/core/resize_observer/resize_observer_controller.h
index f8de314f644..5985219e001 100644
--- a/chromium/third_party/blink/renderer/core/resize_observer/resize_observer_controller.h
+++ b/chromium/third_party/blink/renderer/core/resize_observer/resize_observer_controller.h
@@ -5,24 +5,34 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_RESIZE_OBSERVER_RESIZE_OBSERVER_CONTROLLER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_RESIZE_OBSERVER_RESIZE_OBSERVER_CONTROLLER_H_
+#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
+#include "third_party/blink/renderer/platform/supplementable.h"
namespace blink {
+class LocalDOMWindow;
class ResizeObserver;
// ResizeObserverController keeps track of all ResizeObservers
-// in a single Document.
+// in a single window.
//
// The observation API is used to integrate ResizeObserver
// and the event loop. It delivers notification in a loop.
// In each iteration, only notifications deeper than the
// shallowest notification from previous iteration are delivered.
-class ResizeObserverController final
- : public GarbageCollected<ResizeObserverController> {
+class CORE_EXPORT ResizeObserverController final
+ : public GarbageCollected<ResizeObserverController>,
+ public Supplement<LocalDOMWindow> {
+ USING_GARBAGE_COLLECTED_MIXIN(ResizeObserverController);
+
public:
static const size_t kDepthBottom = 4096;
+ static const char kSupplementName[];
+ static ResizeObserverController* From(LocalDOMWindow&);
+ static ResizeObserverController* FromIfExists(LocalDOMWindow&);
+
ResizeObserverController();
void AddObserver(ResizeObserver&);
@@ -38,7 +48,14 @@ class ResizeObserverController final
void ClearMinDepth() { min_depth_ = 0; }
- void Trace(Visitor*);
+ bool IsLoopLimitErrorDispatched() const {
+ return loop_limit_error_dispatched;
+ }
+ void SetLoopLimitErrorDispatched(bool is_dispatched) {
+ loop_limit_error_dispatched = is_dispatched;
+ }
+
+ void Trace(Visitor*) override;
// For testing only.
const HeapLinkedHashSet<WeakMember<ResizeObserver>>& Observers() {
@@ -50,6 +67,9 @@ class ResizeObserverController final
HeapLinkedHashSet<WeakMember<ResizeObserver>> observers_;
// Minimum depth for observations to be active
size_t min_depth_ = 0;
+ // Used to prevent loop limit errors from being dispatched twice for the
+ // same lifecycle update
+ bool loop_limit_error_dispatched = false;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/resize_observer/resize_observer_entry.cc b/chromium/third_party/blink/renderer/core/resize_observer/resize_observer_entry.cc
index e4c23d5b7a1..92e6fc56cf0 100644
--- a/chromium/third_party/blink/renderer/core/resize_observer/resize_observer_entry.cc
+++ b/chromium/third_party/blink/renderer/core/resize_observer/resize_observer_entry.cc
@@ -4,9 +4,11 @@
#include "third_party/blink/renderer/core/resize_observer/resize_observer_entry.h"
#include "third_party/blink/renderer/core/dom/element.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/geometry/dom_rect_read_only.h"
#include "third_party/blink/renderer/core/layout/adjust_for_absolute_zoom.h"
#include "third_party/blink/renderer/core/layout/layout_box.h"
+#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/core/resize_observer/resize_observation.h"
#include "third_party/blink/renderer/core/resize_observer/resize_observer_size.h"
#include "third_party/blink/renderer/core/style/computed_style.h"
@@ -72,18 +74,26 @@ ResizeObserverEntry::ResizeObserverEntry(Element* target) : target_(target) {
LayoutSize border_box_size =
LayoutSize(layout_box->LogicalWidth(), layout_box->LogicalHeight());
+ // Get Device Scale Factor for cases where use-zoom-for-dsf is disabled.
+ // This is 1 if use-zoom-for-dsf is enabled.
+ float device_scale_factor =
+ layout_object->GetFrame()->GetPage()->DeviceScaleFactorDeprecated();
+
LayoutSize paint_offset =
layout_object->FirstFragment().PaintOffset().ToLayoutSize();
+
ResizeObserverSize* device_pixel_content_box_size =
ResizeObserverSize::Create(
SnapSizeToPixel(layout_box->ContentLogicalWidth(),
style.IsHorizontalWritingMode()
? paint_offset.Width()
- : paint_offset.Height()),
+ : paint_offset.Height()) *
+ device_scale_factor,
SnapSizeToPixel(layout_box->ContentLogicalHeight(),
style.IsHorizontalWritingMode()
? paint_offset.Height()
- : paint_offset.Width()));
+ : paint_offset.Width()) *
+ device_scale_factor);
content_box_size_.push_back(ZoomAdjustedSize(content_box_size, style));
border_box_size_.push_back(ZoomAdjustedSize(border_box_size, style));
diff --git a/chromium/third_party/blink/renderer/core/resize_observer/resize_observer_size.idl b/chromium/third_party/blink/renderer/core/resize_observer/resize_observer_size.idl
index a9d93b39056..d043025e315 100644
--- a/chromium/third_party/blink/renderer/core/resize_observer/resize_observer_size.idl
+++ b/chromium/third_party/blink/renderer/core/resize_observer/resize_observer_size.idl
@@ -5,7 +5,8 @@
// https://drafts.csswg.org/resize-observer-1/#resizeobserversize
[
- RuntimeEnabled=ResizeObserverUpdates
+ Exposed=Window,
+ RuntimeEnabled=ResizeObserverUpdates
] interface ResizeObserverSize {
readonly attribute unrestricted double inlineSize;
readonly attribute unrestricted double blockSize;
diff --git a/chromium/third_party/blink/renderer/core/resize_observer/resize_observer_test.cc b/chromium/third_party/blink/renderer/core/resize_observer/resize_observer_test.cc
index 988b84e3d24..f39ef42669e 100644
--- a/chromium/third_party/blink/renderer/core/resize_observer/resize_observer_test.cc
+++ b/chromium/third_party/blink/renderer/core/resize_observer/resize_observer_test.cc
@@ -11,6 +11,7 @@
#include "third_party/blink/renderer/bindings/core/v8/v8_gc_controller.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_resize_observer_options.h"
#include "third_party/blink/renderer/core/exported/web_view_impl.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/geometry/dom_rect_read_only.h"
#include "third_party/blink/renderer/core/resize_observer/resize_observation.h"
#include "third_party/blink/renderer/core/resize_observer/resize_observer_box_options.h"
@@ -28,24 +29,22 @@ namespace {
class TestResizeObserverDelegate : public ResizeObserver::Delegate {
public:
- TestResizeObserverDelegate(Document& document)
- : document_(document), call_count_(0) {}
+ explicit TestResizeObserverDelegate(LocalDOMWindow& window)
+ : window_(window), call_count_(0) {}
void OnResize(
const HeapVector<Member<ResizeObserverEntry>>& entries) override {
call_count_++;
}
- ExecutionContext* GetExecutionContext() const {
- return document_->ToExecutionContext();
- }
+ ExecutionContext* GetExecutionContext() const { return window_.Get(); }
int CallCount() const { return call_count_; }
void Trace(Visitor* visitor) override {
ResizeObserver::Delegate::Trace(visitor);
- visitor->Trace(document_);
+ visitor->Trace(window_);
}
private:
- Member<Document> document_;
+ Member<LocalDOMWindow> window_;
int call_count_;
};
@@ -73,8 +72,8 @@ TEST_F(ResizeObserverUnitTest, ResizeObserverDOMContentBoxAndSVG) {
main_resource.Finish();
ResizeObserver::Delegate* delegate =
- MakeGarbageCollected<TestResizeObserverDelegate>(GetDocument());
- ResizeObserver* observer = ResizeObserver::Create(GetDocument(), delegate);
+ MakeGarbageCollected<TestResizeObserverDelegate>(Window());
+ ResizeObserver* observer = ResizeObserver::Create(&Window(), delegate);
Element* dom_target = GetDocument().getElementById("domTarget");
Element* svg_target = GetDocument().getElementById("svgTarget");
ResizeObservation* dom_observation = MakeGarbageCollected<ResizeObservation>(
@@ -118,8 +117,8 @@ TEST_F(ResizeObserverUnitTest, ResizeObserverDOMBorderBox) {
main_resource.Finish();
ResizeObserver::Delegate* delegate =
- MakeGarbageCollected<TestResizeObserverDelegate>(GetDocument());
- ResizeObserver* observer = ResizeObserver::Create(GetDocument(), delegate);
+ MakeGarbageCollected<TestResizeObserverDelegate>(Window());
+ ResizeObserver* observer = ResizeObserver::Create(&Window(), delegate);
Element* dom_border_target = GetDocument().getElementById("domBorderTarget");
ResizeObservation* dom_border_observation =
MakeGarbageCollected<ResizeObservation>(
@@ -153,8 +152,8 @@ TEST_F(ResizeObserverUnitTest, ResizeObserverDOMDevicePixelContentBox) {
main_resource.Finish();
ResizeObserver::Delegate* delegate =
- MakeGarbageCollected<TestResizeObserverDelegate>(GetDocument());
- ResizeObserver* observer = ResizeObserver::Create(GetDocument(), delegate);
+ MakeGarbageCollected<TestResizeObserverDelegate>(Window());
+ ResizeObserver* observer = ResizeObserver::Create(&Window(), delegate);
Element* dom_target = GetDocument().getElementById("domTarget");
Element* dom_dp_target = GetDocument().getElementById("domDPTarget");
@@ -205,8 +204,8 @@ TEST_F(ResizeObserverUnitTest, TestBoxOverwrite) {
border_box_option->setBox("border-box");
ResizeObserver::Delegate* delegate =
- MakeGarbageCollected<TestResizeObserverDelegate>(GetDocument());
- ResizeObserver* observer = ResizeObserver::Create(GetDocument(), delegate);
+ MakeGarbageCollected<TestResizeObserverDelegate>(Window());
+ ResizeObserver* observer = ResizeObserver::Create(&Window(), delegate);
Element* dom_target = GetDocument().getElementById("domTarget");
// Assert no observations (depth returned is kDepthBottom)
@@ -251,7 +250,7 @@ TEST_F(ResizeObserverUnitTest, TestNonBoxTarget) {
TEST_F(ResizeObserverUnitTest, TestMemoryLeaks) {
ResizeObserverController& controller =
- GetDocument().EnsureResizeObserverController();
+ *ResizeObserverController::From(Window());
const HeapLinkedHashSet<WeakMember<ResizeObserver>>& observers =
controller.Observers();
ASSERT_EQ(observers.size(), 0U);
@@ -272,9 +271,7 @@ TEST_F(ResizeObserverUnitTest, TestMemoryLeaks) {
ScriptSourceCode("ro = undefined;"), KURL(),
SanitizeScriptErrors::kSanitize, ScriptFetchOptions(),
ScriptController::kExecuteScriptWhenScriptsDisabled);
- V8GCController::CollectAllGarbageForTesting(
- v8::Isolate::GetCurrent(),
- v8::EmbedderHeapTracer::EmbedderStackState::kEmpty);
+ ThreadState::Current()->CollectAllGarbageForTesting();
WebHeap::CollectAllGarbageForTesting();
ASSERT_EQ(observers.IsEmpty(), true);
@@ -289,18 +286,14 @@ TEST_F(ResizeObserverUnitTest, TestMemoryLeaks) {
KURL(), SanitizeScriptErrors::kSanitize, ScriptFetchOptions(),
ScriptController::kExecuteScriptWhenScriptsDisabled);
ASSERT_EQ(observers.size(), 1U);
- V8GCController::CollectAllGarbageForTesting(
- v8::Isolate::GetCurrent(),
- v8::EmbedderHeapTracer::EmbedderStackState::kEmpty);
+ ThreadState::Current()->CollectAllGarbageForTesting();
WebHeap::CollectAllGarbageForTesting();
ASSERT_EQ(observers.size(), 1U);
script_controller.ExecuteScriptInMainWorldAndReturnValue(
ScriptSourceCode("el = undefined;"), KURL(),
SanitizeScriptErrors::kSanitize, ScriptFetchOptions(),
ScriptController::kExecuteScriptWhenScriptsDisabled);
- V8GCController::CollectAllGarbageForTesting(
- v8::Isolate::GetCurrent(),
- v8::EmbedderHeapTracer::EmbedderStackState::kEmpty);
+ ThreadState::Current()->CollectAllGarbageForTesting();
WebHeap::CollectAllGarbageForTesting();
ASSERT_EQ(observers.IsEmpty(), true);
}
diff --git a/chromium/third_party/blink/renderer/core/scheduler_integration_tests/frame_throttling_test.cc b/chromium/third_party/blink/renderer/core/scheduler_integration_tests/frame_throttling_test.cc
index 18b79eaea43..b137d33dc27 100644
--- a/chromium/third_party/blink/renderer/core/scheduler_integration_tests/frame_throttling_test.cc
+++ b/chromium/third_party/blink/renderer/core/scheduler_integration_tests/frame_throttling_test.cc
@@ -337,7 +337,7 @@ TEST_P(FrameThrottlingTest, ThrottledLifecycleUpdate) {
frame_document->Lifecycle().GetState());
// A hit test will not force a complete lifecycle update.
- WebView().HitTestResultAt(gfx::Point());
+ WebView().HitTestResultAt(gfx::PointF());
EXPECT_EQ(DocumentLifecycle::kPaintClean,
frame_document->Lifecycle().GetState());
} else {
@@ -347,7 +347,7 @@ TEST_P(FrameThrottlingTest, ThrottledLifecycleUpdate) {
frame_document->Lifecycle().GetState());
// A hit test will not force a complete lifecycle update.
- WebView().HitTestResultAt(gfx::Point());
+ WebView().HitTestResultAt(gfx::PointF());
EXPECT_EQ(DocumentLifecycle::kPaintClean,
frame_document->Lifecycle().GetState());
}
diff --git a/chromium/third_party/blink/renderer/core/script/classic_pending_script.cc b/chromium/third_party/blink/renderer/core/script/classic_pending_script.cc
index 99d8e6a6d81..c3838502cf1 100644
--- a/chromium/third_party/blink/renderer/core/script/classic_pending_script.cc
+++ b/chromium/third_party/blink/renderer/core/script/classic_pending_script.cc
@@ -258,9 +258,8 @@ void ClassicPendingScript::NotifyFinished(Resource* resource) {
DCHECK(GetResource());
ScriptElementBase* element = GetElement();
if (element) {
- SubresourceIntegrityHelper::DoReport(
- *element->GetDocument().GetExecutionContext(),
- GetResource()->IntegrityReportInfo());
+ SubresourceIntegrityHelper::DoReport(*element->GetExecutionContext(),
+ GetResource()->IntegrityReportInfo());
// It is possible to get back a script resource with integrity metadata
// for a request with an empty integrity attribute. In that case, the
diff --git a/chromium/third_party/blink/renderer/core/script/document_modulator_impl.cc b/chromium/third_party/blink/renderer/core/script/document_modulator_impl.cc
index f8edf807ba6..9f1699c909f 100644
--- a/chromium/third_party/blink/renderer/core/script/document_modulator_impl.cc
+++ b/chromium/third_party/blink/renderer/core/script/document_modulator_impl.cc
@@ -4,7 +4,7 @@
#include "third_party/blink/renderer/core/script/document_modulator_impl.h"
-#include "third_party/blink/renderer/core/dom/document.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/settings.h"
#include "third_party/blink/renderer/core/loader/modulescript/document_module_script_fetcher.h"
@@ -27,8 +27,8 @@ bool DocumentModulatorImpl::IsDynamicImportForbidden(String* reason) {
}
V8CacheOptions DocumentModulatorImpl::GetV8CacheOptions() const {
- Document* document = Document::From(GetExecutionContext());
- const Settings* settings = document->GetFrame()->GetSettings();
+ LocalDOMWindow* window = To<LocalDOMWindow>(GetExecutionContext());
+ const Settings* settings = window->GetFrame()->GetSettings();
if (settings)
return settings->GetV8CacheOptions();
return kV8CacheOptionsDefault;
diff --git a/chromium/third_party/blink/renderer/core/script/dynamic_module_resolver.cc b/chromium/third_party/blink/renderer/core/script/dynamic_module_resolver.cc
index d0eb4560747..5b317c6c994 100644
--- a/chromium/third_party/blink/renderer/core/script/dynamic_module_resolver.cc
+++ b/chromium/third_party/blink/renderer/core/script/dynamic_module_resolver.cc
@@ -4,8 +4,11 @@
#include "third_party/blink/renderer/core/script/dynamic_module_resolver.h"
+#include "base/feature_list.h"
+#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/platform/web_url_request.h"
#include "third_party/blink/renderer/bindings/core/v8/referrer_script_info.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_function.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
#include "third_party/blink/renderer/core/loader/modulescript/module_script_fetch_request.h"
#include "third_party/blink/renderer/core/script/modulator.h"
@@ -38,6 +41,84 @@ class DynamicImportTreeClient final : public ModuleTreeClient {
const Member<ScriptPromiseResolver> promise_resolver_;
};
+// Abstract callback for modules resolution.
+class ModuleResolutionCallback : public ScriptFunction {
+ public:
+ ModuleResolutionCallback(ScriptState* script_state,
+ ScriptPromiseResolver* promise_resolver)
+ : ScriptFunction(script_state), promise_resolver_(promise_resolver) {}
+
+ void Trace(Visitor* visitor) override {
+ visitor->Trace(promise_resolver_);
+ ScriptFunction::Trace(visitor);
+ }
+
+ protected:
+ Member<ScriptPromiseResolver> promise_resolver_;
+};
+
+// Callback for modules with top-level await.
+// Called on successful resolution.
+class ModuleResolutionSuccessCallback final : public ModuleResolutionCallback {
+ public:
+ ModuleResolutionSuccessCallback(ScriptState* script_state,
+ ScriptPromiseResolver* promise_resolver,
+ ModuleScript* module_script)
+ : ModuleResolutionCallback(script_state, promise_resolver),
+ module_script_(module_script) {}
+
+ static v8::Local<v8::Function> CreateFunction(
+ ScriptState* script_state,
+ ScriptPromiseResolver* promise_resolver,
+ ModuleScript* module_script) {
+ ModuleResolutionSuccessCallback* self =
+ MakeGarbageCollected<ModuleResolutionSuccessCallback>(
+ script_state, promise_resolver, module_script);
+ return self->BindToV8Function();
+ }
+
+ void Trace(Visitor* visitor) final {
+ visitor->Trace(module_script_);
+ ModuleResolutionCallback::Trace(visitor);
+ }
+
+ private:
+ ScriptValue Call(ScriptValue value) override {
+ ScriptState::Scope scope(GetScriptState());
+ v8::Local<v8::Module> record = module_script_->V8Module();
+ v8::Local<v8::Value> module_namespace = ModuleRecord::V8Namespace(record);
+ promise_resolver_->Resolve(module_namespace);
+ return ScriptValue();
+ }
+
+ Member<ModuleScript> module_script_;
+};
+
+// Callback for modules with top-level await.
+// Called on unsuccessful resolution.
+class ModuleResolutionFailureCallback final : public ModuleResolutionCallback {
+ public:
+ ModuleResolutionFailureCallback(ScriptState* script_state,
+ ScriptPromiseResolver* promise_resolver)
+ : ModuleResolutionCallback(script_state, promise_resolver) {}
+
+ static v8::Local<v8::Function> CreateFunction(
+ ScriptState* script_state,
+ ScriptPromiseResolver* promise_resolver) {
+ ModuleResolutionFailureCallback* self =
+ MakeGarbageCollected<ModuleResolutionFailureCallback>(script_state,
+ promise_resolver);
+ return self->BindToV8Function();
+ }
+
+ private:
+ ScriptValue Call(ScriptValue exception) override {
+ ScriptState::Scope scope(GetScriptState());
+ promise_resolver_->Reject(exception);
+ return ScriptValue();
+ }
+};
+
// Implements steps 2.[5-8] of
// <specdef
// href="https://html.spec.whatwg.org/C/#hostimportmoduledynamically(referencingscriptormodule,-specifier,-promisecapability)">
@@ -72,11 +153,11 @@ void DynamicImportTreeClient::NotifyModuleTreeLoadFinished(
// <spec step="7">Run the module script result, with the rethrow errors
// boolean set to true.</spec>
- ScriptValue error = modulator_->ExecuteModule(
+ ModuleEvaluationResult result = modulator_->ExecuteModule(
module_script, Modulator::CaptureEvalErrorFlag::kCapture);
// <spec step="8">If running the module script throws an exception, ...</spec>
- if (!error.IsEmpty()) {
+ if (result.IsException()) {
// <spec step="8">... then perform
// FinishDynamicImport(referencingScriptOrModule, specifier,
// promiseCapability, the thrown exception completion).</spec>
@@ -88,7 +169,7 @@ void DynamicImportTreeClient::NotifyModuleTreeLoadFinished(
// step="1">If completion is an abrupt completion, then perform !
// Call(promiseCapability.[[Reject]], undefined, « completion.[[Value]]
// »).</spec>
- promise_resolver_->Reject(error);
+ promise_resolver_->Reject(result.GetException());
return;
}
@@ -100,7 +181,19 @@ void DynamicImportTreeClient::NotifyModuleTreeLoadFinished(
// href="https://tc39.github.io/proposal-dynamic-import/#sec-finishdynamicimport"
// step="2.1">Assert: completion is a normal completion and
// completion.[[Value]] is undefined.</spec>
- DCHECK(error.IsEmpty());
+ DCHECK(result.IsSuccess());
+
+ if (base::FeatureList::IsEnabled(features::kTopLevelAwait)) {
+ ScriptPromise promise = result.GetPromise(script_state);
+ v8::Local<v8::Function> callback_success =
+ ModuleResolutionSuccessCallback::CreateFunction(
+ script_state, promise_resolver_, module_script);
+ v8::Local<v8::Function> callback_failure =
+ ModuleResolutionFailureCallback::CreateFunction(script_state,
+ promise_resolver_);
+ promise.Then(callback_success, callback_failure);
+ return;
+ }
// <spec
// href="https://tc39.github.io/proposal-dynamic-import/#sec-finishdynamicimport"
diff --git a/chromium/third_party/blink/renderer/core/script/dynamic_module_resolver_test.cc b/chromium/third_party/blink/renderer/core/script/dynamic_module_resolver_test.cc
index bc58f764374..258e069216c 100644
--- a/chromium/third_party/blink/renderer/core/script/dynamic_module_resolver_test.cc
+++ b/chromium/third_party/blink/renderer/core/script/dynamic_module_resolver_test.cc
@@ -4,7 +4,9 @@
#include "third_party/blink/renderer/core/script/dynamic_module_resolver.h"
+#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/bindings/core/v8/referrer_script_info.h"
#include "third_party/blink/renderer/bindings/core/v8/script_function.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
@@ -15,6 +17,7 @@
#include "third_party/blink/renderer/core/loader/modulescript/module_script_fetch_request.h"
#include "third_party/blink/renderer/core/script/js_module_script.h"
#include "third_party/blink/renderer/core/testing/dummy_modulator.h"
+#include "third_party/blink/renderer/core/testing/module_test_base.h"
#include "v8/include/v8.h"
namespace blink {
@@ -88,13 +91,15 @@ class DynamicModuleResolverTestModulator final : public DummyModulator {
fetch_tree_was_called_ = true;
}
- ScriptValue ExecuteModule(ModuleScript* module_script,
- CaptureEvalErrorFlag capture_error) final {
+ ModuleEvaluationResult ExecuteModule(
+ ModuleScript* module_script,
+ CaptureEvalErrorFlag capture_error) final {
EXPECT_EQ(CaptureEvalErrorFlag::kCapture, capture_error);
- ScriptState::Scope scope(script_state_);
- return ModuleRecord::Evaluate(script_state_, module_script->V8Module(),
- module_script->SourceURL());
+ ScriptState::EscapableScope scope(script_state_);
+ ModuleEvaluationResult result = ModuleRecord::Evaluate(
+ script_state_, module_script->V8Module(), module_script->SourceURL());
+ return result.Escape(&scope);
}
Member<ScriptState> script_state_;
@@ -202,9 +207,17 @@ class DynamicModuleResolverTestNotReached final : public ScriptFunction {
}
};
+class DynamicModuleResolverTest : public testing::Test,
+ public ParametrizedModuleTest {
+ public:
+ void SetUp() override { ParametrizedModuleTest::SetUp(); }
+
+ void TearDown() override { ParametrizedModuleTest::TearDown(); }
+};
+
} // namespace
-TEST(DynamicModuleResolverTest, ResolveSuccess) {
+TEST_P(DynamicModuleResolverTest, ResolveSuccess) {
V8TestingScope scope;
auto* modulator = MakeGarbageCollected<DynamicModuleResolverTestModulator>(
scope.GetScriptState());
@@ -243,7 +256,7 @@ TEST(DynamicModuleResolverTest, ResolveSuccess) {
EXPECT_EQ("hello", capture->CapturedValue());
}
-TEST(DynamicModuleResolverTest, ResolveSpecifierFailure) {
+TEST_P(DynamicModuleResolverTest, ResolveSpecifierFailure) {
V8TestingScope scope;
auto* modulator = MakeGarbageCollected<DynamicModuleResolverTestModulator>(
scope.GetScriptState());
@@ -269,7 +282,7 @@ TEST(DynamicModuleResolverTest, ResolveSpecifierFailure) {
EXPECT_TRUE(capture->Message().StartsWith("Failed to resolve"));
}
-TEST(DynamicModuleResolverTest, FetchFailure) {
+TEST_P(DynamicModuleResolverTest, FetchFailure) {
V8TestingScope scope;
auto* modulator = MakeGarbageCollected<DynamicModuleResolverTestModulator>(
scope.GetScriptState());
@@ -299,7 +312,7 @@ TEST(DynamicModuleResolverTest, FetchFailure) {
EXPECT_TRUE(capture->Message().StartsWith("Failed to fetch"));
}
-TEST(DynamicModuleResolverTest, ExceptionThrown) {
+TEST_P(DynamicModuleResolverTest, ExceptionThrown) {
V8TestingScope scope;
auto* modulator = MakeGarbageCollected<DynamicModuleResolverTestModulator>(
scope.GetScriptState());
@@ -338,7 +351,7 @@ TEST(DynamicModuleResolverTest, ExceptionThrown) {
EXPECT_EQ("bar", capture->Message());
}
-TEST(DynamicModuleResolverTest, ResolveWithNullReferrerScriptSuccess) {
+TEST_P(DynamicModuleResolverTest, ResolveWithNullReferrerScriptSuccess) {
V8TestingScope scope;
scope.GetDocument().SetURL(KURL("https://example.com"));
@@ -379,7 +392,7 @@ TEST(DynamicModuleResolverTest, ResolveWithNullReferrerScriptSuccess) {
EXPECT_EQ("hello", capture->CapturedValue());
}
-TEST(DynamicModuleResolverTest, ResolveWithReferrerScriptInfoBaseURL) {
+TEST_P(DynamicModuleResolverTest, ResolveWithReferrerScriptInfoBaseURL) {
V8TestingScope scope;
scope.GetDocument().SetURL(KURL("https://example.com"));
@@ -402,4 +415,10 @@ TEST(DynamicModuleResolverTest, ResolveWithReferrerScriptInfoBaseURL) {
EXPECT_TRUE(modulator->fetch_tree_was_called());
}
+// Instantiate tests once with TLA and once without:
+INSTANTIATE_TEST_SUITE_P(DynamicModuleResolverTestGroup,
+ DynamicModuleResolverTest,
+ testing::Bool(),
+ ParametrizedModuleTestParamName());
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/script/mock_script_element_base.h b/chromium/third_party/blink/renderer/core/script/mock_script_element_base.h
index 92513c146a2..350d9f0682a 100644
--- a/chromium/third_party/blink/renderer/core/script/mock_script_element_base.h
+++ b/chromium/third_party/blink/renderer/core/script/mock_script_element_base.h
@@ -50,6 +50,7 @@ class MockScriptElementBase : public GarbageCollected<MockScriptElementBase>,
const WTF::OrdinalNumber&,
const String&));
MOCK_CONST_METHOD0(GetDocument, Document&());
+ MOCK_CONST_METHOD0(GetExecutionContext, ExecutionContext*());
MOCK_METHOD1(SetScriptElementForBinding,
void(HTMLScriptElementOrSVGScriptElement&));
MOCK_CONST_METHOD0(Loader, ScriptLoader*());
diff --git a/chromium/third_party/blink/renderer/core/script/modulator.cc b/chromium/third_party/blink/renderer/core/script/modulator.cc
index 2f48e3a2cef..0a2c8ac1595 100644
--- a/chromium/third_party/blink/renderer/core/script/modulator.cc
+++ b/chromium/third_party/blink/renderer/core/script/modulator.cc
@@ -35,12 +35,11 @@ Modulator* Modulator::From(ScriptState* script_state) {
if (modulator)
return modulator;
ExecutionContext* execution_context = ExecutionContext::From(script_state);
- if (auto* document = Document::DynamicFrom(execution_context)) {
+ if (auto* window = DynamicTo<LocalDOMWindow>(execution_context)) {
modulator = MakeGarbageCollected<DocumentModulatorImpl>(script_state);
Modulator::SetModulator(script_state, modulator);
// See comment in LocalDOMWindow::modulator_ for this workaround.
- LocalDOMWindow* window = document->ExecutingWindow();
window->SetModulator(modulator);
} else if (auto* worklet_scope =
DynamicTo<WorkletGlobalScope>(execution_context)) {
diff --git a/chromium/third_party/blink/renderer/core/script/modulator.h b/chromium/third_party/blink/renderer/core/script/modulator.h
index 25985a349da..60512cf7c1a 100644
--- a/chromium/third_party/blink/renderer/core/script/modulator.h
+++ b/chromium/third_party/blink/renderer/core/script/modulator.h
@@ -207,11 +207,14 @@ class CORE_EXPORT Modulator : public GarbageCollected<Modulator>,
// CaptureEvalErrorFlag is used to implement "rethrow errors" parameter in
// run-a-module-script.
// - When "rethrow errors" is to be set, use kCapture for EvaluateModule().
- // Then EvaluateModule() returns an exception if any (instead of throwing it),
- // and the caller should rethrow the returned exception. - When "rethrow
- // errors" is not to be set, use kReport. EvaluateModule() "report the error"
- // inside it (if any), and always returns null ScriptValue().
- virtual ScriptValue ExecuteModule(ModuleScript*, CaptureEvalErrorFlag) = 0;
+ // Then EvaluateModule() wraps exceptions in a ModuleEvaluationResult instead
+ // of throwing it and the caller should rethrow the exception.
+ // - When "rethrow errors" is not to be set, use kReport. EvaluateModule()
+ // "report the error" inside it (if any), and returns either a
+ // ModuleEvaluationResult that is empty or contains the successful
+ // evaluation result.
+ virtual ModuleEvaluationResult ExecuteModule(ModuleScript*,
+ CaptureEvalErrorFlag) = 0;
virtual ModuleScriptFetcher* CreateModuleScriptFetcher(
ModuleScriptCustomFetchType,
diff --git a/chromium/third_party/blink/renderer/core/script/modulator_impl_base.cc b/chromium/third_party/blink/renderer/core/script/modulator_impl_base.cc
index c86c9be0937..3de8263baaf 100644
--- a/chromium/third_party/blink/renderer/core/script/modulator_impl_base.cc
+++ b/chromium/third_party/blink/renderer/core/script/modulator_impl_base.cc
@@ -3,9 +3,11 @@
// found in the LICENSE file.
#include "third_party/blink/renderer/core/script/modulator_impl_base.h"
-
+#include "base/feature_list.h"
+#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/mojom/devtools/console_message.mojom-blink.h"
#include "third_party/blink/public/platform/task_type.h"
+#include "third_party/blink/renderer/bindings/core/v8/module_record.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/frame/web_feature.h"
@@ -325,7 +327,7 @@ void ModulatorImplBase::ProduceCacheModuleTree(
}
// <specdef href="https://html.spec.whatwg.org/C/#run-a-module-script">
-ScriptValue ModulatorImplBase::ExecuteModule(
+ModuleEvaluationResult ModulatorImplBase::ExecuteModule(
ModuleScript* module_script,
CaptureEvalErrorFlag capture_error) {
// <spec step="1">If rethrow errors is not given, let it be false.</spec>
@@ -337,23 +339,24 @@ ScriptValue ModulatorImplBase::ExecuteModule(
// <spec step="3">Check if we can run script with settings. If this returns
// "do not run" then return NormalCompletion(empty).</spec>
if (IsScriptingDisabled())
- return ScriptValue();
+ return ModuleEvaluationResult::Empty();
// <spec step="4">Prepare to run script given settings.</spec>
//
// This is placed here to also cover ModuleRecord::ReportException().
- ScriptState::Scope scope(script_state_);
+ ScriptState::EscapableScope scope(script_state_);
// <spec step="5">Let evaluationStatus be null.</spec>
//
- // |error| corresponds to "evaluationStatus of [[Type]]: throw".
- ScriptValue error;
+ // |result| corresponds to "evaluationStatus of [[Type]]: throw".
+ ModuleEvaluationResult result = ModuleEvaluationResult::Empty();
// <spec step="6">If script's error to rethrow is not null, ...</spec>
if (module_script->HasErrorToRethrow()) {
// <spec step="6">... then set evaluationStatus to Completion { [[Type]]:
// throw, [[Value]]: script's error to rethrow, [[Target]]: empty }.</spec>
- error = module_script->CreateErrorToRethrow();
+ result = ModuleEvaluationResult::FromException(
+ module_script->CreateErrorToRethrow().V8Value());
} else {
// <spec step="7">Otherwise:</spec>
@@ -362,8 +365,8 @@ ScriptValue ModulatorImplBase::ExecuteModule(
CHECK(!record.IsEmpty());
// <spec step="7.2">Set evaluationStatus to record.Evaluate(). ...</spec>
- error = ModuleRecord::Evaluate(script_state_, record,
- module_script->SourceURL());
+ result = ModuleRecord::Evaluate(script_state_, record,
+ module_script->SourceURL());
// <spec step="7.2">... If Evaluate fails to complete as a result of the
// user agent aborting the running script, then set evaluationStatus to
@@ -371,7 +374,7 @@ ScriptValue ModulatorImplBase::ExecuteModule(
// DOMException, [[Target]]: empty }.</spec>
// [not specced] Store V8 code cache on successful evaluation.
- if (error.IsEmpty()) {
+ if (result.IsSuccess()) {
TaskRunner()->PostTask(
FROM_HERE,
WTF::Bind(&ModulatorImplBase::ProduceCacheModuleTreeTopLevel,
@@ -380,21 +383,24 @@ ScriptValue ModulatorImplBase::ExecuteModule(
}
// <spec step="8">If evaluationStatus is an abrupt completion, then:</spec>
- if (!error.IsEmpty()) {
+ if (result.IsException()) {
// <spec step="8.1">If rethrow errors is true, rethrow the exception given
// by evaluationStatus.[[Value]].</spec>
if (capture_error == CaptureEvalErrorFlag::kCapture)
- return error;
+ return result.Escape(&scope);
// <spec step="8.2">Otherwise, report the exception given by
// evaluationStatus.[[Value]] for script.</spec>
- ModuleRecord::ReportException(script_state_, error.V8Value());
+ ModuleRecord::ReportException(script_state_, result.GetException());
}
// <spec step="9">Clean up after running script with settings.</spec>
//
// Implemented as the ScriptState::Scope destructor.
- return ScriptValue();
+ if (base::FeatureList::IsEnabled(features::kTopLevelAwait))
+ return result.Escape(&scope);
+ else
+ return ModuleEvaluationResult::Empty();
}
void ModulatorImplBase::Trace(Visitor* visitor) {
diff --git a/chromium/third_party/blink/renderer/core/script/modulator_impl_base.h b/chromium/third_party/blink/renderer/core/script/modulator_impl_base.h
index fcae74ca783..be2a95e7f1d 100644
--- a/chromium/third_party/blink/renderer/core/script/modulator_impl_base.h
+++ b/chromium/third_party/blink/renderer/core/script/modulator_impl_base.h
@@ -89,7 +89,8 @@ class ModulatorImplBase : public Modulator {
ScriptValue InstantiateModule(v8::Local<v8::Module>, const KURL&) override;
Vector<ModuleRequest> ModuleRequestsFromModuleRecord(
v8::Local<v8::Module>) override;
- ScriptValue ExecuteModule(ModuleScript*, CaptureEvalErrorFlag) override;
+ ModuleEvaluationResult ExecuteModule(ModuleScript*,
+ CaptureEvalErrorFlag) override;
// Populates |reason| and returns true if the dynamic import is disallowed on
// the associated execution context. In that case, a caller of this function
diff --git a/chromium/third_party/blink/renderer/core/script/module_map_test.cc b/chromium/third_party/blink/renderer/core/script/module_map_test.cc
index 93738d839f8..193deaab4f9 100644
--- a/chromium/third_party/blink/renderer/core/script/module_map_test.cc
+++ b/chromium/third_party/blink/renderer/core/script/module_map_test.cc
@@ -16,6 +16,7 @@
#include "third_party/blink/renderer/core/script/module_script.h"
#include "third_party/blink/renderer/core/testing/dummy_modulator.h"
#include "third_party/blink/renderer/core/testing/dummy_page_holder.h"
+#include "third_party/blink/renderer/core/testing/module_test_base.h"
#include "third_party/blink/renderer/core/testing/page_test_base.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/loader/fetch/fetch_client_settings_object_snapshot.h"
@@ -189,9 +190,10 @@ void ModuleMapTestModulator::ResolveFetches() {
test_requests_.clear();
}
-class ModuleMapTest : public PageTestBase {
+class ModuleMapTest : public PageTestBase, public ParametrizedModuleTest {
public:
void SetUp() override;
+ void TearDown() override;
ModuleMapTestModulator* Modulator() { return modulator_.Get(); }
ModuleMap* Map() { return map_; }
@@ -202,6 +204,7 @@ class ModuleMapTest : public PageTestBase {
};
void ModuleMapTest::SetUp() {
+ ParametrizedModuleTest::SetUp();
PageTestBase::SetUp(IntSize(500, 500));
NavigateTo(KURL("https://example.com"));
modulator_ = MakeGarbageCollected<ModuleMapTestModulator>(
@@ -209,7 +212,12 @@ void ModuleMapTest::SetUp() {
map_ = MakeGarbageCollected<ModuleMap>(modulator_);
}
-TEST_F(ModuleMapTest, sequentialRequests) {
+void ModuleMapTest::TearDown() {
+ ParametrizedModuleTest::TearDown();
+ PageTestBase::TearDown();
+}
+
+TEST_P(ModuleMapTest, sequentialRequests) {
ScopedTestingPlatformSupport<TestingPlatformSupportWithMockScheduler>
platform;
platform->AdvanceClockSeconds(1.); // For non-zero DocumentParserTimings
@@ -256,7 +264,7 @@ TEST_F(ModuleMapTest, sequentialRequests) {
EXPECT_TRUE(client2->GetModuleScript());
}
-TEST_F(ModuleMapTest, concurrentRequestsShouldJoin) {
+TEST_P(ModuleMapTest, concurrentRequestsShouldJoin) {
ScopedTestingPlatformSupport<TestingPlatformSupportWithMockScheduler>
platform;
platform->AdvanceClockSeconds(1.); // For non-zero DocumentParserTimings
@@ -296,5 +304,10 @@ TEST_F(ModuleMapTest, concurrentRequestsShouldJoin) {
EXPECT_TRUE(client2->WasNotifyFinished());
EXPECT_TRUE(client2->GetModuleScript());
}
+// Instantiate tests once with TLA and once without:
+INSTANTIATE_TEST_SUITE_P(ModuleMapTestGroup,
+ ModuleMapTest,
+ testing::Bool(),
+ ParametrizedModuleTestParamName());
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/script/module_record_resolver_impl_test.cc b/chromium/third_party/blink/renderer/core/script/module_record_resolver_impl_test.cc
index 21cfd612c98..98df6107d5b 100644
--- a/chromium/third_party/blink/renderer/core/script/module_record_resolver_impl_test.cc
+++ b/chromium/third_party/blink/renderer/core/script/module_record_resolver_impl_test.cc
@@ -4,12 +4,15 @@
#include "third_party/blink/renderer/core/script/module_record_resolver_impl.h"
+#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/public/platform/platform.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h"
#include "third_party/blink/renderer/core/script/js_module_script.h"
#include "third_party/blink/renderer/core/script/modulator.h"
#include "third_party/blink/renderer/core/testing/dummy_modulator.h"
+#include "third_party/blink/renderer/core/testing/module_test_base.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"
#include "third_party/blink/renderer/platform/bindings/v8_throw_exception.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
@@ -104,7 +107,8 @@ ModuleScript* CreateTargetModuleScript(Modulator* modulator,
} // namespace
-class ModuleRecordResolverImplTest : public testing::Test {
+class ModuleRecordResolverImplTest : public testing::Test,
+ public ParametrizedModuleTest {
public:
void SetUp() override;
@@ -119,11 +123,12 @@ class ModuleRecordResolverImplTest : public testing::Test {
};
void ModuleRecordResolverImplTest::SetUp() {
+ ParametrizedModuleTest::SetUp();
platform_->AdvanceClockSeconds(1.); // For non-zero DocumentParserTimings
modulator_ = MakeGarbageCollected<ModuleRecordResolverImplTestModulator>();
}
-TEST_F(ModuleRecordResolverImplTest, RegisterResolveSuccess) {
+TEST_P(ModuleRecordResolverImplTest, RegisterResolveSuccess) {
V8TestingScope scope;
ModuleRecordResolver* resolver =
MakeGarbageCollected<ModuleRecordResolverImpl>(
@@ -148,4 +153,10 @@ TEST_F(ModuleRecordResolverImplTest, RegisterResolveSuccess) {
<< "Unexpectedly fetched URL: " << modulator_->FetchedUrl().GetString();
}
+// Instantiate tests once with TLA and once without:
+INSTANTIATE_TEST_SUITE_P(ModuleRecordResolverImplTestGroup,
+ ModuleRecordResolverImplTest,
+ testing::Bool(),
+ ParametrizedModuleTestParamName());
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/script/module_script.cc b/chromium/third_party/blink/renderer/core/script/module_script.cc
index 2da6b2d4965..1274503deb5 100644
--- a/chromium/third_party/blink/renderer/core/script/module_script.cc
+++ b/chromium/third_party/blink/renderer/core/script/module_script.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/core/script/module_script.h"
+#include "third_party/blink/renderer/bindings/core/v8/module_record.h"
#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
#include "third_party/blink/renderer/core/script/module_record_resolver.h"
#include "third_party/blink/renderer/core/workers/worker_global_scope.h"
@@ -101,12 +102,19 @@ void ModuleScript::Trace(Visitor* visitor) {
}
void ModuleScript::RunScript(LocalFrame* frame, const SecurityOrigin*) {
+ // We need a HandleScope for the ModuleEvaluationResult that is created
+ // in ::ExecuteModule(...).
+ ScriptState::Scope scope(SettingsObject()->GetScriptState());
DVLOG(1) << *this << "::RunScript()";
+
SettingsObject()->ExecuteModule(this,
Modulator::CaptureEvalErrorFlag::kReport);
}
void ModuleScript::RunScriptOnWorker(WorkerGlobalScope& worker_global_scope) {
+ // We need a HandleScope for the ModuleEvaluationResult that is created
+ // in ::ExecuteModule(...).
+ ScriptState::Scope scope(SettingsObject()->GetScriptState());
DCHECK(worker_global_scope.IsContextThread());
WorkerReportingProxy& worker_reporting_proxy =
@@ -116,9 +124,9 @@ void ModuleScript::RunScriptOnWorker(WorkerGlobalScope& worker_global_scope) {
// This |error| is always null because the second argument is |kReport|.
// TODO(nhiroki): Catch an error when an evaluation error happens.
// (https://crbug.com/680046)
- ScriptValue error = SettingsObject()->ExecuteModule(
+ ModuleEvaluationResult result = SettingsObject()->ExecuteModule(
this, Modulator::CaptureEvalErrorFlag::kReport);
- worker_reporting_proxy.DidEvaluateModuleScript(error.IsEmpty());
+ worker_reporting_proxy.DidEvaluateModuleScript(result.IsSuccess());
}
std::ostream& operator<<(std::ostream& stream,
diff --git a/chromium/third_party/blink/renderer/core/script/module_script_test.cc b/chromium/third_party/blink/renderer/core/script/module_script_test.cc
index dcda9136481..5bab441e36d 100644
--- a/chromium/third_party/blink/renderer/core/script/module_script_test.cc
+++ b/chromium/third_party/blink/renderer/core/script/module_script_test.cc
@@ -15,6 +15,7 @@
#include "third_party/blink/renderer/core/script/js_module_script.h"
#include "third_party/blink/renderer/core/script/value_wrapper_synthetic_module_script.h"
#include "third_party/blink/renderer/core/testing/dummy_modulator.h"
+#include "third_party/blink/renderer/core/testing/module_test_base.h"
#include "third_party/blink/renderer/core/testing/page_test_base.h"
#include "third_party/blink/renderer/platform/loader/fetch/cached_metadata.h"
#include "third_party/blink/renderer/platform/loader/fetch/cached_metadata_handler.h"
@@ -62,7 +63,7 @@ static const int kScriptRepeatLength = 500;
} // namespace
-class ModuleScriptTest : public ::testing::Test {
+class ModuleScriptTest : public ::testing::Test, public ParametrizedModuleTest {
protected:
static String LargeSourceText() {
StringBuilder builder;
@@ -127,13 +128,20 @@ class ModuleScriptTest : public ::testing::Test {
return handler->cached_metadata_discarded_;
}
+ void SetUp() override { ParametrizedModuleTest::SetUp(); }
+
+ void TearDown() override {
+ feature_list_.Reset();
+ ParametrizedModuleTest::TearDown();
+ }
+
base::test::ScopedFeatureList feature_list_;
};
// Test expectations depends on heuristics in V8CodeCache and therefore these
// tests should be updated if necessary when V8CodeCache is modified. The
// version without code cache discarding.
-TEST_F(ModuleScriptTest, V8CodeCacheWithoutDiscarding) {
+TEST_P(ModuleScriptTest, V8CodeCacheWithoutDiscarding) {
feature_list_.InitAndDisableFeature(
blink::features::kDiscardCodeCacheAfterFirstUse);
using Checkpoint = testing::StrictMock<testing::MockFunction<void(int)>>;
@@ -166,7 +174,7 @@ TEST_F(ModuleScriptTest, V8CodeCacheWithoutDiscarding) {
ASSERT_TRUE(ModuleRecord::Evaluate(scope.GetScriptState(),
module_script->V8Module(),
module_script->SourceURL())
- .IsEmpty());
+ .IsSuccess());
TestFoo(scope);
Checkpoint checkpoint;
@@ -259,7 +267,7 @@ TEST_F(ModuleScriptTest, V8CodeCacheWithoutDiscarding) {
// Test expectations depends on heuristics in V8CodeCache and therefore these
// tests should be updated if necessary when V8CodeCache is modified. The
// version with code cache discarding.
-TEST_F(ModuleScriptTest, V8CodeCacheWithDiscarding) {
+TEST_P(ModuleScriptTest, V8CodeCacheWithDiscarding) {
feature_list_.InitAndEnableFeature(
blink::features::kDiscardCodeCacheAfterFirstUse);
using Checkpoint = testing::StrictMock<testing::MockFunction<void(int)>>;
@@ -292,7 +300,7 @@ TEST_F(ModuleScriptTest, V8CodeCacheWithDiscarding) {
ASSERT_TRUE(ModuleRecord::Evaluate(scope.GetScriptState(),
module_script->V8Module(),
module_script->SourceURL())
- .IsEmpty());
+ .IsSuccess());
TestFoo(scope);
Checkpoint checkpoint;
@@ -397,7 +405,7 @@ TEST_F(ModuleScriptTest, V8CodeCacheWithDiscarding) {
EXPECT_FALSE(cache_handler->GetCachedMetadata(kCodeTag));
}
-TEST_F(ModuleScriptTest, ValueWrapperSyntheticModuleScript) {
+TEST_P(ModuleScriptTest, ValueWrapperSyntheticModuleScript) {
V8TestingScope scope;
v8::Local<v8::Value> local_value(v8::Number::New(scope.GetIsolate(), 1234));
Modulator* modulator =
@@ -407,4 +415,10 @@ TEST_F(ModuleScriptTest, ValueWrapperSyntheticModuleScript) {
ASSERT_FALSE(module_script->V8Module().IsEmpty());
}
+// Instantiate tests once with TLA and once without:
+INSTANTIATE_TEST_SUITE_P(ModuleScriptTestGroup,
+ ModuleScriptTest,
+ testing::Bool(),
+ ParametrizedModuleTestParamName());
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/script/pending_import_map.cc b/chromium/third_party/blink/renderer/core/script/pending_import_map.cc
index 2d51fbf4301..b9bc112044f 100644
--- a/chromium/third_party/blink/renderer/core/script/pending_import_map.cc
+++ b/chromium/third_party/blink/renderer/core/script/pending_import_map.cc
@@ -6,6 +6,7 @@
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
#include "third_party/blink/renderer/core/dom/document.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/script/import_map.h"
#include "third_party/blink/renderer/core/script/modulator.h"
#include "third_party/blink/renderer/core/script/script_element_base.h"
@@ -16,28 +17,26 @@ namespace blink {
PendingImportMap* PendingImportMap::CreateInline(ScriptElementBase& element,
const String& import_map_text,
const KURL& base_url) {
- Document& element_document = element.GetDocument();
- Document* context_document = element_document.ContextDocument();
+ ExecutionContext* context = element.GetExecutionContext();
ScriptState* script_state =
- ToScriptStateForMainWorld(context_document->GetFrame());
+ ToScriptStateForMainWorld(To<LocalDOMWindow>(context)->GetFrame());
Modulator* modulator = Modulator::From(script_state);
ScriptValue error_to_rethrow;
ImportMap* import_map = ImportMap::Parse(
- *modulator, import_map_text, base_url,
- *context_document->GetExecutionContext(), &error_to_rethrow);
+ *modulator, import_map_text, base_url, *context, &error_to_rethrow);
return MakeGarbageCollected<PendingImportMap>(
- script_state, element, import_map, error_to_rethrow, *context_document);
+ script_state, element, import_map, error_to_rethrow, *context);
}
PendingImportMap::PendingImportMap(ScriptState* script_state,
ScriptElementBase& element,
ImportMap* import_map,
ScriptValue error_to_rethrow,
- const Document& original_context_document)
+ const ExecutionContext& original_context)
: element_(&element),
import_map_(import_map),
- original_context_document_(&original_context_document) {
+ original_execution_context_(&original_context) {
if (!error_to_rethrow.IsEmpty()) {
ScriptState::Scope scope(script_state);
error_to_rethrow_.Set(script_state->GetIsolate(),
@@ -72,14 +71,12 @@ void PendingImportMap::RegisterImportMap() const {
//
// <spec step="6">If element’s node document’s relevant settings object is not
// equal to settings object, then return. ...</spec>
- Document* context_document = element_->GetDocument().ContextDocument();
- if (!context_document)
- return;
- if (original_context_document_ != context_document)
+ ExecutionContext* context = element_->GetExecutionContext();
+ if (original_execution_context_ != context)
return;
// Steps 7 and 8.
- LocalFrame* frame = context_document->GetFrame();
+ LocalFrame* frame = To<LocalDOMWindow>(context)->GetFrame();
if (!frame)
return;
@@ -104,7 +101,7 @@ void PendingImportMap::Trace(Visitor* visitor) {
visitor->Trace(element_);
visitor->Trace(import_map_);
visitor->Trace(error_to_rethrow_);
- visitor->Trace(original_context_document_);
+ visitor->Trace(original_execution_context_);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/script/pending_import_map.h b/chromium/third_party/blink/renderer/core/script/pending_import_map.h
index f4005bad221..0f922ff09b6 100644
--- a/chromium/third_party/blink/renderer/core/script/pending_import_map.h
+++ b/chromium/third_party/blink/renderer/core/script/pending_import_map.h
@@ -14,7 +14,7 @@
namespace blink {
-class Document;
+class ExecutionContext;
class ImportMap;
class KURL;
class ScriptElementBase;
@@ -44,7 +44,7 @@ class CORE_EXPORT PendingImportMap final
ScriptElementBase&,
ImportMap*,
ScriptValue error_to_rethrow,
- const Document& original_context_document);
+ const ExecutionContext& original_context);
void RegisterImportMap() const;
@@ -61,10 +61,10 @@ class CORE_EXPORT PendingImportMap final
WorldSafeV8Reference<v8::Value> error_to_rethrow_;
// https://wicg.github.io/import-maps/#import-map-parse-result-settings-object
- // The context document at the time when PrepareScript() is executed.
+ // The context at the time when PrepareScript() is executed.
// This is only used to check whether the script element is moved between
- // documents and thus doesn't retain a strong reference.
- WeakMember<const Document> original_context_document_;
+ // context and thus doesn't retain a strong reference.
+ WeakMember<const ExecutionContext> original_execution_context_;
DISALLOW_COPY_AND_ASSIGN(PendingImportMap);
};
diff --git a/chromium/third_party/blink/renderer/core/script/pending_script.cc b/chromium/third_party/blink/renderer/core/script/pending_script.cc
index 77275af086e..fca268bff72 100644
--- a/chromium/third_party/blink/renderer/core/script/pending_script.cc
+++ b/chromium/third_party/blink/renderer/core/script/pending_script.cc
@@ -25,10 +25,12 @@
#include "third_party/blink/renderer/core/script/pending_script.h"
+#include "third_party/blink/public/mojom/script/script_type.mojom-shared.h"
#include "third_party/blink/public/mojom/web_feature/web_feature.mojom-blink.h"
#include "third_party/blink/renderer/bindings/core/v8/script_controller.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/document_parser_timing.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/script/ignore_destructive_write_count_incrementer.h"
#include "third_party/blink/renderer/core/script/script_element_base.h"
@@ -60,7 +62,7 @@ PendingScript::PendingScript(ScriptElementBase* element,
virtual_time_pauser_(CreateWebScopedVirtualTimePauser(element)),
client_(nullptr),
original_element_document_(&element->GetDocument()),
- original_context_document_(element->GetDocument().ContextDocument()),
+ original_execution_context_(element->GetExecutionContext()),
created_during_document_write_(
element->GetDocument().IsInDocumentWrite()) {}
@@ -128,20 +130,19 @@ void PendingScript::MarkParserBlockingLoadStartTime() {
// <specdef href="https://html.spec.whatwg.org/C/#execute-the-script-block">
void PendingScript::ExecuteScriptBlock(const KURL& document_url) {
TRACE_EVENT0("blink", "PendingScript::ExecuteScriptBlock");
- Document* context_document = element_->GetDocument().ContextDocument();
- if (!context_document) {
+ ExecutionContext* context = element_->GetExecutionContext();
+ if (!context) {
Dispose();
return;
}
- LocalFrame* frame = context_document->GetFrame();
- if (!frame) {
+ if (!To<LocalDOMWindow>(context)->GetFrame()) {
Dispose();
return;
}
- if (OriginalContextDocument() != context_document) {
- // Do not execute scripts if they are moved between context documents.
+ if (original_execution_context_ != context) {
+ // Do not execute scripts if they are moved between contexts.
Dispose();
return;
}
@@ -149,12 +150,6 @@ void PendingScript::ExecuteScriptBlock(const KURL& document_url) {
if (original_element_document_ != &element_->GetDocument()) {
// Do not execute scripts if they are moved between element documents (under
// the same context Document).
-
- // We continue counting for a while to confirm that such cases are really
- // rare on stable channel. https://crbug.com/721914
- UseCounter::Count(context_document,
- WebFeature::kEvaluateScriptMovedBetweenElementDocuments);
-
Dispose();
return;
}
@@ -187,7 +182,8 @@ void PendingScript::ExecuteScriptBlockInternal(
base::TimeTicks parser_blocking_load_start_time,
bool is_controlled_by_script_runner) {
Document& element_document = element->GetDocument();
- Document* context_document = element_document.ContextDocument();
+ Document* context_document =
+ To<LocalDOMWindow>(element_document.GetExecutionContext())->document();
// <spec step="2">If the script's script is null, fire an event named error at
// the element, and return.</spec>
@@ -219,8 +215,9 @@ void PendingScript::ExecuteScriptBlockInternal(
// <spec step="3">If the script is from an external file, or the script's
// type is "module", ...</spec>
const bool needs_increment =
- is_external || script->GetScriptType() == mojom::ScriptType::kModule ||
- is_imported_script;
+ is_external || is_imported_script ||
+ script->GetScriptType() == mojom::blink::ScriptType::kModule;
+
// <spec step="3">... then increment the ignore-destructive-writes counter
// of the script element's node document. Let neutralized doc be that
// Document.</spec>
@@ -297,7 +294,7 @@ void PendingScript::ExecuteScriptBlockInternal(
void PendingScript::Trace(Visitor* visitor) {
visitor->Trace(element_);
visitor->Trace(client_);
- visitor->Trace(original_context_document_);
+ visitor->Trace(original_execution_context_);
visitor->Trace(original_element_document_);
}
diff --git a/chromium/third_party/blink/renderer/core/script/pending_script.h b/chromium/third_party/blink/renderer/core/script/pending_script.h
index 8ba0a5d806a..93d76b77028 100644
--- a/chromium/third_party/blink/renderer/core/script/pending_script.h
+++ b/chromium/third_party/blink/renderer/core/script/pending_script.h
@@ -40,6 +40,7 @@
namespace blink {
+class ExecutionContext;
class PendingScript;
class CORE_EXPORT PendingScriptClient : public GarbageCollectedMixin {
@@ -119,9 +120,6 @@ class CORE_EXPORT PendingScript : public GarbageCollected<PendingScript>,
DCHECK_EQ(scheduling_type_, ScriptSchedulingType::kNotSet);
scheduling_type_ = scheduling_type;
}
- Document* OriginalContextDocument() const {
- return original_context_document_;
- }
bool WasCreatedDuringDocumentWrite() {
return created_during_document_write_;
@@ -171,7 +169,7 @@ class CORE_EXPORT PendingScript : public GarbageCollected<PendingScript>,
// These are only used to check whether the script element is moved between
// documents and thus don't retain a strong references.
WeakMember<Document> original_element_document_;
- WeakMember<Document> original_context_document_;
+ WeakMember<ExecutionContext> original_execution_context_;
const bool created_during_document_write_;
diff --git a/chromium/third_party/blink/renderer/core/script/script_element_base.h b/chromium/third_party/blink/renderer/core/script/script_element_base.h
index 875ac0468e9..55490546971 100644
--- a/chromium/third_party/blink/renderer/core/script/script_element_base.h
+++ b/chromium/third_party/blink/renderer/core/script/script_element_base.h
@@ -31,6 +31,7 @@
namespace blink {
class Document;
class Element;
+class ExecutionContext;
class HTMLScriptElementOrSVGScriptElement;
class ScriptLoader;
@@ -70,7 +71,25 @@ class CORE_EXPORT ScriptElementBase : public GarbageCollectedMixin {
virtual bool AllowInlineScriptForCSP(const AtomicString& nonce,
const WTF::OrdinalNumber&,
const String& script_content) = 0;
+
+ // GetDocument() is "element document", to which the script element belongs
+ // and a parser is attached (in the case of parser-inserted scripts).
+ // GetExecutionContext() is "context window" (LocalDOMWindow),
+ // in which script should be fetched and evaluated,
+ // and its document() was previously known as "context document".
+ // The distinction between the element document and the context document is
+ // important in HTML imports, where:
+ // The element document is HTML-imported Document, and
+ // The context document is the parent Document that triggers HTML imports.
+ //
+ // TODO(hiroshige): After HTML imports implementation is removed, merge
+ // context documents into element documents, because without HTML imports,
+ // they are the same wherever scripting is enabled.
+ // Even after that, some uses of context window will remain, simply as
+ // script element's node document's relevant settings object.
virtual Document& GetDocument() const = 0;
+ virtual ExecutionContext* GetExecutionContext() const = 0;
+
virtual void SetScriptElementForBinding(
HTMLScriptElementOrSVGScriptElement&) = 0;
diff --git a/chromium/third_party/blink/renderer/core/script/script_loader.cc b/chromium/third_party/blink/renderer/core/script/script_loader.cc
index 211d52589e8..2f9144280a1 100644
--- a/chromium/third_party/blink/renderer/core/script/script_loader.cc
+++ b/chromium/third_party/blink/renderer/core/script/script_loader.cc
@@ -35,6 +35,7 @@
#include "third_party/blink/renderer/core/dom/scriptable_document_parser.h"
#include "third_party/blink/renderer/core/dom/text.h"
#include "third_party/blink/renderer/core/frame/csp/content_security_policy.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/html/html_document.h"
#include "third_party/blink/renderer/core/html/imports/html_import.h"
@@ -354,16 +355,17 @@ bool ScriptLoader::PrepareScript(const TextPosition& script_start_position,
if (!element_document.ExecutingFrame())
return false;
- Document* context_document = element_document.ContextDocument();
- if (!context_document || !context_document->ExecutingFrame())
+ LocalDOMWindow* context_window =
+ To<LocalDOMWindow>(element_->GetExecutionContext());
+ if (!context_window->GetFrame())
return false;
- if (!context_document->CanExecuteScripts(kAboutToExecuteScript))
+ if (!context_window->CanExecuteScripts(kAboutToExecuteScript))
return false;
// Accept import maps only if ImportMapsEnabled().
if (is_import_map) {
- Modulator* modulator = Modulator::From(
- ToScriptStateForMainWorld(context_document->GetFrame()));
+ Modulator* modulator =
+ Modulator::From(ToScriptStateForMainWorld(context_window->GetFrame()));
if (!modulator->ImportMapsEnabled()) {
// Import maps should have been rejected in spec Step 7 above.
// TODO(hiroshige): Returning here (i.e. after spec Step 11) is not spec
@@ -440,11 +442,11 @@ bool ScriptLoader::PrepareScript(const TextPosition& script_start_position,
if (!integrity_attr.IsEmpty()) {
SubresourceIntegrity::IntegrityFeatures integrity_features =
SubresourceIntegrityHelper::GetFeatures(
- element_document.ToExecutionContext());
+ element_->GetExecutionContext());
SubresourceIntegrity::ReportInfo report_info;
SubresourceIntegrity::ParseIntegrityAttribute(
integrity_attr, integrity_features, integrity_metadata, &report_info);
- SubresourceIntegrityHelper::DoReport(*element_document.ToExecutionContext(),
+ SubresourceIntegrityHelper::DoReport(*element_->GetExecutionContext(),
report_info);
}
@@ -474,7 +476,7 @@ bool ScriptLoader::PrepareScript(const TextPosition& script_start_position,
IsParserInserted() ? kParserInserted : kNotParserInserted;
if (GetScriptType() == mojom::ScriptType::kModule)
- UseCounter::Count(*context_document, WebFeature::kPrepareModuleScript);
+ UseCounter::Count(*context_window, WebFeature::kPrepareModuleScript);
DCHECK(!prepared_pending_script_);
@@ -493,15 +495,15 @@ bool ScriptLoader::PrepareScript(const TextPosition& script_start_position,
// the "settings object", while in other cases (mainly for module scripts)
// |content_document| is used.
// TODO(hiroshige): Use a consistent Document everywhere.
- auto* fetch_client_settings_object_fetcher = context_document->Fetcher();
+ auto* fetch_client_settings_object_fetcher = context_window->Fetcher();
// https://wicg.github.io/import-maps/#integration-prepare-a-script
// If the script’s type is "importmap" and the element’s node document’s
// acquiring import maps is false, then queue a task to fire an event named
// error at the element, and return. [spec text]
if (is_import_map) {
- Modulator* modulator = Modulator::From(
- ToScriptStateForMainWorld(context_document->GetFrame()));
+ Modulator* modulator =
+ Modulator::From(ToScriptStateForMainWorld(context_window->GetFrame()));
if (!modulator->IsAcquiringImportMaps()) {
element_document.AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>(
mojom::ConsoleMessageSource::kJavaScript,
@@ -586,7 +588,7 @@ bool ScriptLoader::PrepareScript(const TextPosition& script_start_position,
// script CORS setting, and encoding.</spec>
Document* document_for_origin = &element_document;
if (element_document.ImportsController()) {
- document_for_origin = context_document;
+ document_for_origin = context_window->document();
}
FetchClassicScript(url, *document_for_origin, options, cross_origin,
encoding);
@@ -601,7 +603,7 @@ bool ScriptLoader::PrepareScript(const TextPosition& script_start_position,
// Fetch an external module script graph given url, settings object, and
// options.</spec>
Modulator* modulator = Modulator::From(
- ToScriptStateForMainWorld(context_document->GetFrame()));
+ ToScriptStateForMainWorld(context_window->GetFrame()));
FetchModuleScriptTree(url, fetch_client_settings_object_fetcher,
modulator, options);
}
@@ -639,7 +641,7 @@ bool ScriptLoader::PrepareScript(const TextPosition& script_start_position,
// <spec step="25.2">Switch on the script's type:</spec>
if (is_import_map) {
- UseCounter::Count(*context_document, WebFeature::kImportMap);
+ UseCounter::Count(*context_window, WebFeature::kImportMap);
// https://wicg.github.io/import-maps/#integration-prepare-a-script
// 1. Let import map parse result be the result of create an import map
@@ -696,7 +698,7 @@ bool ScriptLoader::PrepareScript(const TextPosition& script_start_position,
// href="https://html.spec.whatwg.org/C/#fetch-an-inline-module-script-graph">
const KURL& source_url = element_document.Url();
Modulator* modulator = Modulator::From(
- ToScriptStateForMainWorld(context_document->GetFrame()));
+ ToScriptStateForMainWorld(context_window->GetFrame()));
// <spec label="fetch-an-inline-module-script-graph" step="1">Let script
// be the result of creating a JavaScript module script using source
@@ -767,8 +769,8 @@ bool ScriptLoader::PrepareScript(const TextPosition& script_start_position,
// Check for external script that should be force deferred.
if (GetScriptType() == mojom::ScriptType::kClassic &&
element_->HasSourceAttribute() &&
- context_document->GetFrame()->ShouldForceDeferScript() &&
- IsA<HTMLDocument>(context_document) && parser_inserted_ &&
+ context_window->GetFrame()->ShouldForceDeferScript() &&
+ IsA<HTMLDocument>(context_window->document()) && parser_inserted_ &&
!element_->AsyncAttributeValue()) {
// In terms of ScriptLoader flags, force deferred scripts behave like
// parser-blocking scripts, except that |force_deferred_| is set.
@@ -814,9 +816,9 @@ bool ScriptLoader::PrepareScript(const TextPosition& script_start_position,
// document of the script element at the time the prepare a script algorithm
// started. ...</spec>
pending_script_ = TakePendingScript(ScriptSchedulingType::kInOrder);
- // TODO(hiroshige): Here |contextDocument| is used as "node document"
+ // TODO(hiroshige): Here the context document is used as "node document"
// while Step 14 uses |elementDocument| as "node document". Fix this.
- context_document->GetScriptRunner()->QueueScriptForExecution(
+ context_window->document()->GetScriptRunner()->QueueScriptForExecution(
pending_script_);
// Note that watchForLoad can immediately call pendingScriptFinished.
pending_script_->WatchForLoad(this);
@@ -840,9 +842,9 @@ bool ScriptLoader::PrepareScript(const TextPosition& script_start_position,
// script is ready, execute the script block and then remove the element
// from the set of scripts that will execute as soon as possible.</spec>
pending_script_ = TakePendingScript(ScriptSchedulingType::kAsync);
- // TODO(hiroshige): Here |contextDocument| is used as "node document"
+ // TODO(hiroshige): Here the context document is used as "node document"
// while Step 14 uses |elementDocument| as "node document". Fix this.
- context_document->GetScriptRunner()->QueueScriptForExecution(
+ context_window->document()->GetScriptRunner()->QueueScriptForExecution(
pending_script_);
// Note that watchForLoad can immediately call pendingScriptFinished.
pending_script_->WatchForLoad(this);
@@ -859,8 +861,8 @@ bool ScriptLoader::PrepareScript(const TextPosition& script_start_position,
DCHECK(!is_external_script_);
// Check for inline script that should be force deferred.
- if (context_document->GetFrame()->ShouldForceDeferScript() &&
- IsA<HTMLDocument>(context_document) && parser_inserted_) {
+ if (context_window->GetFrame()->ShouldForceDeferScript() &&
+ IsA<HTMLDocument>(context_window->document()) && parser_inserted_) {
force_deferred_ = true;
will_be_parser_executed_ = true;
return true;
@@ -981,13 +983,15 @@ void ScriptLoader::PendingScriptFinished(PendingScript* pending_script) {
resource_keep_alive_ = nullptr;
}
- Document* context_document = element_->GetDocument().ContextDocument();
- if (!context_document) {
+ if (!element_->GetExecutionContext()) {
DetachPendingScript();
return;
}
- context_document->GetScriptRunner()->NotifyScriptReady(pending_script);
+ LocalDOMWindow* context_window =
+ To<LocalDOMWindow>(element_->GetExecutionContext());
+ context_window->document()->GetScriptRunner()->NotifyScriptReady(
+ pending_script);
pending_script_->StopWatchingForLoad();
pending_script_ = nullptr;
}
@@ -1045,7 +1049,7 @@ String ScriptLoader::GetScriptText() const {
return child_text_content;
return GetStringForScriptExecution(child_text_content,
element_->GetScriptElementType(),
- element_->GetDocument().ContextDocument());
+ element_->GetExecutionContext());
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/script/script_runner.cc b/chromium/third_party/blink/renderer/core/script/script_runner.cc
index 9a81bdc25bd..5ba5e0baa44 100644
--- a/chromium/third_party/blink/renderer/core/script/script_runner.cc
+++ b/chromium/third_party/blink/renderer/core/script/script_runner.cc
@@ -29,6 +29,7 @@
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/renderer/core/dom/document.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/script/script_loader.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
@@ -40,7 +41,7 @@
namespace blink {
ScriptRunner::ScriptRunner(Document* document)
- : ExecutionContextLifecycleStateObserver(document),
+ : ExecutionContextLifecycleStateObserver(document->GetExecutionContext()),
document_(document),
task_runner_(document->GetTaskRunner(TaskType::kNetworking)) {
DCHECK(document);
@@ -158,27 +159,14 @@ bool ScriptRunner::RemovePendingInOrderScript(PendingScript* pending_script) {
void ScriptRunner::MovePendingScript(Document& old_document,
Document& new_document,
ScriptLoader* script_loader) {
- Document* new_context_document = new_document.ContextDocument();
- if (!new_context_document) {
- // Document's contextDocument() method will return no Document if the
- // following conditions both hold:
- //
- // - The Document wasn't created with an explicit context document
- // and that document is otherwise kept alive.
- // - The Document itself is detached from its frame.
- //
- // The script element's loader is in that case moved to document() and
- // its script runner, which is the non-null Document that contextDocument()
- // would return if not detached.
- DCHECK(!new_document.GetFrame());
- new_context_document = &new_document;
- }
- Document* old_context_document = old_document.ContextDocument();
- if (!old_context_document) {
- DCHECK(!old_document.GetFrame());
- old_context_document = &old_document;
- }
-
+ Document* new_context_document =
+ new_document.GetExecutionContext()
+ ? To<LocalDOMWindow>(new_document.GetExecutionContext())->document()
+ : &new_document;
+ Document* old_context_document =
+ old_document.GetExecutionContext()
+ ? To<LocalDOMWindow>(old_document.GetExecutionContext())->document()
+ : &old_document;
if (old_context_document == new_context_document)
return;
diff --git a/chromium/third_party/blink/renderer/core/script/script_runner_test.cc b/chromium/third_party/blink/renderer/core/script/script_runner_test.cc
index 27fd139e173..422b9f38bfa 100644
--- a/chromium/third_party/blink/renderer/core/script/script_runner_test.cc
+++ b/chromium/third_party/blink/renderer/core/script/script_runner_test.cc
@@ -65,6 +65,8 @@ class MockPendingScript : public PendingScript {
MockScriptElementBase* element = MockScriptElementBase::Create();
EXPECT_CALL(*element, GetDocument())
.WillRepeatedly(testing::ReturnRef(*document));
+ EXPECT_CALL(*element, GetExecutionContext())
+ .WillRepeatedly(testing::Return(document->GetExecutionContext()));
MockPendingScript* pending_script =
MakeGarbageCollected<MockPendingScript>(element, scheduling_type);
EXPECT_CALL(*pending_script, IsExternal()).WillRepeatedly(Return(true));
diff --git a/chromium/third_party/blink/renderer/core/script/value_wrapper_synthetic_module_script.cc b/chromium/third_party/blink/renderer/core/script/value_wrapper_synthetic_module_script.cc
index ddbd7b22482..f07bb63048d 100644
--- a/chromium/third_party/blink/renderer/core/script/value_wrapper_synthetic_module_script.cc
+++ b/chromium/third_party/blink/renderer/core/script/value_wrapper_synthetic_module_script.cc
@@ -10,6 +10,7 @@
#include "third_party/blink/renderer/core/css/css_style_sheet.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/loader/modulescript/module_script_creation_params.h"
#include "third_party/blink/renderer/core/script/modulator.h"
#include "third_party/blink/renderer/core/script/module_record_resolver.h"
@@ -33,8 +34,8 @@ ValueWrapperSyntheticModuleScript::CreateCSSWrapperSyntheticModuleScript(
"ModuleScriptLoader",
"CreateCSSWrapperSyntheticModuleScript");
ExecutionContext* execution_context = ExecutionContext::From(script_state);
- Document* context_document = Document::DynamicFrom(execution_context);
- if (!context_document) {
+ auto* context_window = DynamicTo<LocalDOMWindow>(execution_context);
+ if (!context_window) {
v8::Local<v8::Value> error = V8ThrowException::CreateTypeError(
isolate, "Cannot create CSS Module in non-document context");
return ValueWrapperSyntheticModuleScript::CreateWithError(
@@ -43,7 +44,7 @@ ValueWrapperSyntheticModuleScript::CreateCSSWrapperSyntheticModuleScript(
}
CSSStyleSheetInit* init = CSSStyleSheetInit::Create();
CSSStyleSheet* style_sheet =
- CSSStyleSheet::Create(*context_document, init, exception_state);
+ CSSStyleSheet::Create(*context_window->document(), init, exception_state);
if (exception_state.HadException()) {
v8::Local<v8::Value> error = exception_state.GetException();
exception_state.ClearException();
@@ -206,4 +207,4 @@ void ValueWrapperSyntheticModuleScript::Trace(Visitor* visitor) {
ModuleScript::Trace(visitor);
}
-} // namespace blink \ No newline at end of file
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/scroll/scroll_test.cc b/chromium/third_party/blink/renderer/core/scroll/scroll_test.cc
index 5203ba517a9..11bd7a2e223 100644
--- a/chromium/third_party/blink/renderer/core/scroll/scroll_test.cc
+++ b/chromium/third_party/blink/renderer/core/scroll/scroll_test.cc
@@ -10,6 +10,7 @@
#include "third_party/blink/renderer/core/css/css_style_declaration.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/element.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
#include "third_party/blink/renderer/core/frame/root_frame_viewport.h"
@@ -414,10 +415,10 @@ class ScrollInfacesUseCounterSimTest : public SimTest {
)HTML");
auto& document = GetDocument();
auto* style = document.getElementById("scroller")->style();
- style->setProperty(document.ToExecutionContext(), "direction", direction,
- String(), ASSERT_NO_EXCEPTION);
- style->setProperty(document.ToExecutionContext(), "writing-mode",
- writing_mode, String(), ASSERT_NO_EXCEPTION);
+ style->setProperty(&Window(), "direction", direction, String(),
+ ASSERT_NO_EXCEPTION);
+ style->setProperty(&Window(), "writing-mode", writing_mode, String(),
+ ASSERT_NO_EXCEPTION);
Compositor().BeginFrame();
EXPECT_FALSE(document.IsUseCounted(
WebFeature::
diff --git a/chromium/third_party/blink/renderer/core/scroll/scrollbar.cc b/chromium/third_party/blink/renderer/core/scroll/scrollbar.cc
index ac4f250c127..8c67ff69697 100644
--- a/chromium/third_party/blink/renderer/core/scroll/scrollbar.cc
+++ b/chromium/third_party/blink/renderer/core/scroll/scrollbar.cc
@@ -213,7 +213,7 @@ void Scrollbar::AutoscrollPressedPart(base::TimeDelta delay) {
}
// Handle the arrows and track by injecting a scroll update.
- InjectScrollGestureForPressedPart(WebInputEvent::kGestureScrollUpdate);
+ InjectScrollGestureForPressedPart(WebInputEvent::Type::kGestureScrollUpdate);
// Always start timer when user press on button since scrollable area maybe
// infinite scrolling.
@@ -357,7 +357,7 @@ bool Scrollbar::GestureEvent(const WebGestureEvent& evt,
bool* should_update_capture) {
DCHECK(should_update_capture);
switch (evt.GetType()) {
- case WebInputEvent::kGestureTapDown: {
+ case WebInputEvent::Type::kGestureTapDown: {
IntPoint position = FlooredIntPoint(evt.PositionInRootFrame());
SetPressedPart(GetTheme().HitTestRootFramePosition(*this, position),
evt.GetType());
@@ -367,12 +367,12 @@ bool Scrollbar::GestureEvent(const WebGestureEvent& evt,
*should_update_capture = true;
return true;
}
- case WebInputEvent::kGestureTapCancel:
+ case WebInputEvent::Type::kGestureTapCancel:
if (pressed_part_ != kThumbPart)
return false;
scroll_pos_ = pressed_pos_;
return true;
- case WebInputEvent::kGestureScrollBegin:
+ case WebInputEvent::Type::kGestureScrollBegin:
switch (evt.SourceDevice()) {
case WebGestureDevice::kSyntheticAutoscroll:
case WebGestureDevice::kTouchpad:
@@ -392,7 +392,7 @@ bool Scrollbar::GestureEvent(const WebGestureEvent& evt,
return true;
}
break;
- case WebInputEvent::kGestureScrollUpdate:
+ case WebInputEvent::Type::kGestureScrollUpdate:
switch (evt.SourceDevice()) {
case WebGestureDevice::kSyntheticAutoscroll:
case WebGestureDevice::kTouchpad:
@@ -410,19 +410,19 @@ bool Scrollbar::GestureEvent(const WebGestureEvent& evt,
return true;
}
break;
- case WebInputEvent::kGestureScrollEnd:
+ case WebInputEvent::Type::kGestureScrollEnd:
// If we see a GSE targeted at the scrollbar, clear the state that
// says we injected GestureScrollBegin, since we no longer need to inject
// a GSE ourselves.
injected_gesture_scroll_begin_ = false;
FALLTHROUGH;
- case WebInputEvent::kGestureLongPress:
- case WebInputEvent::kGestureFlingStart:
+ case WebInputEvent::Type::kGestureLongPress:
+ case WebInputEvent::Type::kGestureFlingStart:
scroll_pos_ = 0;
pressed_pos_ = 0;
SetPressedPart(kNoPart, evt.GetType());
return false;
- case WebInputEvent::kGestureTap:
+ case WebInputEvent::Type::kGestureTap:
return HandleTapGesture();
default:
// By default, we assume that gestures don't deselect the scrollbar.
@@ -438,9 +438,11 @@ bool Scrollbar::HandleTapGesture() {
// Taps perform a single scroll begin/update/end sequence of gesture
// events. There's no autoscroll timer since long press is not treated
// the same as holding a mouse down.
- InjectScrollGestureForPressedPart(WebInputEvent::kGestureScrollBegin);
- InjectScrollGestureForPressedPart(WebInputEvent::kGestureScrollUpdate);
- InjectScrollGestureForPressedPart(WebInputEvent::kGestureScrollEnd);
+ InjectScrollGestureForPressedPart(
+ WebInputEvent::Type::kGestureScrollBegin);
+ InjectScrollGestureForPressedPart(
+ WebInputEvent::Type::kGestureScrollUpdate);
+ InjectScrollGestureForPressedPart(WebInputEvent::Type::kGestureScrollEnd);
return true;
}
@@ -542,7 +544,7 @@ void Scrollbar::MouseUp(const WebMouseEvent& mouse_event) {
scrollable_area_->MouseExitedScrollbar(*this);
}
- InjectScrollGestureForPressedPart(WebInputEvent::kGestureScrollEnd);
+ InjectScrollGestureForPressedPart(WebInputEvent::Type::kGestureScrollEnd);
}
}
@@ -804,7 +806,7 @@ void Scrollbar::SetNeedsPaintInvalidation(ScrollbarPart invalid_parts) {
scrollable_area_->SetScrollbarNeedsPaintInvalidation(Orientation());
}
-CompositorElementId Scrollbar::GetElementId() {
+CompositorElementId Scrollbar::GetElementId() const {
DCHECK(scrollable_area_);
return scrollable_area_->GetScrollbarElementId(orientation_);
}
diff --git a/chromium/third_party/blink/renderer/core/scroll/scrollbar.h b/chromium/third_party/blink/renderer/core/scroll/scrollbar.h
index 5082cb9232a..0c90f64ec9e 100644
--- a/chromium/third_party/blink/renderer/core/scroll/scrollbar.h
+++ b/chromium/third_party/blink/renderer/core/scroll/scrollbar.h
@@ -192,7 +192,7 @@ class CORE_EXPORT Scrollbar : public GarbageCollected<Scrollbar>,
// part.
void SetNeedsPaintInvalidation(ScrollbarPart invalid_parts);
- CompositorElementId GetElementId();
+ CompositorElementId GetElementId() const;
float EffectiveZoom() const;
bool ContainerIsRightToLeft() const;
diff --git a/chromium/third_party/blink/renderer/core/scroll/scrollbar_layer_delegate.cc b/chromium/third_party/blink/renderer/core/scroll/scrollbar_layer_delegate.cc
index e8ba3ace2fb..340cd67b2aa 100644
--- a/chromium/third_party/blink/renderer/core/scroll/scrollbar_layer_delegate.cc
+++ b/chromium/third_party/blink/renderer/core/scroll/scrollbar_layer_delegate.cc
@@ -45,6 +45,11 @@ ScrollbarLayerDelegate::ScrollbarLayerDelegate(blink::Scrollbar& scrollbar,
ScrollbarLayerDelegate::~ScrollbarLayerDelegate() = default;
+bool ScrollbarLayerDelegate::IsSame(const cc::Scrollbar& other) const {
+ return scrollbar_.Get() ==
+ static_cast<const ScrollbarLayerDelegate&>(other).scrollbar_.Get();
+}
+
cc::ScrollbarOrientation ScrollbarLayerDelegate::Orientation() const {
if (scrollbar_->Orientation() == kHorizontalScrollbar)
return cc::HORIZONTAL;
diff --git a/chromium/third_party/blink/renderer/core/scroll/scrollbar_layer_delegate.h b/chromium/third_party/blink/renderer/core/scroll/scrollbar_layer_delegate.h
index 0275a3b9284..3eafffa8643 100644
--- a/chromium/third_party/blink/renderer/core/scroll/scrollbar_layer_delegate.h
+++ b/chromium/third_party/blink/renderer/core/scroll/scrollbar_layer_delegate.h
@@ -22,6 +22,7 @@ class CORE_EXPORT ScrollbarLayerDelegate : public cc::Scrollbar {
float device_scale_factor);
// cc::Scrollbar implementation.
+ bool IsSame(const cc::Scrollbar& other) const override;
cc::ScrollbarOrientation Orientation() const override;
bool IsLeftSideVerticalScrollbar() const override;
bool HasThumb() const override;
diff --git a/chromium/third_party/blink/renderer/core/scroll/scrollbar_theme.cc b/chromium/third_party/blink/renderer/core/scroll/scrollbar_theme.cc
index 2f8f6dc37aa..efb2ace6a7b 100644
--- a/chromium/third_party/blink/renderer/core/scroll/scrollbar_theme.cc
+++ b/chromium/third_party/blink/renderer/core/scroll/scrollbar_theme.cc
@@ -191,7 +191,7 @@ int ScrollbarTheme::ThumbPosition(const Scrollbar& scrollbar,
return 0;
float pos = std::max(0.0f, scroll_position) *
(TrackLength(scrollbar) - ThumbLength(scrollbar)) / size;
- return (pos < 1 && pos > 0) ? 1 : pos;
+ return (pos < 1 && pos > 0) ? 1 : base::saturated_cast<int>(pos);
}
return 0;
}
diff --git a/chromium/third_party/blink/renderer/core/scroll/scrollbar_theme_aura_test.cc b/chromium/third_party/blink/renderer/core/scroll/scrollbar_theme_aura_test.cc
index e76a22a47ad..af926f45768 100644
--- a/chromium/third_party/blink/renderer/core/scroll/scrollbar_theme_aura_test.cc
+++ b/chromium/third_party/blink/renderer/core/scroll/scrollbar_theme_aura_test.cc
@@ -49,13 +49,13 @@ void SendEvent(Scrollbar* scrollbar,
blink::WebInputEvent::kScrollbarManipulationHandledOnCompositorThread,
base::TimeTicks::Now());
switch (type) {
- case blink::WebInputEvent::kMouseDown:
+ case blink::WebInputEvent::Type::kMouseDown:
scrollbar->MouseDown(web_mouse_event);
break;
- case blink::WebInputEvent::kMouseMove:
+ case blink::WebInputEvent::Type::kMouseMove:
scrollbar->MouseMoved(web_mouse_event);
break;
- case blink::WebInputEvent::kMouseUp:
+ case blink::WebInputEvent::Type::kMouseUp:
scrollbar->MouseUp(web_mouse_event);
break;
default:
@@ -149,13 +149,16 @@ TEST_F(ScrollbarThemeAuraTest, ScrollbarPartsInvalidationTest) {
scrollbar->ClearTrackNeedsRepaint();
// Tests that mousedown on the thumb causes an invalidation.
- SendEvent(scrollbar, blink::WebInputEvent::kMouseMove, gfx::PointF(10, 20));
- SendEvent(scrollbar, blink::WebInputEvent::kMouseDown, gfx::PointF(10, 20));
+ SendEvent(scrollbar, blink::WebInputEvent::Type::kMouseMove,
+ gfx::PointF(10, 20));
+ SendEvent(scrollbar, blink::WebInputEvent::Type::kMouseDown,
+ gfx::PointF(10, 20));
EXPECT_TRUE(scrollbar->ThumbNeedsRepaint());
// Tests that mouseup on the thumb causes an invalidation.
scrollbar->ClearThumbNeedsRepaint();
- SendEvent(scrollbar, blink::WebInputEvent::kMouseUp, gfx::PointF(10, 20));
+ SendEvent(scrollbar, blink::WebInputEvent::Type::kMouseUp,
+ gfx::PointF(10, 20));
EXPECT_TRUE(scrollbar->ThumbNeedsRepaint());
// Note that, since these tests run with the assumption that the compositor
@@ -189,13 +192,16 @@ TEST_F(ScrollbarThemeAuraTest, ScrollbarPartsInvalidationTest) {
// Tests that mousedown on the arrow causes an invalidation.
scrollbar->ClearTrackNeedsRepaint();
- SendEvent(scrollbar, blink::WebInputEvent::kMouseMove, gfx::PointF(10, 760));
- SendEvent(scrollbar, blink::WebInputEvent::kMouseDown, gfx::PointF(10, 760));
+ SendEvent(scrollbar, blink::WebInputEvent::Type::kMouseMove,
+ gfx::PointF(10, 760));
+ SendEvent(scrollbar, blink::WebInputEvent::Type::kMouseDown,
+ gfx::PointF(10, 760));
EXPECT_TRUE(scrollbar->TrackNeedsRepaint());
// Tests that mouseup on the arrow causes an invalidation.
scrollbar->ClearTrackNeedsRepaint();
- SendEvent(scrollbar, blink::WebInputEvent::kMouseUp, gfx::PointF(10, 760));
+ SendEvent(scrollbar, blink::WebInputEvent::Type::kMouseUp,
+ gfx::PointF(10, 760));
EXPECT_TRUE(scrollbar->TrackNeedsRepaint());
ThreadState::Current()->CollectAllGarbageForTesting();
diff --git a/chromium/third_party/blink/renderer/core/scroll/scrollbar_theme_mac.mm b/chromium/third_party/blink/renderer/core/scroll/scrollbar_theme_mac.mm
index 28ff7ed1e6f..368227b5a29 100644
--- a/chromium/third_party/blink/renderer/core/scroll/scrollbar_theme_mac.mm
+++ b/chromium/third_party/blink/renderer/core/scroll/scrollbar_theme_mac.mm
@@ -236,8 +236,8 @@ CocoaScrollbarPainter::Params GetPaintParams(const Scrollbar& scrollbar,
if (scrollbar.IsLeftSideVerticalScrollbar())
params.orientation = CocoaScrollbarPainter::Orientation::kVerticalOnLeft;
+ params.dark_mode = scrollbar.UsedColorScheme() == WebColorScheme::kDark;
params.overlay = overlay;
- // Only enable dark mode for overlay scrollbars (for now).
if (overlay)
params.dark_mode = scrollbar.GetScrollbarOverlayColorTheme() ==
kScrollbarOverlayColorThemeLight;
diff --git a/chromium/third_party/blink/renderer/core/scroll/scrollbar_theme_overlay_test.cc b/chromium/third_party/blink/renderer/core/scroll/scrollbar_theme_overlay_test.cc
index d27ef082bc3..abb7fa37196 100644
--- a/chromium/third_party/blink/renderer/core/scroll/scrollbar_theme_overlay_test.cc
+++ b/chromium/third_party/blink/renderer/core/scroll/scrollbar_theme_overlay_test.cc
@@ -96,7 +96,8 @@ TEST_F(ScrollbarThemeOverlayTest, PaintInvalidation) {
mock_scrollable_area->ClearNeedsPaintInvalidationForScrollControls();
// Pressing down should also cause an invalidation.
- vertical_scrollbar->SetPressedPart(kThumbPart, WebInputEvent::kMouseDown);
+ vertical_scrollbar->SetPressedPart(kThumbPart,
+ WebInputEvent::Type::kMouseDown);
EXPECT_TRUE(vertical_scrollbar->ThumbNeedsRepaint());
EXPECT_TRUE(mock_scrollable_area->VerticalScrollbarNeedsPaintInvalidation());
@@ -104,7 +105,7 @@ TEST_F(ScrollbarThemeOverlayTest, PaintInvalidation) {
mock_scrollable_area->ClearNeedsPaintInvalidationForScrollControls();
// Release should cause invalidation.
- vertical_scrollbar->SetPressedPart(kNoPart, WebInputEvent::kMouseDown);
+ vertical_scrollbar->SetPressedPart(kNoPart, WebInputEvent::Type::kMouseDown);
EXPECT_TRUE(vertical_scrollbar->ThumbNeedsRepaint());
EXPECT_TRUE(mock_scrollable_area->VerticalScrollbarNeedsPaintInvalidation());
diff --git a/chromium/third_party/blink/renderer/core/streams/readable_stream_default_controller.cc b/chromium/third_party/blink/renderer/core/streams/readable_stream_default_controller.cc
index ce0c2ebbfa9..b349d0fee8d 100644
--- a/chromium/third_party/blink/renderer/core/streams/readable_stream_default_controller.cc
+++ b/chromium/third_party/blink/renderer/core/streams/readable_stream_default_controller.cc
@@ -23,14 +23,6 @@ namespace blink {
ReadableStreamDefaultController::ReadableStreamDefaultController()
: queue_(MakeGarbageCollected<QueueWithSizes>()) {}
-double ReadableStreamDefaultController::desiredSize(bool& is_null) const {
- // https://streams.spec.whatwg.org/#rs-default-controller-desired-size
- // 2. Return ! ReadableStreamDefaultControllerGetDesiredSize(this).
- base::Optional<double> desired_size = GetDesiredSize();
- is_null = !desired_size.has_value();
- return is_null ? 0.0 : desired_size.value();
-}
-
void ReadableStreamDefaultController::close(ScriptState* script_state,
ExceptionState& exception_state) {
// https://streams.spec.whatwg.org/#rs-default-controller-close
diff --git a/chromium/third_party/blink/renderer/core/streams/readable_stream_default_controller.h b/chromium/third_party/blink/renderer/core/streams/readable_stream_default_controller.h
index 8dcbbf3e4ea..02f4a769990 100644
--- a/chromium/third_party/blink/renderer/core/streams/readable_stream_default_controller.h
+++ b/chromium/third_party/blink/renderer/core/streams/readable_stream_default_controller.h
@@ -29,8 +29,6 @@ class ReadableStreamDefaultController : public ScriptWrappable {
// https://streams.spec.whatwg.org/#rs-default-controller-desired-size
base::Optional<double> desiredSize() const { return GetDesiredSize(); }
- // TODO(crbug.com/1060971): Remove |is_null| version.
- double desiredSize(bool& is_null) const; // DEPRECATED
// https://streams.spec.whatwg.org/#rs-default-controller-close
void close(ScriptState*, ExceptionState&);
diff --git a/chromium/third_party/blink/renderer/core/streams/readable_stream_default_controller.idl b/chromium/third_party/blink/renderer/core/streams/readable_stream_default_controller.idl
index 3d2f119b790..e605a1a7d11 100644
--- a/chromium/third_party/blink/renderer/core/streams/readable_stream_default_controller.idl
+++ b/chromium/third_party/blink/renderer/core/streams/readable_stream_default_controller.idl
@@ -3,10 +3,7 @@
// found in the LICENSE file.
// https://streams.spec.whatwg.org/#rs-default-controller-class-definition
-[
- Exposed=(Window,Worker,Worklet),
- NoInterfaceObject
-] interface ReadableStreamDefaultController {
+interface ReadableStreamDefaultController {
[NotEnumerable] readonly attribute double? desiredSize;
[CallWith=ScriptState, NotEnumerable, RaisesException] void close();
[CallWith=ScriptState, NotEnumerable, RaisesException] void enqueue(
diff --git a/chromium/third_party/blink/renderer/core/streams/readable_stream_test.cc b/chromium/third_party/blink/renderer/core/streams/readable_stream_test.cc
index 9601e3ae57e..45e68f90acc 100644
--- a/chromium/third_party/blink/renderer/core/streams/readable_stream_test.cc
+++ b/chromium/third_party/blink/renderer/core/streams/readable_stream_test.cc
@@ -433,8 +433,7 @@ TEST_F(ReadableStreamTest, GarbageCollectJavaScriptUnderlyingSource) {
weak_underlying_source.SetWeak();
}
- V8GCController::CollectAllGarbageForTesting(
- isolate, v8::EmbedderHeapTracer::EmbedderStackState::kEmpty);
+ ThreadState::Current()->CollectAllGarbageForTesting();
EXPECT_TRUE(weak_underlying_source.IsEmpty());
}
@@ -463,8 +462,7 @@ TEST_F(ReadableStreamTest, GarbageCollectCPlusPlusUnderlyingSource) {
// Allow Promises to resolve.
v8::MicrotasksScope::PerformCheckpoint(isolate);
- V8GCController::CollectAllGarbageForTesting(
- isolate, v8::EmbedderHeapTracer::EmbedderStackState::kEmpty);
+ ThreadState::Current()->CollectAllGarbageForTesting();
EXPECT_FALSE(weak_underlying_source);
}
diff --git a/chromium/third_party/blink/renderer/core/streams/transform_stream_default_controller.cc b/chromium/third_party/blink/renderer/core/streams/transform_stream_default_controller.cc
index db3e39a83d2..1949264041e 100644
--- a/chromium/third_party/blink/renderer/core/streams/transform_stream_default_controller.cc
+++ b/chromium/third_party/blink/renderer/core/streams/transform_stream_default_controller.cc
@@ -39,21 +39,6 @@ base::Optional<double> TransformStreamDefaultController::desiredSize() const {
return readable_controller->desiredSize();
}
-double TransformStreamDefaultController::desiredSize(bool& is_null) const {
- // https://streams.spec.whatwg.org/#ts-default-controller-desired-size
- // 2. Let readableController be
- // this.[[controlledTransformStream]].[[readable]].
- // [[readableStreamController]].
- const auto* readable_controller =
- controlled_transform_stream_->readable_->GetController();
-
- // 3. Return !
- // ReadableStreamDefaultControllerGetDesiredSize(readableController).
- // Use the accessor instead as it already has the semantics we need and can't
- // be interfered with from JavaScript.
- return readable_controller->desiredSize(is_null);
-}
-
// The handling of undefined arguments is implicit in the standard, but needs to
// be done explicitly with IDL.
void TransformStreamDefaultController::enqueue(
diff --git a/chromium/third_party/blink/renderer/core/streams/transform_stream_default_controller.h b/chromium/third_party/blink/renderer/core/streams/transform_stream_default_controller.h
index 4e859c06037..39f5b58537a 100644
--- a/chromium/third_party/blink/renderer/core/streams/transform_stream_default_controller.h
+++ b/chromium/third_party/blink/renderer/core/streams/transform_stream_default_controller.h
@@ -27,8 +27,6 @@ class CORE_EXPORT TransformStreamDefaultController : public ScriptWrappable {
// https://streams.spec.whatwg.org/#ts-default-controller-desired-size
base::Optional<double> desiredSize() const;
- // TODO(crbug.com/1060971): Remove |is_null| version.
- double desiredSize(bool& is_null) const; // DEPRECATED
// https://streams.spec.whatwg.org/#ts-default-controller-enqueue
void enqueue(ScriptState*, ExceptionState&);
diff --git a/chromium/third_party/blink/renderer/core/streams/transform_stream_default_controller.idl b/chromium/third_party/blink/renderer/core/streams/transform_stream_default_controller.idl
index 080f78e7a98..02fc1802f9c 100644
--- a/chromium/third_party/blink/renderer/core/streams/transform_stream_default_controller.idl
+++ b/chromium/third_party/blink/renderer/core/streams/transform_stream_default_controller.idl
@@ -5,10 +5,7 @@
// This is only used when the new C++ implementation is enabled.
// https://streams.spec.whatwg.org/#rs-default-controller-class-definition
-[
- Exposed=(Window,Worker,Worklet),
- NoInterfaceObject
-] interface TransformStreamDefaultController {
+interface TransformStreamDefaultController {
[NotEnumerable] readonly attribute double? desiredSize;
[CallWith=ScriptState, NotEnumerable, RaisesException] void enqueue(
optional any chunk);
diff --git a/chromium/third_party/blink/renderer/core/streams/writable_stream.h b/chromium/third_party/blink/renderer/core/streams/writable_stream.h
index 70533b494fa..99775e5fa1e 100644
--- a/chromium/third_party/blink/renderer/core/streams/writable_stream.h
+++ b/chromium/third_party/blink/renderer/core/streams/writable_stream.h
@@ -92,14 +92,6 @@ class CORE_EXPORT WritableStream : public ScriptWrappable {
// Inherited methods used internally.
- // https://streams.spec.whatwg.org/#is-writable-stream-locked
- // TODO(ricea): Delete this variant once the V8 extras implementation is
- // removed.
- base::Optional<bool> IsLocked(ScriptState*, ExceptionState&) const {
- return IsLocked(this);
- }
-
- // This version can't fail.
static bool IsLocked(const WritableStream* stream) { return stream->writer_; }
void Serialize(ScriptState*, MessagePort*, ExceptionState&);
diff --git a/chromium/third_party/blink/renderer/core/streams/writable_stream_default_controller.idl b/chromium/third_party/blink/renderer/core/streams/writable_stream_default_controller.idl
index fd2327f5486..f301939cce7 100644
--- a/chromium/third_party/blink/renderer/core/streams/writable_stream_default_controller.idl
+++ b/chromium/third_party/blink/renderer/core/streams/writable_stream_default_controller.idl
@@ -5,9 +5,6 @@
// This is only used when the new C++ implementation is enabled.
// https://streams.spec.whatwg.org/#ws-default-controller-class-definition
-[
- Exposed=(Window,Worker,Worklet),
- NoInterfaceObject
-] interface WritableStreamDefaultController {
+interface WritableStreamDefaultController {
[CallWith=ScriptState, NotEnumerable] void error(optional any e);
};
diff --git a/chromium/third_party/blink/renderer/core/streams/writable_stream_test.cc b/chromium/third_party/blink/renderer/core/streams/writable_stream_test.cc
index 731c0d3d428..df68988cb50 100644
--- a/chromium/third_party/blink/renderer/core/streams/writable_stream_test.cc
+++ b/chromium/third_party/blink/renderer/core/streams/writable_stream_test.cc
@@ -41,14 +41,10 @@ TEST(WritableStreamTest, GetWriter) {
ASSERT_TRUE(stream);
EXPECT_FALSE(stream->locked());
- EXPECT_EQ(stream->IsLocked(script_state, ASSERT_NO_EXCEPTION),
- base::make_optional(false));
stream->getWriter(script_state, ASSERT_NO_EXCEPTION);
EXPECT_TRUE(stream->locked());
- EXPECT_EQ(stream->IsLocked(script_state, ASSERT_NO_EXCEPTION),
- base::make_optional(true));
}
TEST(WritableStreamTest, Serialize) {
diff --git a/chromium/third_party/blink/renderer/core/style/BUILD.gn b/chromium/third_party/blink/renderer/core/style/BUILD.gn
index 3c0bba4f189..61caa6d6da5 100644
--- a/chromium/third_party/blink/renderer/core/style/BUILD.gn
+++ b/chromium/third_party/blink/renderer/core/style/BUILD.gn
@@ -92,6 +92,8 @@ blink_core_sources("rendering") {
"style_self_alignment_data.h",
"style_variables.cc",
"style_variables.h",
+ "text_decoration_thickness.cc",
+ "text_decoration_thickness.h",
"text_size_adjust.h",
]
}
diff --git a/chromium/third_party/blink/renderer/core/style/computed_style.cc b/chromium/third_party/blink/renderer/core/style/computed_style.cc
index 10d353555c7..d64f2c49712 100644
--- a/chromium/third_party/blink/renderer/core/style/computed_style.cc
+++ b/chromium/third_party/blink/renderer/core/style/computed_style.cc
@@ -76,6 +76,7 @@
#include "third_party/blink/renderer/platform/wtf/math_extras.h"
#include "third_party/blink/renderer/platform/wtf/size_assertions.h"
#include "third_party/blink/renderer/platform/wtf/text/case_map.h"
+#include "third_party/blink/renderer/platform/wtf/text/math_transform.h"
#include "ui/base/ui_base_features.h"
namespace blink {
@@ -101,7 +102,7 @@ struct SameSizeAsComputedStyleBase {
}
private:
- void* data_refs[7];
+ void* data_refs[8];
unsigned bitfields[5];
};
@@ -290,8 +291,16 @@ ComputedStyle::ComputeDifferenceIgnoringInheritedFirstLineStyle(
if (!non_inherited_equal && old_style.HasExplicitlyInheritedProperties()) {
return Difference::kInherited;
}
- if (!old_style.IndependentInheritedEqual(new_style))
+ bool variables_independent = RuntimeEnabledFeatures::CSSCascadeEnabled() &&
+ !old_style.HasVariableReference() &&
+ !old_style.HasVariableDeclaration();
+ bool inherited_variables_equal = old_style.InheritedVariablesEqual(new_style);
+ if (!inherited_variables_equal && !variables_independent)
+ return Difference::kInherited;
+ if (!old_style.IndependentInheritedEqual(new_style) ||
+ !inherited_variables_equal) {
return Difference::kIndependentInherited;
+ }
if (non_inherited_equal) {
DCHECK(old_style == new_style);
if (PseudoElementStylesEqual(old_style, new_style))
@@ -311,6 +320,8 @@ ComputedStyle::ComputeDifferenceIgnoringInheritedFirstLineStyle(
void ComputedStyle::PropagateIndependentInheritedProperties(
const ComputedStyle& parent_style) {
ComputedStyleBase::PropagateIndependentInheritedProperties(parent_style);
+ if (!HasVariableReference() && !HasVariableDeclaration())
+ InheritCustomPropertiesFrom(parent_style);
}
StyleSelfAlignmentData ResolvedSelfAlignment(
@@ -1072,7 +1083,7 @@ void ComputedStyle::UpdateIsStackingContext(bool is_document_element,
}
void ComputedStyle::AddCallbackSelector(const String& selector) {
- if (!CallbackSelectorsInternal().Contains(selector))
+ if (!CallbackSelectors().Contains(selector))
MutableCallbackSelectorsInternal().push_back(selector);
}
@@ -1102,6 +1113,9 @@ static bool IsWillChangeCompositingHintProperty(CSSPropertyID property) {
return true;
switch (property) {
case CSSPropertyID::kOpacity:
+ case CSSPropertyID::kFilter:
+ case CSSPropertyID::kAliasWebkitFilter:
+ case CSSPropertyID::kBackdropFilter:
case CSSPropertyID::kTop:
case CSSPropertyID::kLeft:
case CSSPropertyID::kBottom:
@@ -1336,7 +1350,7 @@ bool ComputedStyle::SetEffectiveZoom(float f) {
float clamped_effective_zoom = clampTo<float>(f, 1e-6, 1e6);
if (EffectiveZoom() == clamped_effective_zoom)
return false;
- SetInternalEffectiveZoom(clamped_effective_zoom);
+ SetEffectiveZoomInternal(clamped_effective_zoom);
// Record UMA for the effective zoom in order to assess the relative
// importance of sub-pixel behavior, and related features and bugs.
// Clamp to a max of 400%, to make the histogram behave better at no
@@ -1454,7 +1468,16 @@ FloatRoundedRect ComputedStyle::GetRoundedInnerBorderFor(
inner_rect_size.ClampNegativeToZero();
inner_rect.SetSize(inner_rect_size);
- FloatRoundedRect rounded_rect(PixelSnappedIntRect(inner_rect));
+ // The standard LayoutRect::PixelSnappedIntRect() method will not
+ // let small sizes snap to zero, but that has the side effect here of
+ // preventing an inner border for a very thin element from snapping to
+ // zero size as occurs when a unit width border is applied to a sub-pixel
+ // sized element. So round without forcing non-near-zero sizes to one.
+ FloatRoundedRect rounded_rect(IntRect(
+ RoundedIntPoint(inner_rect.Location()),
+ IntSize(
+ SnapSizeToPixelAllowingZero(inner_rect.Width(), inner_rect.X()),
+ SnapSizeToPixelAllowingZero(inner_rect.Height(), inner_rect.Y()))));
if (HasBorderRadius()) {
FloatRoundedRect::Radii radii = GetRoundedBorderFor(border_rect).GetRadii();
@@ -1632,6 +1655,26 @@ static String DisableNewGeorgianCapitalLetters(const String& text) {
return result.ToString();
}
+namespace {
+
+// TODO(https://crbug.com/1076420): this needs to handle all text-transform
+// values.
+static void ApplyMathTransform(String* text, ETextTransform math_variant) {
+ DCHECK(math_variant == ETextTransform::kMathAuto);
+ DCHECK_EQ(text->length(), 1u);
+ UChar character = (*text)[0];
+ UChar32 transformed_char = MathVariant((*text)[0]);
+ if (transformed_char == static_cast<UChar32>(character))
+ return;
+
+ Vector<UChar> transformed_text(U16_LENGTH(transformed_char));
+ int i = 0;
+ U16_APPEND_UNSAFE(transformed_text, i, transformed_char);
+ *text = String(transformed_text);
+}
+
+} // namespace
+
void ComputedStyle::ApplyTextTransform(String* text,
UChar previous_character) const {
switch (TextTransform()) {
@@ -1652,6 +1695,10 @@ void ComputedStyle::ApplyTextTransform(String* text,
*text = case_map.ToLower(*text);
return;
}
+ case ETextTransform::kMathAuto:
+ if (text->length() == 1)
+ ApplyMathTransform(text, ETextTransform::kMathAuto);
+ return;
}
NOTREACHED();
}
@@ -1831,6 +1878,17 @@ bool ComputedStyle::HasVariables() const {
HasInitialVariables(InitialDataInternal().get());
}
+HashSet<AtomicString> ComputedStyle::GetVariableNames() const {
+ HashSet<AtomicString> names;
+ if (auto* initial_data = InitialDataInternal().get())
+ initial_data->CollectVariableNames(names);
+ if (auto* inherited_variables = InheritedVariables())
+ inherited_variables->CollectNames(names);
+ if (auto* non_inherited_variables = NonInheritedVariables())
+ non_inherited_variables->CollectNames(names);
+ return names;
+}
+
StyleInheritedVariables* ComputedStyle::InheritedVariables() const {
return InheritedVariablesInternal().get();
}
@@ -2234,11 +2292,9 @@ int ComputedStyle::OutlineOutsetExtent() const {
return 0;
if (OutlineStyleIsAuto()) {
return GraphicsContext::FocusRingOutsetExtent(
- OutlineOffset(), GetDefaultOffsetForFocusRing(),
- std::ceil(GetOutlineStrokeWidthForFocusRing()),
- LayoutTheme::GetTheme().IsFocusRingOutset());
+ OutlineOffsetInt(), std::ceil(GetOutlineStrokeWidthForFocusRing()));
}
- return base::ClampAdd(OutlineWidth(), OutlineOffset()).Max(0);
+ return base::ClampAdd(OutlineWidthInt(), OutlineOffsetInt()).Max(0);
}
float ComputedStyle::GetOutlineStrokeWidthForFocusRing() const {
@@ -2247,31 +2303,14 @@ float ComputedStyle::GetOutlineStrokeWidthForFocusRing() const {
}
#if defined(OS_MACOSX)
- return OutlineWidth();
+ return OutlineWidthInt();
#else
- if (LayoutTheme::GetTheme().IsFocusRingOutset()) {
- return OutlineWidth();
- }
// Draw an outline with thickness in proportion to the zoom level, but never
// so narrow that it becomes invisible.
return std::max(EffectiveZoom(), 1.f);
#endif
}
-int ComputedStyle::GetDefaultOffsetForFocusRing() const {
- if (!::features::IsFormControlsRefreshEnabled())
- return 0;
-
- if (EffectiveAppearance() == kCheckboxPart ||
- EffectiveAppearance() == kRadioPart) {
- return 2;
- } else if (IsLink()) {
- return 1;
- }
-
- return 0;
-}
-
bool ComputedStyle::ColumnRuleEquivalent(
const ComputedStyle& other_style) const {
return ColumnRuleStyle() == other_style.ColumnRuleStyle() &&
diff --git a/chromium/third_party/blink/renderer/core/style/computed_style.h b/chromium/third_party/blink/renderer/core/style/computed_style.h
index c15c7b5417f..0f4b33439a2 100644
--- a/chromium/third_party/blink/renderer/core/style/computed_style.h
+++ b/chromium/third_party/blink/renderer/core/style/computed_style.h
@@ -33,6 +33,7 @@
#include "third_party/blink/renderer/core/css/properties/css_property.h"
#include "third_party/blink/renderer/core/css/style_auto_color.h"
#include "third_party/blink/renderer/core/css/style_color.h"
+#include "third_party/blink/renderer/core/layout/geometry/logical_size.h"
#include "third_party/blink/renderer/core/scroll/scroll_types.h"
#include "third_party/blink/renderer/core/style/border_value.h"
#include "third_party/blink/renderer/core/style/computed_style_base.h"
@@ -94,6 +95,7 @@ typedef Vector<scoped_refptr<const ComputedStyle>, 4> PseudoElementStyleCache;
namespace css_longhand {
+class Appearance;
class BackgroundColor;
class BorderBottomColor;
class BorderLeftColor;
@@ -125,7 +127,6 @@ class Resize;
class StopColor;
class Stroke;
class TextDecorationColor;
-class WebkitAppearance;
class WebkitTapHighlightColor;
class WebkitTextEmphasisColor;
class WebkitTextFillColor;
@@ -238,7 +239,7 @@ class ComputedStyle : public ComputedStyleBase,
friend class LayoutTheme;
friend class StyleAdjuster;
friend class StyleCascade;
- friend class css_longhand::WebkitAppearance;
+ friend class css_longhand::Appearance;
// Editing has to only reveal unvisited info.
friend class ApplyStyleCommand;
// Editing has to only reveal unvisited info.
@@ -435,6 +436,8 @@ class ComputedStyle : public ComputedStyleBase,
DCHECK(BackdropFilterInternal().Get());
return MutableBackdropFilterInternal()->operations_;
}
+ // For containing blocks, use |HasNonInitialBackdropFilter()| which includes
+ // will-change: backdrop-filter.
bool HasBackdropFilter() const {
DCHECK(BackdropFilterInternal().Get());
return !BackdropFilterInternal()->operations_.Operations().IsEmpty();
@@ -457,6 +460,8 @@ class ComputedStyle : public ComputedStyleBase,
DCHECK(FilterInternal().Get());
return FilterInternal()->operations_;
}
+ // For containing blocks, use |HasNonInitialFilter()| which includes
+ // will-change: filter.
bool HasFilter() const {
DCHECK(FilterInternal().Get());
return !FilterInternal()->operations_.Operations().IsEmpty();
@@ -707,7 +712,7 @@ class ComputedStyle : public ComputedStyleBase,
OutlineColorIsCurrentColor() == other.OutlineColorIsCurrentColor() &&
OutlineColor() == other.OutlineColor() &&
OutlineStyle() == other.OutlineStyle() &&
- OutlineOffsetInternal() == other.OutlineOffsetInternal() &&
+ OutlineOffset() == other.OutlineOffset() &&
OutlineStyleIsAuto() == other.OutlineStyleIsAuto();
}
@@ -720,17 +725,22 @@ class ComputedStyle : public ComputedStyleBase,
}
// outline-width
- uint16_t OutlineWidth() const {
+ float OutlineWidth() const {
+ if (OutlineStyle() == EBorderStyle::kNone)
+ return 0;
+ return OutlineWidthInternal();
+ }
+ void SetOutlineWidth(float v) { SetOutlineWidthInternal(LayoutUnit(v)); }
+ // TODO(rego): This is a temporal method that will be removed once we start
+ // using the float OutlineWidth() in the painting code.
+ uint16_t OutlineWidthInt() const {
if (OutlineStyle() == EBorderStyle::kNone)
return 0;
return OutlineWidthInternal().ToUnsigned();
}
- void SetOutlineWidth(uint16_t v) { SetOutlineWidthInternal(LayoutUnit(v)); }
// outline-offset
- int OutlineOffset() const {
- return OutlineOffsetInternal();
- }
+ int16_t OutlineOffsetInt() const { return OutlineOffset().ToInt(); }
// -webkit-perspective-origin-x
const Length& PerspectiveOriginX() const { return PerspectiveOrigin().X(); }
@@ -899,7 +909,6 @@ class ComputedStyle : public ComputedStyleBase,
}
CORE_EXPORT bool SetEffectiveZoom(float);
- float EffectiveZoom() const;
// -webkit-clip-path
bool ClipPathDataEquivalent(const ComputedStyle& other) const {
@@ -1229,6 +1238,7 @@ class ComputedStyle : public ComputedStyleBase,
// Variables.
bool HasVariables() const;
+ CORE_EXPORT HashSet<AtomicString> GetVariableNames() const;
CORE_EXPORT StyleInheritedVariables* InheritedVariables() const;
CORE_EXPORT StyleNonInheritedVariables* NonInheritedVariables() const;
@@ -1261,9 +1271,6 @@ class ComputedStyle : public ComputedStyleBase,
CSSTransitionData& AccessTransitions();
// Callback selectors.
- const Vector<String>& CallbackSelectors() const {
- return CallbackSelectorsInternal();
- }
void AddCallbackSelector(const String& selector);
// Non-property flags.
@@ -1484,6 +1491,13 @@ class ComputedStyle : public ComputedStyleBase,
return WillChangeProperties().Contains(CSSPropertyID::kOpacity);
}
bool HasWillChangeTransformHint() const;
+ bool HasWillChangeFilterHint() const {
+ return WillChangeProperties().Contains(CSSPropertyID::kFilter) ||
+ WillChangeProperties().Contains(CSSPropertyID::kAliasWebkitFilter);
+ }
+ bool HasWillChangeBackdropFilterHint() const {
+ return WillChangeProperties().Contains(CSSPropertyID::kBackdropFilter);
+ }
// Hyphen utility functions.
Hyphenation* GetHyphenation() const;
@@ -2014,7 +2028,6 @@ class ComputedStyle : public ComputedStyleBase,
}
CORE_EXPORT int OutlineOutsetExtent() const;
CORE_EXPORT float GetOutlineStrokeWidthForFocusRing() const;
- CORE_EXPORT int GetDefaultOffsetForFocusRing() const;
bool HasOutlineWithCurrentColor() const {
return HasOutline() && OutlineColor().IsCurrentColor();
}
@@ -2344,7 +2357,19 @@ class ComputedStyle : public ComputedStyleBase,
// Returns |true| if any property that renders using filter operations is
// used (including, but not limited to, 'filter' and 'box-reflect').
bool HasFilterInducingProperty() const {
- return HasFilter() || HasBoxReflect();
+ return HasNonInitialFilter() || HasBoxReflect();
+ }
+
+ // Returns |true| if filter should be considered to have non-initial value
+ // for the purposes of containing blocks.
+ bool HasNonInitialFilter() const {
+ return HasFilter() || HasWillChangeFilterHint();
+ }
+
+ // Returns |true| if backdrop-filter should be considered to have non-initial
+ // value for the purposes of containing blocks.
+ bool HasNonInitialBackdropFilter() const {
+ return HasBackdropFilter() || HasWillChangeBackdropFilterHint();
}
// Returns |true| if opacity should be considered to have non-initial value
@@ -2423,6 +2448,8 @@ class ComputedStyle : public ComputedStyleBase,
bool CanContainAbsolutePositionObjects() const {
return GetPosition() != EPosition::kStatic;
}
+ // TODO(pdr): Should this function be unified with
+ // LayoutObject::ComputeIsFixedContainer?
bool CanContainFixedPositionObjects(bool is_document_element) const {
return HasTransformRelatedProperty() ||
// Filter establishes containing block for non-document elements:
@@ -2430,7 +2457,8 @@ class ComputedStyle : public ComputedStyleBase,
// Backdrop-filter creates a containing block for fixed and absolute
// positioned elements:
// https://drafts.fxtf.org/filter-effects-2/#backdrop-filter-operation
- (!is_document_element && (HasFilter() || HasBackdropFilter()));
+ (!is_document_element &&
+ (HasNonInitialFilter() || HasNonInitialBackdropFilter()));
}
// Whitespace utility functions.
@@ -2500,7 +2528,8 @@ class ComputedStyle : public ComputedStyleBase,
bool HasBoxDecorations() const {
return HasBorderDecoration() || HasBorderRadius() || HasOutline() ||
HasEffectiveAppearance() || BoxShadow() ||
- HasFilterInducingProperty() || HasBackdropFilter() || HasResize();
+ HasFilterInducingProperty() || HasNonInitialBackdropFilter() ||
+ HasResize();
}
// "Box decoration background" includes all box decorations and backgrounds
@@ -2601,6 +2630,15 @@ class ComputedStyle : public ComputedStyleBase,
!ListStyleImage()->ErrorOccurred();
}
+ base::Optional<LogicalSize> LogicalAspectRatio() const {
+ if (!AspectRatio())
+ return base::nullopt;
+ IntSize ratio = *AspectRatio();
+ if (!IsHorizontalWritingMode())
+ ratio = ratio.TransposedSize();
+ return LogicalSize(LayoutUnit(ratio.Width()), LayoutUnit(ratio.Height()));
+ }
+
private:
EClear Clear() const { return ClearInternal(); }
EFloat Floating() const { return FloatingInternal(); }
@@ -2886,7 +2924,7 @@ class ComputedStyle : public ComputedStyleBase,
StyleInheritedVariables& MutableInheritedVariables();
StyleNonInheritedVariables& MutableNonInheritedVariables();
- void SetInitialData(scoped_refptr<StyleInitialData>);
+ CORE_EXPORT void SetInitialData(scoped_refptr<StyleInitialData>);
PhysicalToLogical<const Length&> PhysicalMarginToLogical(
const ComputedStyle& other) const {
@@ -2966,12 +3004,11 @@ class ComputedStyle : public ComputedStyleBase,
UpdatePropertySpecificDifferencesHasAlpha);
FRIEND_TEST_ALL_PREFIXES(ComputedStyleTest, CustomPropertiesEqual_Values);
FRIEND_TEST_ALL_PREFIXES(ComputedStyleTest, CustomPropertiesEqual_Data);
+ FRIEND_TEST_ALL_PREFIXES(ComputedStyleTest, InitialVariableNames);
+ FRIEND_TEST_ALL_PREFIXES(ComputedStyleTest,
+ InitialAndInheritedAndNonInheritedVariableNames);
};
-inline float ComputedStyle::EffectiveZoom() const {
- return InternalEffectiveZoom();
-}
-
inline bool ComputedStyle::HasAnyPseudoElementStyles() const {
return !!PseudoBitsInternal();
}
diff --git a/chromium/third_party/blink/renderer/core/style/computed_style_diff_functions.json5 b/chromium/third_party/blink/renderer/core/style/computed_style_diff_functions.json5
index cd6337fead7..b87986adc2b 100644
--- a/chromium/third_party/blink/renderer/core/style/computed_style_diff_functions.json5
+++ b/chromium/third_party/blink/renderer/core/style/computed_style_diff_functions.json5
@@ -81,9 +81,9 @@
{
name: "DiffNeedsFullLayoutAndPaintInvalidation",
fields_to_diff: ["padding-top", "padding-left", "padding-right",
- "padding-bottom", "-webkit-appearance", "-webkit-line-clamp",
+ "padding-bottom", "appearance", "-webkit-line-clamp",
"text-overflow", "shape-margin", "order", "-webkit-highlight",
- "text-indent", "text-align-last", "TextIndentLine", "-internal-effective-zoom",
+ "text-indent", "text-align-last", "TextIndentLine", "EffectiveZoom",
"word-break", "overflow-wrap", "-webkit-line-break",
"-webkit-text-security", "hyphens", "HyphenationLimitBefore",
"HyphenationLimitAfter", "-webkit-hyphenate-character",
@@ -130,10 +130,6 @@
field_dependencies: ["border-right-width"]
},
{
- method: "HasFilters()",
- field_dependencies: ["filter"]
- },
- {
method: "HasPseudoElementStyle(kPseudoIdScrollbar)",
field_dependencies: ["StyleType"]
},
@@ -270,6 +266,10 @@
method: "Resize()",
field_dependencies: ["resize"]
},
+ {
+ method: "UsedColorScheme()",
+ field_dependencies: ["color-scheme"]
+ },
],
predicates_to_test: [
{
diff --git a/chromium/third_party/blink/renderer/core/style/computed_style_extra_fields.json5 b/chromium/third_party/blink/renderer/core/style/computed_style_extra_fields.json5
index 9327fd02612..4331914478e 100644
--- a/chromium/third_party/blink/renderer/core/style/computed_style_extra_fields.json5
+++ b/chromium/third_party/blink/renderer/core/style/computed_style_extra_fields.json5
@@ -129,6 +129,16 @@
custom_copy: true,
custom_compare: true,
},
+ // Style has applied a non-inherited -internal-light-dark() value from a UA
+ // stylesheet. Since such values have a dependency on the used color-scheme,
+ // we cannot use the MatchedPropertyCache when this flag is set.
+ {
+ name: "HasNonInheritedLightDarkValue",
+ field_template: "monotonic_flag",
+ default_value: "false",
+ custom_copy: true,
+ custom_compare: true,
+ },
// Whether this style is affected by these pseudo-classes.
{
name: "AffectedByFocusWithin",
@@ -166,6 +176,20 @@
custom_copy: true,
custom_compare: true,
},
+ // A property references a variable that needs to be resolved
+ {
+ name: "HasVariableReference",
+ field_template: "monotonic_flag",
+ default_value: "false",
+ custom_compare: true,
+ },
+ // A property which value consists of a custom property declaration.
+ {
+ name: "HasVariableDeclaration",
+ field_template: "monotonic_flag",
+ default_value: "false",
+ custom_compare: true,
+ },
// Explicitly inherits a non-inherited property
{
name: "HasExplicitlyInheritedProperties",
@@ -319,6 +343,15 @@
computed_style_custom_functions: ["getter", "setter"],
},
{
+ name: "EffectiveZoom",
+ inherited: true,
+ field_template: "primitive",
+ type_name: "float",
+ default_value: "1.0f",
+ field_group: "*",
+ computed_style_custom_functions: ["setter"],
+ },
+ {
name: "TextStrokeColorIsCurrentColor",
inherited: true,
field_template: "primitive",
@@ -542,12 +575,13 @@
{
name: "InheritedVariables",
inherited: true,
+ semi_independent_variable: true,
field_template: "external",
type_name: "StyleInheritedVariables",
include_paths: ["third_party/blink/renderer/core/style/style_inherited_variables.h"],
default_value: "nullptr",
wrapper_pointer_name: "scoped_refptr",
- field_group: "*",
+ field_group: "InheritedVariables",
computed_style_custom_functions: ["getter", "setter"],
},
{
@@ -638,7 +672,7 @@
default_value: "Vector<String>()",
include_paths: ["third_party/blink/renderer/platform/wtf/vector.h",
"third_party/blink/renderer/platform/wtf/text/wtf_string.h"],
- computed_style_custom_functions: ["getter", "setter"],
+ computed_style_custom_functions: ["setter"],
},
{
name: "PaintImages",
diff --git a/chromium/third_party/blink/renderer/core/style/computed_style_test.cc b/chromium/third_party/blink/renderer/core/style/computed_style_test.cc
index f20076456e0..f7dce414130 100644
--- a/chromium/third_party/blink/renderer/core/style/computed_style_test.cc
+++ b/chromium/third_party/blink/renderer/core/style/computed_style_test.cc
@@ -16,6 +16,7 @@
#include "third_party/blink/renderer/core/css/css_value_list.h"
#include "third_party/blink/renderer/core/css/parser/css_parser.h"
#include "third_party/blink/renderer/core/css/properties/css_property_ref.h"
+#include "third_party/blink/renderer/core/css/property_registry.h"
#include "third_party/blink/renderer/core/css/resolver/style_resolver_state.h"
#include "third_party/blink/renderer/core/css/style_engine.h"
#include "third_party/blink/renderer/core/dom/document.h"
@@ -25,10 +26,12 @@
#include "third_party/blink/renderer/core/style/shape_value.h"
#include "third_party/blink/renderer/core/style/style_difference.h"
#include "third_party/blink/renderer/core/style/style_generated_image.h"
+#include "third_party/blink/renderer/core/style/style_initial_data.h"
#include "third_party/blink/renderer/core/testing/color_scheme_helper.h"
#include "third_party/blink/renderer/core/testing/dummy_page_holder.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
+#include "third_party/blink/renderer/platform/transforms/scale_transform_operation.h"
#include "ui/base/ui_base_features.h"
namespace blink {
@@ -88,12 +91,10 @@ TEST(ComputedStyleTest, FocusRingWidth) {
static uint16_t outline_width = 4;
style->SetOutlineWidth(outline_width);
- double expected_width =
- LayoutTheme::GetTheme().IsFocusRingOutset() ? outline_width : 3.5;
+ double expected_width = 3.5;
EXPECT_EQ(expected_width, style->GetOutlineStrokeWidthForFocusRing());
- expected_width =
- LayoutTheme::GetTheme().IsFocusRingOutset() ? outline_width : 1.0;
+ expected_width = 1.0;
style->SetEffectiveZoom(0.5);
EXPECT_EQ(expected_width, style->GetOutlineStrokeWidthForFocusRing());
#endif
@@ -107,8 +108,6 @@ TEST(ComputedStyleTest, FocusRingOutset) {
style->SetEffectiveZoom(4.75);
if (::features::IsFormControlsRefreshEnabled()) {
EXPECT_EQ(4, style->OutlineOutsetExtent());
- style->SetEffectiveAppearance(kRadioPart);
- EXPECT_EQ(6, style->OutlineOutsetExtent());
} else {
#if defined(OS_MACOSX)
EXPECT_EQ(4, style->OutlineOutsetExtent());
@@ -171,7 +170,12 @@ TEST(ComputedStyleTest,
scoped_refptr<ComputedStyle> style = ComputedStyle::Create();
scoped_refptr<ComputedStyle> other = ComputedStyle::Clone(*style);
- TransformOperations operations(true);
+ TransformOperations operations;
+ // An operation is necessary since having either a non-empty transform list
+ // or a transform animation will set HasTransform();
+ operations.Operations().push_back(
+ ScaleTransformOperation::Create(1, 1, TransformOperation::kScale));
+
style->SetTransform(operations);
other->SetTransform(operations);
@@ -523,6 +527,134 @@ TEST(ComputedStyleTest, CustomPropertiesEqual_Data) {
EXPECT_FALSE(style1->CustomPropertiesEqual(properties, *style2));
}
+TEST(ComputedStyleTest, CustomPropertiesInheritance_FastPath) {
+ auto dummy = std::make_unique<DummyPageHolder>(IntSize(0, 0));
+ css_test_helpers::RegisterProperty(dummy->GetDocument(), "--x", "<length>",
+ "0px", true);
+
+ scoped_refptr<ComputedStyle> old_style = ComputedStyle::Create();
+ scoped_refptr<ComputedStyle> new_style = ComputedStyle::Create();
+
+ using UnitType = CSSPrimitiveValue::UnitType;
+
+ const auto* value1 = CSSNumericLiteralValue::Create(1.0, UnitType::kPixels);
+ const auto* value2 = CSSNumericLiteralValue::Create(2.0, UnitType::kPixels);
+
+ EXPECT_FALSE(old_style->HasVariableDeclaration());
+ EXPECT_FALSE(old_style->HasVariableReference());
+ EXPECT_FALSE(new_style->HasVariableReference());
+ EXPECT_FALSE(new_style->HasVariableDeclaration());
+
+ // Removed variable
+ old_style->SetVariableValue("--x", value1, true);
+ EXPECT_EQ(ComputedStyle::Difference::kIndependentInherited,
+ ComputedStyle::ComputeDifference(old_style.get(), new_style.get()));
+
+ old_style = ComputedStyle::Create();
+ new_style = ComputedStyle::Create();
+
+ // Added a new variable
+ new_style->SetVariableValue("--x", value2, true);
+ EXPECT_EQ(ComputedStyle::Difference::kIndependentInherited,
+ ComputedStyle::ComputeDifference(old_style.get(), new_style.get()));
+
+ // Change value of variable
+ old_style->SetVariableValue("--x", value1, true);
+ new_style->SetVariableValue("--x", value2, true);
+ new_style->SetHasVariableReference();
+ EXPECT_FALSE(new_style->HasVariableDeclaration());
+ EXPECT_TRUE(new_style->HasVariableReference());
+ EXPECT_EQ(ComputedStyle::Difference::kIndependentInherited,
+ ComputedStyle::ComputeDifference(old_style.get(), new_style.get()));
+
+ old_style = ComputedStyle::Create();
+ new_style = ComputedStyle::Create();
+
+ // New styles with variable declaration don't force style recalc
+ old_style->SetVariableValue("--x", value1, true);
+ new_style->SetVariableValue("--x", value2, true);
+ new_style->SetHasVariableDeclaration();
+ EXPECT_TRUE(new_style->HasVariableDeclaration());
+ EXPECT_FALSE(new_style->HasVariableReference());
+ EXPECT_EQ(ComputedStyle::Difference::kIndependentInherited,
+ ComputedStyle::ComputeDifference(old_style.get(), new_style.get()));
+
+ old_style = ComputedStyle::Create();
+ new_style = ComputedStyle::Create();
+
+ // New styles with variable reference don't force style recalc
+ old_style->SetVariableValue("--x", value1, true);
+ new_style->SetVariableValue("--x", value2, true);
+ new_style->SetHasVariableDeclaration();
+ new_style->SetHasVariableReference();
+ EXPECT_TRUE(new_style->HasVariableDeclaration());
+ EXPECT_TRUE(new_style->HasVariableReference());
+ EXPECT_EQ(ComputedStyle::Difference::kIndependentInherited,
+ ComputedStyle::ComputeDifference(old_style.get(), new_style.get()));
+}
+
+TEST(ComputedStyleTest, CustomPropertiesInheritance_StyleRecalc) {
+ auto dummy = std::make_unique<DummyPageHolder>(IntSize(0, 0));
+ css_test_helpers::RegisterProperty(dummy->GetDocument(), "--x", "<length>",
+ "0px", true);
+
+ scoped_refptr<ComputedStyle> old_style = ComputedStyle::Create();
+ scoped_refptr<ComputedStyle> new_style = ComputedStyle::Create();
+
+ using UnitType = CSSPrimitiveValue::UnitType;
+
+ const auto* value1 = CSSNumericLiteralValue::Create(1.0, UnitType::kPixels);
+ const auto* value2 = CSSNumericLiteralValue::Create(2.0, UnitType::kPixels);
+
+ EXPECT_FALSE(old_style->HasVariableDeclaration());
+ EXPECT_FALSE(old_style->HasVariableReference());
+ EXPECT_FALSE(new_style->HasVariableReference());
+ EXPECT_FALSE(new_style->HasVariableDeclaration());
+
+ // Removed variable value
+ // Old styles with variable reference force style recalc
+ old_style->SetHasVariableReference();
+ old_style->SetVariableValue("--x", value2, true);
+ EXPECT_TRUE(old_style->HasVariableReference());
+ EXPECT_EQ(ComputedStyle::Difference::kInherited,
+ ComputedStyle::ComputeDifference(old_style.get(), new_style.get()));
+
+ old_style = ComputedStyle::Create();
+ new_style = ComputedStyle::Create();
+
+ // New variable value
+ // Old styles with variable declaration force style recalc
+ old_style->SetHasVariableDeclaration();
+ new_style->SetVariableValue("--x", value2, true);
+ EXPECT_TRUE(old_style->HasVariableDeclaration());
+ EXPECT_EQ(ComputedStyle::Difference::kInherited,
+ ComputedStyle::ComputeDifference(old_style.get(), new_style.get()));
+
+ old_style = ComputedStyle::Create();
+ new_style = ComputedStyle::Create();
+
+ // Change variable value
+ // Old styles with variable declaration force style recalc
+ old_style->SetVariableValue("--x", value1, true);
+ new_style->SetVariableValue("--x", value2, true);
+ old_style->SetHasVariableDeclaration();
+ EXPECT_TRUE(old_style->HasVariableDeclaration());
+ EXPECT_EQ(ComputedStyle::Difference::kInherited,
+ ComputedStyle::ComputeDifference(old_style.get(), new_style.get()));
+
+ old_style = ComputedStyle::Create();
+ new_style = ComputedStyle::Create();
+
+ // Change variable value
+ // Old styles with variable reference force style recalc
+ old_style->SetVariableValue("--x", value1, true);
+ new_style->SetVariableValue("--x", value2, true);
+ old_style->SetHasVariableReference();
+ EXPECT_TRUE(old_style->HasVariableReference());
+ EXPECT_EQ(ComputedStyle::Difference::kInherited,
+ ComputedStyle::ComputeDifference(old_style.get(), new_style.get()));
+}
+
TEST(ComputedStyleTest, ApplyColorSchemeLightOnDark) {
ScopedCSSColorSchemeForTest scoped_property_enabled(true);
ScopedCSSColorSchemeUARenderingForTest scoped_ua_enabled(true);
@@ -568,8 +700,7 @@ TEST(ComputedStyleTest, ApplyInternalLightDarkColor) {
auto* ua_context = MakeGarbageCollected<CSSParserContext>(
kUASheetMode, SecureContextMode::kInsecureContext);
const CSSValue* internal_light_dark = CSSParser::ParseSingleValue(
- CSSPropertyID::kColor, "-internal-light-dark-color(black, white)",
- ua_context);
+ CSSPropertyID::kColor, "-internal-light-dark(black, white)", ua_context);
ColorSchemeHelper color_scheme_helper(dummy_page_holder_->GetDocument());
color_scheme_helper.SetPreferredColorScheme(PreferredColorScheme::kDark);
@@ -609,7 +740,7 @@ TEST(ComputedStyleTest, ApplyInternalLightDarkColor) {
ScopedCSSCascadeForTest scoped_cascade_enabled(true);
auto* color_declaration =
- ParseDeclarationBlock("color:-internal-light-dark-color(black, white)");
+ ParseDeclarationBlock("color:-internal-light-dark(black, white)");
auto* dark_declaration = ParseDeclarationBlock("color-scheme:dark");
auto* light_declaration = ParseDeclarationBlock("color-scheme:light");
@@ -629,6 +760,52 @@ TEST(ComputedStyleTest, ApplyInternalLightDarkColor) {
}
}
+TEST(ComputedStyleTest, ApplyInternalLightDarkBackgroundImage) {
+ using css_test_helpers::ParseDeclarationBlock;
+
+ ScopedCSSCascadeForTest scoped_cascade_enabled(true);
+ ScopedCSSColorSchemeForTest scoped_property_enabled(true);
+ ScopedCSSColorSchemeUARenderingForTest scoped_ua_enabled(true);
+
+ std::unique_ptr<DummyPageHolder> dummy_page_holder_ =
+ std::make_unique<DummyPageHolder>(IntSize(0, 0), nullptr);
+ const ComputedStyle* initial = &ComputedStyle::InitialStyle();
+
+ ColorSchemeHelper color_scheme_helper(dummy_page_holder_->GetDocument());
+ color_scheme_helper.SetPreferredColorScheme(PreferredColorScheme::kDark);
+ StyleResolverState state(dummy_page_holder_->GetDocument(),
+ *dummy_page_holder_->GetDocument().documentElement(),
+ initial, initial);
+
+ scoped_refptr<ComputedStyle> style = ComputedStyle::Create();
+ state.SetStyle(style);
+
+ auto* bgimage_declaration = ParseDeclarationBlock(
+ "background-image:-internal-light-dark(none, url(dummy.png))",
+ kUASheetMode);
+ auto* dark_declaration = ParseDeclarationBlock("color-scheme:dark");
+ auto* light_declaration = ParseDeclarationBlock("color-scheme:light");
+
+ EXPECT_FALSE(style->HasNonInheritedLightDarkValue());
+
+ StyleCascade cascade1(state);
+ cascade1.MutableMatchResult().AddMatchedProperties(bgimage_declaration);
+ cascade1.MutableMatchResult().AddMatchedProperties(dark_declaration);
+ cascade1.Apply();
+ EXPECT_TRUE(style->HasBackgroundImage());
+ EXPECT_TRUE(style->HasNonInheritedLightDarkValue());
+
+ style = ComputedStyle::Create();
+ state.SetStyle(style);
+
+ StyleCascade cascade2(state);
+ cascade2.MutableMatchResult().AddMatchedProperties(bgimage_declaration);
+ cascade2.MutableMatchResult().AddMatchedProperties(light_declaration);
+ cascade2.Apply();
+ EXPECT_FALSE(style->HasBackgroundImage());
+ EXPECT_TRUE(style->HasNonInheritedLightDarkValue());
+}
+
TEST(ComputedStyleTest, StrokeWidthZoomAndCalc) {
std::unique_ptr<DummyPageHolder> dummy_page_holder_ =
std::make_unique<DummyPageHolder>(IntSize(0, 0), nullptr);
@@ -662,4 +839,141 @@ TEST(ComputedStyleTest, StrokeWidthZoomAndCalc) {
EXPECT_EQ(10, numeric_value->DoubleValue());
}
+TEST(ComputedStyleTest, InitialVariableNamesEmpty) {
+ scoped_refptr<ComputedStyle> style = ComputedStyle::Create();
+ EXPECT_TRUE(style->GetVariableNames().IsEmpty());
+}
+
+TEST(ComputedStyleTest, InitialVariableNames) {
+ using css_test_helpers::CreateLengthRegistration;
+
+ scoped_refptr<ComputedStyle> style = ComputedStyle::Create();
+
+ PropertyRegistry* registry = MakeGarbageCollected<PropertyRegistry>();
+ registry->RegisterProperty("--x", *CreateLengthRegistration("--x", 1));
+ registry->RegisterProperty("--y", *CreateLengthRegistration("--y", 2));
+ style->SetInitialData(StyleInitialData::Create(*registry));
+
+ EXPECT_EQ(2u, style->GetVariableNames().size());
+ EXPECT_TRUE(style->GetVariableNames().Contains("--x"));
+ EXPECT_TRUE(style->GetVariableNames().Contains("--y"));
+}
+
+TEST(ComputedStyleTest, InheritedVariableNames) {
+ using css_test_helpers::CreateVariableData;
+
+ scoped_refptr<ComputedStyle> style = ComputedStyle::Create();
+
+ const bool inherited = true;
+ style->SetVariableData("--a", CreateVariableData("foo"), inherited);
+ style->SetVariableData("--b", CreateVariableData("bar"), inherited);
+
+ EXPECT_EQ(2u, style->GetVariableNames().size());
+ EXPECT_TRUE(style->GetVariableNames().Contains("--a"));
+ EXPECT_TRUE(style->GetVariableNames().Contains("--b"));
+}
+
+TEST(ComputedStyleTest, NonInheritedVariableNames) {
+ using css_test_helpers::CreateVariableData;
+
+ scoped_refptr<ComputedStyle> style = ComputedStyle::Create();
+
+ const bool inherited = true;
+ style->SetVariableData("--a", CreateVariableData("foo"), !inherited);
+ style->SetVariableData("--b", CreateVariableData("bar"), !inherited);
+
+ EXPECT_EQ(2u, style->GetVariableNames().size());
+ EXPECT_TRUE(style->GetVariableNames().Contains("--a"));
+ EXPECT_TRUE(style->GetVariableNames().Contains("--b"));
+}
+
+TEST(ComputedStyleTest, InheritedAndNonInheritedVariableNames) {
+ using css_test_helpers::CreateVariableData;
+
+ scoped_refptr<ComputedStyle> style = ComputedStyle::Create();
+
+ const bool inherited = true;
+ style->SetVariableData("--a", CreateVariableData("foo"), inherited);
+ style->SetVariableData("--b", CreateVariableData("bar"), inherited);
+ style->SetVariableData("--d", CreateVariableData("foz"), !inherited);
+ style->SetVariableData("--c", CreateVariableData("baz"), !inherited);
+
+ EXPECT_EQ(4u, style->GetVariableNames().size());
+ EXPECT_TRUE(style->GetVariableNames().Contains("--a"));
+ EXPECT_TRUE(style->GetVariableNames().Contains("--b"));
+ EXPECT_TRUE(style->GetVariableNames().Contains("--c"));
+ EXPECT_TRUE(style->GetVariableNames().Contains("--d"));
+}
+
+TEST(ComputedStyleTest, InitialAndInheritedAndNonInheritedVariableNames) {
+ using css_test_helpers::CreateLengthRegistration;
+ using css_test_helpers::CreateVariableData;
+
+ scoped_refptr<ComputedStyle> style = ComputedStyle::Create();
+
+ PropertyRegistry* registry = MakeGarbageCollected<PropertyRegistry>();
+ registry->RegisterProperty("--b", *CreateLengthRegistration("--b", 1));
+ registry->RegisterProperty("--e", *CreateLengthRegistration("--e", 2));
+ style->SetInitialData(StyleInitialData::Create(*registry));
+
+ const bool inherited = true;
+ style->SetVariableData("--a", CreateVariableData("foo"), inherited);
+ style->SetVariableData("--b", CreateVariableData("bar"), inherited);
+ style->SetVariableData("--d", CreateVariableData("foz"), !inherited);
+ style->SetVariableData("--c", CreateVariableData("baz"), !inherited);
+
+ EXPECT_EQ(5u, style->GetVariableNames().size());
+ EXPECT_TRUE(style->GetVariableNames().Contains("--a"));
+ EXPECT_TRUE(style->GetVariableNames().Contains("--b"));
+ EXPECT_TRUE(style->GetVariableNames().Contains("--c"));
+ EXPECT_TRUE(style->GetVariableNames().Contains("--d"));
+ EXPECT_TRUE(style->GetVariableNames().Contains("--e"));
+}
+
+TEST(ComputedStyleTest, BorderWidthZoom) {
+ std::unique_ptr<DummyPageHolder> dummy_page_holder_ =
+ std::make_unique<DummyPageHolder>(IntSize(0, 0), nullptr);
+
+ const ComputedStyle* initial = &ComputedStyle::InitialStyle();
+
+ StyleResolverState state(dummy_page_holder_->GetDocument(),
+ *dummy_page_holder_->GetDocument().documentElement(),
+ initial, initial);
+
+ scoped_refptr<ComputedStyle> style = ComputedStyle::Create();
+ style->SetEffectiveZoom(2);
+ style->SetBorderLeftStyle(EBorderStyle::kSolid);
+ style->SetOutlineStyle(EBorderStyle::kSolid);
+ style->SetColumnRuleStyle(EBorderStyle::kSolid);
+ state.SetStyle(style);
+
+ const struct {
+ CSSIdentifierValue* css_value;
+ double expected_px;
+ STACK_ALLOCATED();
+ } tests[] = {
+ {CSSIdentifierValue::Create(CSSValueID::kThin), 1.0},
+ {CSSIdentifierValue::Create(CSSValueID::kMedium), 3.0},
+ {CSSIdentifierValue::Create(CSSValueID::kThick), 5.0},
+ };
+
+ for (const auto& test : tests) {
+ for (const auto* property :
+ {&GetCSSPropertyBorderLeftWidth(), &GetCSSPropertyOutlineWidth(),
+ &GetCSSPropertyColumnRuleWidth()}) {
+ const Longhand& longhand = To<Longhand>(*property);
+ longhand.ApplyValue(state, *test.css_value);
+ auto* computed_value = longhand.CSSValueFromComputedStyleInternal(
+ *style, style->SvgStyle(), nullptr /* layout_object */,
+ false /* allow_visited_style */);
+ AtomicString prop_name = longhand.GetCSSPropertyName().ToAtomicString();
+ ASSERT_TRUE(computed_value) << prop_name;
+ auto* numeric_value = DynamicTo<CSSNumericLiteralValue>(computed_value);
+ ASSERT_TRUE(numeric_value) << prop_name;
+ EXPECT_TRUE(numeric_value->IsPx()) << prop_name;
+ EXPECT_EQ(test.expected_px, numeric_value->DoubleValue()) << prop_name;
+ }
+ }
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/style/style_fetched_image.cc b/chromium/third_party/blink/renderer/core/style/style_fetched_image.cc
index fc358725ebc..a029869c544 100644
--- a/chromium/third_party/blink/renderer/core/style/style_fetched_image.cc
+++ b/chromium/third_party/blink/renderer/core/style/style_fetched_image.cc
@@ -46,7 +46,8 @@ StyleFetchedImage::StyleFetchedImage(const Document& document,
bool is_lazyload_possibly_deferred)
: document_(&document),
url_(params.Url()),
- origin_clean_(!params.IsFromOriginDirtyStyleSheet()) {
+ origin_clean_(!params.IsFromOriginDirtyStyleSheet()),
+ is_ad_related_(params.GetResourceRequest().IsAdResource()) {
is_image_resource_ = true;
is_lazyload_possibly_deferred_ = is_lazyload_possibly_deferred;
@@ -84,7 +85,7 @@ ImageResourceContent* StyleFetchedImage::CachedImage() const {
CSSValue* StyleFetchedImage::CssValue() const {
return MakeGarbageCollected<CSSImageValue>(
AtomicString(url_.GetString()), url_, Referrer(),
- origin_clean_ ? OriginClean::kTrue : OriginClean::kFalse,
+ origin_clean_ ? OriginClean::kTrue : OriginClean::kFalse, is_ad_related_,
const_cast<StyleFetchedImage*>(this));
}
diff --git a/chromium/third_party/blink/renderer/core/style/style_fetched_image.h b/chromium/third_party/blink/renderer/core/style/style_fetched_image.h
index d579633c07e..fed3be5dda2 100644
--- a/chromium/third_party/blink/renderer/core/style/style_fetched_image.h
+++ b/chromium/third_party/blink/renderer/core/style/style_fetched_image.h
@@ -88,6 +88,9 @@ class StyleFetchedImage final : public StyleImage,
Member<const Document> document_;
const KURL url_;
const bool origin_clean_;
+
+ // Whether this was created by an ad-related CSSParserContext.
+ const bool is_ad_related_;
};
template <>
diff --git a/chromium/third_party/blink/renderer/core/style/style_inherited_variables.cc b/chromium/third_party/blink/renderer/core/style/style_inherited_variables.cc
index 43fa47ca6cc..bd06ce55ddd 100644
--- a/chromium/third_party/blink/renderer/core/style/style_inherited_variables.cc
+++ b/chromium/third_party/blink/renderer/core/style/style_inherited_variables.cc
@@ -44,15 +44,13 @@ StyleVariables::OptionalValue StyleInheritedVariables::GetValue(
return base::nullopt;
}
-HashSet<AtomicString> StyleInheritedVariables::GetCustomPropertyNames() const {
- HashSet<AtomicString> names;
+void StyleInheritedVariables::CollectNames(HashSet<AtomicString>& names) const {
if (root_) {
for (const auto& pair : root_->Data())
names.insert(pair.key);
}
for (const auto& pair : Data())
names.insert(pair.key);
- return names;
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/style/style_inherited_variables.h b/chromium/third_party/blink/renderer/core/style/style_inherited_variables.h
index 774e957944f..6a40219ca48 100644
--- a/chromium/third_party/blink/renderer/core/style/style_inherited_variables.h
+++ b/chromium/third_party/blink/renderer/core/style/style_inherited_variables.h
@@ -48,7 +48,7 @@ class CORE_EXPORT StyleInheritedVariables
// Note that not all custom property names returned here necessarily have
// valid values, due to cycles or references to invalid variables without
// using a fallback.
- HashSet<AtomicString> GetCustomPropertyNames() const;
+ void CollectNames(HashSet<AtomicString>&) const;
const StyleVariables::DataMap& Data() const { return variables_.Data(); }
const StyleVariables::ValueMap& Values() const { return variables_.Values(); }
diff --git a/chromium/third_party/blink/renderer/core/style/style_initial_data.h b/chromium/third_party/blink/renderer/core/style/style_initial_data.h
index 9f44d73cfe8..389e6cef870 100644
--- a/chromium/third_party/blink/renderer/core/style/style_initial_data.h
+++ b/chromium/third_party/blink/renderer/core/style/style_initial_data.h
@@ -35,6 +35,10 @@ class CORE_EXPORT StyleInitialData : public RefCounted<StyleInitialData> {
bool HasInitialVariables() const { return !variables_.IsEmpty(); }
+ void CollectVariableNames(HashSet<AtomicString>& names) const {
+ return variables_.CollectNames(names);
+ }
+
CSSVariableData* GetVariableData(const AtomicString& name) const {
return variables_.GetData(name).value_or(nullptr);
}
diff --git a/chromium/third_party/blink/renderer/core/style/style_non_inherited_variables.h b/chromium/third_party/blink/renderer/core/style/style_non_inherited_variables.h
index e8e36c2ba51..5ccba54078c 100644
--- a/chromium/third_party/blink/renderer/core/style/style_non_inherited_variables.h
+++ b/chromium/third_party/blink/renderer/core/style/style_non_inherited_variables.h
@@ -53,8 +53,8 @@ class CORE_EXPORT StyleNonInheritedVariables {
return variables_.GetValue(name);
}
- HashSet<AtomicString> GetCustomPropertyNames() const {
- return variables_.GetNames();
+ void CollectNames(HashSet<AtomicString>& names) const {
+ variables_.CollectNames(names);
}
const StyleVariables::DataMap& Data() const { return variables_.Data(); }
diff --git a/chromium/third_party/blink/renderer/core/style/style_variables.cc b/chromium/third_party/blink/renderer/core/style/style_variables.cc
index 334cd7765d6..2bb5fe6af90 100644
--- a/chromium/third_party/blink/renderer/core/style/style_variables.cc
+++ b/chromium/third_party/blink/renderer/core/style/style_variables.cc
@@ -86,11 +86,9 @@ bool StyleVariables::IsEmpty() const {
return data_.IsEmpty() && values_->IsEmpty();
}
-HashSet<AtomicString> StyleVariables::GetNames() const {
- HashSet<AtomicString> names;
+void StyleVariables::CollectNames(HashSet<AtomicString>& names) const {
for (const auto& pair : data_)
names.insert(pair.key);
- return names;
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/style/style_variables.h b/chromium/third_party/blink/renderer/core/style/style_variables.h
index 416ee2900e6..3b2eaa606ff 100644
--- a/chromium/third_party/blink/renderer/core/style/style_variables.h
+++ b/chromium/third_party/blink/renderer/core/style/style_variables.h
@@ -62,7 +62,7 @@ class CORE_EXPORT StyleVariables {
void SetValue(const AtomicString&, const CSSValue*);
bool IsEmpty() const;
- HashSet<AtomicString> GetNames() const;
+ void CollectNames(HashSet<AtomicString>&) const;
const DataMap& Data() const { return data_; }
const ValueMap& Values() const { return *values_; }
diff --git a/chromium/third_party/blink/renderer/core/style/style_variables_test.cc b/chromium/third_party/blink/renderer/core/style/style_variables_test.cc
index 63b0797d658..4d62b457fe7 100644
--- a/chromium/third_party/blink/renderer/core/style/style_variables_test.cc
+++ b/chromium/third_party/blink/renderer/core/style/style_variables_test.cc
@@ -41,7 +41,8 @@ TEST_F(StyleVariablesTest, GetNames) {
vars.SetData("--x", css_test_helpers::CreateVariableData("foo"));
vars.SetData("--y", css_test_helpers::CreateVariableData("bar"));
- HashSet<AtomicString> names = vars.GetNames();
+ HashSet<AtomicString> names;
+ vars.CollectNames(names);
EXPECT_EQ(2u, names.size());
EXPECT_TRUE(names.Contains("--x"));
EXPECT_TRUE(names.Contains("--y"));
diff --git a/chromium/third_party/blink/renderer/core/style/text_decoration_thickness.cc b/chromium/third_party/blink/renderer/core/style/text_decoration_thickness.cc
new file mode 100644
index 00000000000..0e98a748385
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/style/text_decoration_thickness.cc
@@ -0,0 +1,30 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/style/text_decoration_thickness.h"
+
+namespace blink {
+
+TextDecorationThickness::TextDecorationThickness() = default;
+
+TextDecorationThickness::TextDecorationThickness(const Length& length)
+ : thickness_(length) {}
+
+TextDecorationThickness::TextDecorationThickness(CSSValueID from_font_keyword) {
+ DCHECK_EQ(from_font_keyword, CSSValueID::kFromFont);
+ thickness_from_font_ = true;
+}
+
+Length TextDecorationThickness::Thickness() const {
+ DCHECK(!thickness_from_font_);
+ return thickness_;
+}
+
+bool TextDecorationThickness::operator==(
+ const TextDecorationThickness& other) const {
+ return thickness_from_font_ == other.thickness_from_font_ &&
+ thickness_ == other.thickness_;
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/style/text_decoration_thickness.h b/chromium/third_party/blink/renderer/core/style/text_decoration_thickness.h
new file mode 100644
index 00000000000..132967ad6fe
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/style/text_decoration_thickness.h
@@ -0,0 +1,35 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_STYLE_TEXT_DECORATION_THICKNESS_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_STYLE_TEXT_DECORATION_THICKNESS_H_
+
+#include "third_party/blink/renderer/core/css_value_keywords.h"
+#include "third_party/blink/renderer/platform/geometry/length.h"
+
+namespace blink {
+
+class TextDecorationThickness {
+ DISALLOW_NEW();
+
+ public:
+ TextDecorationThickness();
+
+ explicit TextDecorationThickness(const Length& length);
+
+ explicit TextDecorationThickness(CSSValueID from_font_keyword);
+
+ bool IsFromFont() const { return thickness_from_font_; }
+ Length Thickness() const;
+
+ bool operator==(const TextDecorationThickness&) const;
+
+ private:
+ Length thickness_;
+ bool thickness_from_font_{false};
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_STYLE_TEXT_DECORATION_THICKNESS_H_
diff --git a/chromium/third_party/blink/renderer/core/svg/BUILD.gn b/chromium/third_party/blink/renderer/core/svg/BUILD.gn
index d69850b5ec9..b4b05d1bd40 100644
--- a/chromium/third_party/blink/renderer/core/svg/BUILD.gn
+++ b/chromium/third_party/blink/renderer/core/svg/BUILD.gn
@@ -111,6 +111,8 @@ blink_core_sources("svg") {
"svg_enumeration.h",
"svg_enumeration_map.cc",
"svg_enumeration_map.h",
+ "svg_external_document_cache.cc",
+ "svg_external_document_cache.h",
"svg_fe_blend_element.cc",
"svg_fe_blend_element.h",
"svg_fe_color_matrix_element.cc",
diff --git a/chromium/third_party/blink/renderer/core/svg/animation/smil_time_container_test.cc b/chromium/third_party/blink/renderer/core/svg/animation/smil_time_container_test.cc
index 7af0c153fe3..1192a7dc41c 100644
--- a/chromium/third_party/blink/renderer/core/svg/animation/smil_time_container_test.cc
+++ b/chromium/third_party/blink/renderer/core/svg/animation/smil_time_container_test.cc
@@ -29,7 +29,8 @@ class ContentLoadedEventListener final : public NativeEventListener {
: callback_(std::move(callback)) {}
void Invoke(ExecutionContext* execution_context, Event*) override {
- std::move(callback_).Run(*Document::From(execution_context));
+ std::move(callback_).Run(
+ *To<LocalDOMWindow>(execution_context)->document());
}
private:
diff --git a/chromium/third_party/blink/renderer/core/svg/graphics/svg_image.cc b/chromium/third_party/blink/renderer/core/svg/graphics/svg_image.cc
index c67810593dd..6f555dcfa2d 100644
--- a/chromium/third_party/blink/renderer/core/svg/graphics/svg_image.cc
+++ b/chromium/third_party/blink/renderer/core/svg/graphics/svg_image.cc
@@ -867,13 +867,14 @@ Image::SizeAvailability SVGImage::DataChanged(bool all_data_received) {
DCHECK(!frame_client_);
frame_client_ = MakeGarbageCollected<SVGImageLocalFrameClient>(this);
frame = MakeGarbageCollected<LocalFrame>(frame_client_, *page, nullptr,
+ base::UnguessableToken::Create(),
nullptr, nullptr);
frame->SetView(MakeGarbageCollected<LocalFrameView>(*frame));
frame->Init();
}
FrameLoader& loader = frame->Loader();
- loader.ForceSandboxFlags(mojom::blink::WebSandboxFlags::kAll);
+ loader.ForceSandboxFlags(network::mojom::blink::WebSandboxFlags::kAll);
// SVG Images will always synthesize a viewBox, if it's not available, and
// thus never see scrollbars.
diff --git a/chromium/third_party/blink/renderer/core/svg/graphics/svg_image_test.cc b/chromium/third_party/blink/renderer/core/svg/graphics/svg_image_test.cc
index 59944100bb6..6a7a5717eed 100644
--- a/chromium/third_party/blink/renderer/core/svg/graphics/svg_image_test.cc
+++ b/chromium/third_party/blink/renderer/core/svg/graphics/svg_image_test.cc
@@ -368,7 +368,7 @@ TEST_F(SVGImageSimTest, PageVisibilityHiddenToVisible) {
// Set page visibility to 'hidden', and then wait for the animation timer to
// fire. This should suspend the image animation. (Suspend the image's
// animation timeline.)
- WebView().SetVisibilityState(PageVisibilityState::kHidden,
+ WebView().SetVisibilityState(mojom::blink::PageVisibilityState::kHidden,
/*initial_state=*/false);
test::RunDelayedTasks(base::TimeDelta::FromMilliseconds(1) +
timer->NextFireInterval());
@@ -377,7 +377,7 @@ TEST_F(SVGImageSimTest, PageVisibilityHiddenToVisible) {
// Set page visibility to 'visible' - this should schedule a new animation
// frame and resume the image animation.
- WebView().SetVisibilityState(PageVisibilityState::kVisible,
+ WebView().SetVisibilityState(mojom::blink::PageVisibilityState::kVisible,
/*initial_state=*/false);
test::RunDelayedTasks(base::TimeDelta::FromMilliseconds(1) +
timer->NextFireInterval());
diff --git a/chromium/third_party/blink/renderer/core/svg/properties/svg_animated_property.cc b/chromium/third_party/blink/renderer/core/svg/properties/svg_animated_property.cc
index 31b4b832dd5..3b73e215eaa 100644
--- a/chromium/third_party/blink/renderer/core/svg/properties/svg_animated_property.cc
+++ b/chromium/third_party/blink/renderer/core/svg/properties/svg_animated_property.cc
@@ -62,20 +62,15 @@ void SVGAnimatedPropertyBase::Trace(Visitor* visitor) {
visitor->Trace(context_element_);
}
-void SVGAnimatedPropertyBase::AnimationEnded() {
- SynchronizeAttribute();
-}
-
bool SVGAnimatedPropertyBase::NeedsSynchronizeAttribute() const {
// DOM attribute synchronization is only needed if a change has been made
- // through JavaScript (via a tear-off or primitive) or the property is being
- // animated. This prevents unnecessary attribute creation on the target
- // element.
- return base_value_needs_synchronization_ || IsAnimating();
+ // through the JavaScript IDL attribute (via a tear-off or primitive). This
+ // prevents unnecessary attribute creation on the target element.
+ return base_value_needs_synchronization_;
}
void SVGAnimatedPropertyBase::SynchronizeAttribute() {
- AtomicString value(CurrentValueBase()->ValueAsString());
+ AtomicString value(BaseValueBase().ValueAsString());
context_element_->SetSynchronizedLazyAttribute(attribute_name_, value);
base_value_needs_synchronization_ = false;
}
diff --git a/chromium/third_party/blink/renderer/core/svg/properties/svg_animated_property.h b/chromium/third_party/blink/renderer/core/svg/properties/svg_animated_property.h
index 7bcf423b221..5acb3121fe0 100644
--- a/chromium/third_party/blink/renderer/core/svg/properties/svg_animated_property.h
+++ b/chromium/third_party/blink/renderer/core/svg/properties/svg_animated_property.h
@@ -49,13 +49,12 @@ class SVGAnimatedPropertyBase : public GarbageCollectedMixin {
public:
virtual ~SVGAnimatedPropertyBase();
- virtual SVGPropertyBase* CurrentValueBase() = 0;
virtual const SVGPropertyBase& BaseValueBase() const = 0;
virtual bool IsAnimating() const = 0;
virtual SVGPropertyBase* CreateAnimatedValue() = 0;
virtual void SetAnimatedValue(SVGPropertyBase*) = 0;
- virtual void AnimationEnded();
+ virtual void AnimationEnded() = 0;
virtual SVGParsingError AttributeChanged(const String&) = 0;
virtual bool NeedsSynchronizeAttribute() const;
@@ -125,8 +124,6 @@ class SVGAnimatedPropertyCommon : public SVGAnimatedPropertyBase {
return const_cast<SVGAnimatedPropertyCommon*>(this)->CurrentValue();
}
- SVGPropertyBase* CurrentValueBase() override { return CurrentValue(); }
-
const SVGPropertyBase& BaseValueBase() const override { return *base_value_; }
bool IsAnimating() const override { return current_value_ != base_value_; }
@@ -158,7 +155,6 @@ class SVGAnimatedPropertyCommon : public SVGAnimatedPropertyBase {
void AnimationEnded() override {
current_value_ = base_value_;
- SVGAnimatedPropertyBase::AnimationEnded();
}
void Trace(Visitor* visitor) override {
diff --git a/chromium/third_party/blink/renderer/core/svg/properties/svg_list_property_helper.h b/chromium/third_party/blink/renderer/core/svg/properties/svg_list_property_helper.h
index dfea5e8c7b6..24f2aed8241 100644
--- a/chromium/third_party/blink/renderer/core/svg/properties/svg_list_property_helper.h
+++ b/chromium/third_party/blink/renderer/core/svg/properties/svg_list_property_helper.h
@@ -46,6 +46,7 @@ template <typename Derived, typename ItemProperty>
class SVGListPropertyHelper : public SVGPropertyHelper<Derived> {
public:
typedef ItemProperty ItemPropertyType;
+ using ItemPropertyListType = HeapVector<Member<ItemPropertyType>>;
SVGListPropertyHelper() = default;
@@ -64,33 +65,9 @@ class SVGListPropertyHelper : public SVGPropertyHelper<Derived> {
index);
}
- class ConstIterator {
- STACK_ALLOCATED();
-
- private:
- typedef typename HeapVector<Member<ItemPropertyType>>::const_iterator
- WrappedType;
-
- public:
- ConstIterator(WrappedType it) : it_(it) {}
-
- ConstIterator& operator++() {
- ++it_;
- return *this;
- }
-
- bool operator==(const ConstIterator& o) const { return it_ == o.it_; }
- bool operator!=(const ConstIterator& o) const { return it_ != o.it_; }
-
- ItemPropertyType* operator*() { return *it_; }
- ItemPropertyType* operator->() { return *it_; }
-
- private:
- WrappedType it_;
- };
-
- ConstIterator begin() const { return ConstIterator(values_.begin()); }
- ConstIterator end() const { return ConstIterator(values_.end()); }
+ using const_iterator = typename ItemPropertyListType::const_iterator;
+ const_iterator begin() const { return values_.begin(); }
+ const_iterator end() const { return values_.end(); }
void Append(ItemPropertyType* new_item) {
DCHECK(new_item);
@@ -146,7 +123,7 @@ class SVGListPropertyHelper : public SVGPropertyHelper<Derived> {
private:
inline bool CheckIndexBound(uint32_t, ExceptionState&);
- HeapVector<Member<ItemPropertyType>> values_;
+ ItemPropertyListType values_;
};
template <typename Derived, typename ItemProperty>
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_animate_element.cc b/chromium/third_party/blink/renderer/core/svg/svg_animate_element.cc
index 16e66af4305..47090b5d649 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_animate_element.cc
+++ b/chromium/third_party/blink/renderer/core/svg/svg_animate_element.cc
@@ -183,7 +183,7 @@ void SVGAnimateElement::ResolveTargetProperty() {
type_ = SVGElement::AnimatedPropertyTypeForCSSAttribute(AttributeName());
css_property_id_ =
type_ != kAnimatedUnknown
- ? cssPropertyID(targetElement()->GetDocument().ToExecutionContext(),
+ ? cssPropertyID(targetElement()->GetExecutionContext(),
AttributeName().LocalName())
: CSSPropertyID::kInvalid;
}
@@ -239,7 +239,7 @@ SVGPropertyBase* SVGAnimateElement::CreatePropertyForAttributeAnimation(
// http://www.w3.org/TR/SVG/single-page.html#animate-AnimateTransformElement
DCHECK_NE(type_, kAnimatedTransformList);
DCHECK(target_property_);
- return target_property_->CurrentValueBase()->CloneForAnimation(value);
+ return target_property_->BaseValueBase().CloneForAnimation(value);
}
SVGPropertyBase* SVGAnimateElement::CreatePropertyForCSSAnimation(
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_animate_element.idl b/chromium/third_party/blink/renderer/core/svg/svg_animate_element.idl
index 15792170dc0..790eb1d5bb5 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_animate_element.idl
+++ b/chromium/third_party/blink/renderer/core/svg/svg_animate_element.idl
@@ -25,5 +25,7 @@
// https://svgwg.org/specs/animations/#InterfaceSVGAnimateElement
-interface SVGAnimateElement : SVGAnimationElement {
+[
+ Exposed=Window
+] interface SVGAnimateElement : SVGAnimationElement {
};
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_animate_motion_element.idl b/chromium/third_party/blink/renderer/core/svg/svg_animate_motion_element.idl
index 1b5b3ca4a1a..522b46bde3d 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_animate_motion_element.idl
+++ b/chromium/third_party/blink/renderer/core/svg/svg_animate_motion_element.idl
@@ -25,5 +25,7 @@
// https://svgwg.org/specs/animations/#InterfaceSVGAnimateMotionElement
-interface SVGAnimateMotionElement : SVGAnimationElement {
+[
+ Exposed=Window
+] interface SVGAnimateMotionElement : SVGAnimationElement {
};
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_animate_transform_element.idl b/chromium/third_party/blink/renderer/core/svg/svg_animate_transform_element.idl
index fe64235adef..ac30765fa95 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_animate_transform_element.idl
+++ b/chromium/third_party/blink/renderer/core/svg/svg_animate_transform_element.idl
@@ -25,5 +25,7 @@
// https://svgwg.org/specs/animations/#InterfaceSVGAnimateTransformElement
-interface SVGAnimateTransformElement : SVGAnimationElement {
+[
+ Exposed=Window
+] interface SVGAnimateTransformElement : SVGAnimationElement {
};
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_animation_element.idl b/chromium/third_party/blink/renderer/core/svg/svg_animation_element.idl
index 23be2805bd1..35776426678 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_animation_element.idl
+++ b/chromium/third_party/blink/renderer/core/svg/svg_animation_element.idl
@@ -26,7 +26,9 @@
// https://svgwg.org/specs/animations/#InterfaceSVGAnimationElement
-interface SVGAnimationElement : SVGElement {
+[
+ Exposed=Window
+] interface SVGAnimationElement : SVGElement {
readonly attribute SVGElement targetElement;
attribute EventHandler onbegin;
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_clip_path_element.idl b/chromium/third_party/blink/renderer/core/svg/svg_clip_path_element.idl
index 31835dae3ea..d477641deee 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_clip_path_element.idl
+++ b/chromium/third_party/blink/renderer/core/svg/svg_clip_path_element.idl
@@ -29,6 +29,8 @@
// TODO(foolip): SVGClipPathElement should inherit from SVGElement and
// implement SVGUnitTypes. The transform attribute (which is on
// SVGGraphicsElement) should also be on SVGClipPathElement.
-interface SVGClipPathElement : SVGGraphicsElement {
+[
+ Exposed=Window
+] interface SVGClipPathElement : SVGGraphicsElement {
[Measure] readonly attribute SVGAnimatedEnumeration clipPathUnits;
};
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_component_transfer_function_element.idl b/chromium/third_party/blink/renderer/core/svg/svg_component_transfer_function_element.idl
index 4a124426c94..72b44446783 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_component_transfer_function_element.idl
+++ b/chromium/third_party/blink/renderer/core/svg/svg_component_transfer_function_element.idl
@@ -26,7 +26,8 @@
// https://drafts.fxtf.org/filter-effects/#InterfaceSVGComponentTransferFunctionElement
[
- DoNotCheckConstants
+ DoNotCheckConstants,
+ Exposed=Window
] interface SVGComponentTransferFunctionElement : SVGElement {
// Component Transfer Types
[MeasureAs=SVG1DOMFilter] const unsigned short SVG_FECOMPONENTTRANSFER_TYPE_UNKNOWN = 0;
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_element.cc b/chromium/third_party/blink/renderer/core/svg/svg_element.cc
index 71de49ebb40..3fe6911ca7d 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_element.cc
+++ b/chromium/third_party/blink/renderer/core/svg/svg_element.cc
@@ -180,7 +180,6 @@ void SVGElement::SetInstanceUpdatesBlocked(bool value) {
void SVGElement::SetWebAnimationsPending() {
GetDocument().AccessSVGExtensions().AddWebAnimationsPendingSVGElement(*this);
EnsureSVGRareData()->SetWebAnimatedAttributesDirty(true);
- EnsureUniqueElementData().SetAnimatedSvgAttributesAreDirty(true);
}
static bool IsSVGAttributeHandle(const PropertyHandle& property_handle) {
@@ -204,12 +203,6 @@ void SVGElement::ApplyActiveWebAnimations() {
SvgRareData()->SetWebAnimatedAttributesDirty(false);
}
-static inline void NotifyAnimValChanged(SVGElement* target_element,
- const QualifiedName& attribute_name) {
- target_element->InvalidateSVGAttributes();
- target_element->SvgAttributeChanged(attribute_name);
-}
-
template <typename T>
static void ForSelfAndInstances(SVGElement* element, T callback) {
SVGElement::InstanceUpdateBlocker blocker(element);
@@ -221,17 +214,17 @@ static void ForSelfAndInstances(SVGElement* element, T callback) {
void SVGElement::SetWebAnimatedAttribute(const QualifiedName& attribute,
SVGPropertyBase* value) {
SetAnimatedAttribute(attribute, value);
- EnsureSVGRareData()->WebAnimatedAttributes().insert(&attribute);
+ EnsureSVGRareData()->WebAnimatedAttributes().insert(attribute);
}
void SVGElement::ClearWebAnimatedAttributes() {
if (!HasSVGRareData())
return;
- for (const QualifiedName* attribute :
- SvgRareData()->WebAnimatedAttributes()) {
- ClearAnimatedAttribute(*attribute);
- }
- SvgRareData()->WebAnimatedAttributes().clear();
+ HashSet<QualifiedName>& animated_attributes =
+ SvgRareData()->WebAnimatedAttributes();
+ for (const QualifiedName& attribute : animated_attributes)
+ ClearAnimatedAttribute(attribute);
+ animated_attributes.clear();
}
ElementSMILAnimations* SVGElement::GetSMILAnimations() {
@@ -246,11 +239,17 @@ ElementSMILAnimations& SVGElement::EnsureSMILAnimations() {
void SVGElement::SetAnimatedAttribute(const QualifiedName& attribute,
SVGPropertyBase* value) {
+ // When animating the 'class' attribute we need to have our own
+ // unique element data since we'll be altering the active class
+ // names for the element.
+ if (attribute == html_names::kClassAttr)
+ EnsureUniqueElementData();
+
ForSelfAndInstances(this, [&attribute, &value](SVGElement* element) {
if (SVGAnimatedPropertyBase* animated_property =
element->PropertyFromAttribute(attribute)) {
animated_property->SetAnimatedValue(value);
- NotifyAnimValChanged(element, attribute);
+ element->SvgAttributeChanged(attribute);
}
});
}
@@ -260,7 +259,7 @@ void SVGElement::ClearAnimatedAttribute(const QualifiedName& attribute) {
if (SVGAnimatedPropertyBase* animated_property =
element->PropertyFromAttribute(attribute)) {
animated_property->AnimationEnded();
- NotifyAnimValChanged(element, attribute);
+ element->SvgAttributeChanged(attribute);
}
});
}
@@ -735,16 +734,16 @@ bool SVGElement::IsAnimatableCSSProperty(const QualifiedName& attr_name) {
bool SVGElement::IsPresentationAttribute(const QualifiedName& name) const {
if (const SVGAnimatedPropertyBase* property = PropertyFromAttribute(name))
return property->HasPresentationAttributeMapping();
- return CssPropertyIdForSVGAttributeName(GetDocument().ToExecutionContext(),
- name) > CSSPropertyID::kInvalid;
+ return CssPropertyIdForSVGAttributeName(GetExecutionContext(), name) >
+ CSSPropertyID::kInvalid;
}
void SVGElement::CollectStyleForPresentationAttribute(
const QualifiedName& name,
const AtomicString& value,
MutableCSSPropertyValueSet* style) {
- CSSPropertyID property_id = CssPropertyIdForSVGAttributeName(
- GetDocument().ToExecutionContext(), name);
+ CSSPropertyID property_id =
+ CssPropertyIdForSVGAttributeName(GetExecutionContext(), name);
if (property_id > CSSPropertyID::kInvalid)
AddPropertyToPresentationAttributeStyle(style, property_id, value);
}
@@ -878,7 +877,7 @@ void SVGElement::AttributeChanged(const AttributeModificationParams& params) {
void SVGElement::SvgAttributeChanged(const QualifiedName& attr_name) {
CSSPropertyID prop_id = SVGElement::CssPropertyIdForSVGAttributeName(
- GetDocument().ToExecutionContext(), attr_name);
+ GetExecutionContext(), attr_name);
if (prop_id > CSSPropertyID::kInvalid) {
InvalidateInstances();
return;
@@ -893,14 +892,20 @@ void SVGElement::SvgAttributeChanged(const QualifiedName& attr_name) {
void SVGElement::SvgAttributeBaseValChanged(const QualifiedName& attribute) {
SvgAttributeChanged(attribute);
+ UpdateWebAnimatedAttributeOnBaseValChange(attribute);
+}
- if (!HasSVGRareData() || SvgRareData()->WebAnimatedAttributes().IsEmpty())
+void SVGElement::UpdateWebAnimatedAttributeOnBaseValChange(
+ const QualifiedName& attribute) {
+ if (!HasSVGRareData())
+ return;
+ const auto& animated_attributes = SvgRareData()->WebAnimatedAttributes();
+ if (animated_attributes.IsEmpty() || !animated_attributes.Contains(attribute))
return;
-
// TODO(alancutter): Only mark attributes as dirty if their animation depends
// on the underlying value.
SvgRareData()->SetWebAnimatedAttributesDirty(true);
- GetElementData()->SetAnimatedSvgAttributesAreDirty(true);
+ EnsureAttributeAnimValUpdated();
}
void SVGElement::EnsureAttributeAnimValUpdated() {
@@ -915,34 +920,47 @@ void SVGElement::EnsureAttributeAnimValUpdated() {
}
}
-void SVGElement::SynchronizeAnimatedSVGAttribute(
- const QualifiedName& name) const {
- if (!GetElementData() ||
- !GetElementData()->animated_svg_attributes_are_dirty())
- return;
-
- // We const_cast here because we have deferred baseVal mutation animation
- // updates to this point in time.
- const_cast<SVGElement*>(this)->EnsureAttributeAnimValUpdated();
-
+void SVGElement::SynchronizeSVGAttribute(const QualifiedName& name) const {
+ DCHECK(GetElementData());
+ DCHECK(GetElementData()->svg_attributes_are_dirty());
if (name == AnyQName()) {
- AttributeToPropertyMap::const_iterator::ValuesIterator it =
- attribute_to_property_map_.Values().begin();
- AttributeToPropertyMap::const_iterator::ValuesIterator end =
- attribute_to_property_map_.Values().end();
- for (; it != end; ++it) {
- if ((*it)->NeedsSynchronizeAttribute())
- (*it)->SynchronizeAttribute();
+ for (SVGAnimatedPropertyBase* property :
+ attribute_to_property_map_.Values()) {
+ if (property->NeedsSynchronizeAttribute())
+ property->SynchronizeAttribute();
}
-
- GetElementData()->SetAnimatedSvgAttributesAreDirty(false);
+ GetElementData()->SetSvgAttributesAreDirty(false);
} else {
- SVGAnimatedPropertyBase* property = attribute_to_property_map_.at(name);
+ SVGAnimatedPropertyBase* property = PropertyFromAttribute(name);
if (property && property->NeedsSynchronizeAttribute())
property->SynchronizeAttribute();
}
}
+void SVGElement::CollectStyleForAnimatedPresentationAttributes(
+ MutableCSSPropertyValueSet* style) {
+ // TODO(fs): This re-applies all animating attributes that are also
+ // presentation attributes. The precise predicate that we want is animated
+ // attributes that are presentation attributes and do not have a content
+ // attribute.
+ // That last bit ("do not have a content attribute") would mean a linear
+ // search of the attribute collection per property.
+ // Maybe reversing the order of operations would be preferable here (i.e
+ // collect style for animating attributes first, stashing which in a map, and
+ // then selectively collecting the rest of the presentation attributes).
+ // Maintaining the presentation attribute style "manually" also seems like a
+ // reasonable scheme since that means we can avoid reparsing the presentation
+ // attributes that didn't change.
+ for (SVGAnimatedPropertyBase* property :
+ attribute_to_property_map_.Values()) {
+ if (!property->HasPresentationAttributeMapping() ||
+ !property->IsAnimating())
+ continue;
+ CollectStyleForPresentationAttribute(property->AttributeName(),
+ g_empty_atom, style);
+ }
+}
+
scoped_refptr<ComputedStyle> SVGElement::CustomStyleForLayoutObject() {
SVGElement* corresponding_element = CorrespondingElement();
if (!corresponding_element)
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_element.h b/chromium/third_party/blink/renderer/core/svg/svg_element.h
index c11a50ffb0d..3a626772952 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_element.h
+++ b/chromium/third_party/blink/renderer/core/svg/svg_element.h
@@ -132,7 +132,7 @@ class CORE_EXPORT SVGElement : public Element {
virtual AffineTransform* AnimateMotionTransform() { return nullptr; }
void InvalidateSVGAttributes() {
- EnsureUniqueElementData().SetAnimatedSvgAttributesAreDirty(true);
+ EnsureUniqueElementData().SetSvgAttributesAreDirty(true);
}
void InvalidateSVGPresentationAttributeStyle() {
EnsureUniqueElementData().SetPresentationAttributeStyleIsDirty(true);
@@ -146,7 +146,9 @@ class CORE_EXPORT SVGElement : public Element {
void SetCorrespondingElement(SVGElement*);
SVGUseElement* GeneratingUseElement() const;
- void SynchronizeAnimatedSVGAttribute(const QualifiedName&) const;
+ void SynchronizeSVGAttribute(const QualifiedName&) const;
+ void CollectStyleForAnimatedPresentationAttributes(
+ MutableCSSPropertyValueSet*);
scoped_refptr<ComputedStyle> CustomStyleForLayoutObject() final;
bool LayoutObjectIsNeeded(const ComputedStyle&) const override;
@@ -278,6 +280,7 @@ class CORE_EXPORT SVGElement : public Element {
}
void WillRecalcStyle(const StyleRecalcChange) override;
static SVGElementSet& GetDependencyTraversalVisitedSet();
+ void UpdateWebAnimatedAttributeOnBaseValChange(const QualifiedName&);
HeapHashSet<WeakMember<SVGElement>> elements_with_relative_lengths_;
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_element_rare_data.h b/chromium/third_party/blink/renderer/core/svg/svg_element_rare_data.h
index f68e1069979..05881f5f07b 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_element_rare_data.h
+++ b/chromium/third_party/blink/renderer/core/svg/svg_element_rare_data.h
@@ -76,7 +76,7 @@ class SVGElementRareData final : public GarbageCollected<SVGElementRareData> {
return web_animated_attributes_dirty_;
}
- HashSet<const QualifiedName*>& WebAnimatedAttributes() {
+ HashSet<QualifiedName>& WebAnimatedAttributes() {
return web_animated_attributes_;
}
@@ -117,7 +117,7 @@ class SVGElementRareData final : public GarbageCollected<SVGElementRareData> {
bool use_override_computed_style_ : 1;
bool needs_override_computed_style_update_ : 1;
bool web_animated_attributes_dirty_ : 1;
- HashSet<const QualifiedName*> web_animated_attributes_;
+ HashSet<QualifiedName> web_animated_attributes_;
Member<MutableCSSPropertyValueSet> animated_smil_style_properties_;
scoped_refptr<ComputedStyle> override_computed_style_;
// Used by <animateMotion>
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_external_document_cache.cc b/chromium/third_party/blink/renderer/core/svg/svg_external_document_cache.cc
new file mode 100644
index 00000000000..91a0eaaf0c1
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/svg/svg_external_document_cache.cc
@@ -0,0 +1,134 @@
+/*
+ Copyright (C) 2010 Rob Buis <rwlbuis@gmail.com>
+ Copyright (C) 2011 Cosmin Truta <ctruta@gmail.com>
+ Copyright (C) 2012 University of Szeged
+ Copyright (C) 2012 Renata Hodovan <reni@webkit.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "third_party/blink/renderer/core/svg/svg_external_document_cache.h"
+
+#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h"
+#include "third_party/blink/renderer/core/dom/document.h"
+#include "third_party/blink/renderer/core/dom/document_init.h"
+#include "third_party/blink/renderer/core/dom/xml_document.h"
+#include "third_party/blink/renderer/core/loader/resource/text_resource.h"
+#include "third_party/blink/renderer/platform/loader/fetch/fetch_parameters.h"
+
+namespace blink {
+
+namespace {
+
+bool MimeTypeAllowed(const ResourceResponse& response) {
+ AtomicString mime_type = response.MimeType();
+ if (response.IsHTTP())
+ mime_type = response.HttpContentType();
+ return mime_type == "image/svg+xml" || mime_type == "text/xml" ||
+ mime_type == "application/xml" || mime_type == "application/xhtml+xml";
+}
+
+} // namespace
+
+void SVGExternalDocumentCache::Entry::AddClient(Client* client) {
+ if (!GetResource()->IsLoaded()) {
+ clients_.insert(client);
+ return;
+ }
+ context_document_->GetTaskRunner(TaskType::kInternalLoading)
+ ->PostTask(
+ FROM_HERE,
+ WTF::Bind(&SVGExternalDocumentCache::Client::NotifyFinished,
+ WrapPersistent(client), WrapPersistent(document_.Get())));
+}
+
+void SVGExternalDocumentCache::Entry::NotifyFinished(Resource* resource) {
+ DCHECK_EQ(GetResource(), resource);
+ for (auto client : clients_) {
+ if (client)
+ client->NotifyFinished(GetDocument());
+ }
+}
+
+Document* SVGExternalDocumentCache::Entry::GetDocument() {
+ const TextResource* resource = To<TextResource>(GetResource());
+ if (!document_ && resource->IsLoaded() && resource->HasData() &&
+ MimeTypeAllowed(resource->GetResponse())) {
+ document_ = XMLDocument::CreateSVG(
+ DocumentInit::Create()
+ .WithURL(resource->GetResponse().CurrentRequestUrl())
+ .WithContextDocument(context_document_));
+ document_->SetContent(resource->DecodedText());
+ }
+ return document_.Get();
+}
+
+void SVGExternalDocumentCache::Entry::Trace(Visitor* visitor) {
+ ResourceClient::Trace(visitor);
+ visitor->Trace(document_);
+ visitor->Trace(context_document_);
+ visitor->Trace(clients_);
+}
+
+const char SVGExternalDocumentCache::kSupplementName[] =
+ "SVGExternalDocumentCache";
+
+SVGExternalDocumentCache* SVGExternalDocumentCache::From(Document& document) {
+ SVGExternalDocumentCache* cache =
+ Supplement<Document>::From<SVGExternalDocumentCache>(document);
+ if (!cache) {
+ cache = MakeGarbageCollected<SVGExternalDocumentCache>(document);
+ Supplement<Document>::ProvideTo(document, cache);
+ }
+ return cache;
+}
+
+SVGExternalDocumentCache::SVGExternalDocumentCache(Document& document)
+ : Supplement<Document>(document) {}
+
+SVGExternalDocumentCache::Entry* SVGExternalDocumentCache::Get(
+ Client* client,
+ const KURL& url,
+ const AtomicString& initiator_name,
+ network::mojom::blink::CSPDisposition csp_disposition) {
+ ResourceLoaderOptions options;
+ options.initiator_info.name = initiator_name;
+ FetchParameters params(ResourceRequest(url), options);
+ params.SetContentSecurityCheck(csp_disposition);
+ params.MutableResourceRequest().SetMode(
+ network::mojom::blink::RequestMode::kSameOrigin);
+ params.SetRequestContext(mojom::blink::RequestContextType::IMAGE);
+ params.SetRequestDestination(network::mojom::RequestDestination::kImage);
+
+ Document* context_document = GetSupplementable();
+ Entry* entry = MakeGarbageCollected<Entry>(context_document);
+ Resource* resource = TextResource::FetchSVGDocument(
+ params, context_document->Fetcher(), entry);
+ // TODO(fs): Handle revalidations that return a new/different resource without
+ // needing to throw away the old Entry.
+ if (resource && resource->IsCacheValidator())
+ entries_.erase(resource);
+ entry = entries_.insert(resource, entry).stored_value->value;
+ entry->AddClient(client);
+ return entry;
+}
+
+void SVGExternalDocumentCache::Trace(Visitor* visitor) {
+ Supplement<Document>::Trace(visitor);
+ visitor->Trace(entries_);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_external_document_cache.h b/chromium/third_party/blink/renderer/core/svg/svg_external_document_cache.h
new file mode 100644
index 00000000000..a5eba9a0da4
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/svg/svg_external_document_cache.h
@@ -0,0 +1,89 @@
+/*
+ Copyright (C) 2010 Rob Buis <rwlbuis@gmail.com>
+ Copyright (C) 2011 Cosmin Truta <ctruta@gmail.com>
+ Copyright (C) 2012 University of Szeged
+ Copyright (C) 2012 Renata Hodovan <reni@webkit.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_SVG_SVG_EXTERNAL_DOCUMENT_CACHE_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_SVG_SVG_EXTERNAL_DOCUMENT_CACHE_H_
+
+#include "services/network/public/mojom/content_security_policy.mojom-blink.h"
+#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/platform/heap/handle.h"
+#include "third_party/blink/renderer/platform/loader/fetch/resource.h"
+#include "third_party/blink/renderer/platform/loader/fetch/resource_client.h"
+#include "third_party/blink/renderer/platform/supplementable.h"
+
+namespace blink {
+class Document;
+
+class CORE_EXPORT SVGExternalDocumentCache
+ : public GarbageCollected<SVGExternalDocumentCache>,
+ public Supplement<Document> {
+ USING_GARBAGE_COLLECTED_MIXIN(SVGExternalDocumentCache);
+
+ public:
+ static const char kSupplementName[];
+ static SVGExternalDocumentCache* From(Document&);
+ explicit SVGExternalDocumentCache(Document&);
+ void Trace(Visitor*) override;
+
+ class Client : public GarbageCollectedMixin {
+ public:
+ virtual void NotifyFinished(Document*) = 0;
+ };
+
+ class CORE_EXPORT Entry final : public GarbageCollected<Entry>,
+ public ResourceClient {
+ USING_GARBAGE_COLLECTED_MIXIN(Entry);
+
+ public:
+ explicit Entry(Document* context_document)
+ : context_document_(context_document) {}
+ ~Entry() override = default;
+ void Trace(Visitor*) override;
+ Document* GetDocument();
+ const KURL& Url() const { return GetResource()->Url(); }
+
+ private:
+ friend class SVGExternalDocumentCache;
+ void AddClient(Client*);
+
+ // ResourceClient overrides;
+ void NotifyFinished(Resource*) override;
+ String DebugName() const override { return "SVGExternalDocumentCache"; }
+
+ Member<Document> document_;
+ Member<Document> context_document_;
+ HeapHashSet<WeakMember<Client>> clients_;
+ };
+
+ Entry* Get(Client*,
+ const KURL&,
+ const AtomicString& initiator_name,
+ network::mojom::blink::CSPDisposition =
+ network::mojom::blink::CSPDisposition::CHECK);
+
+ private:
+ HeapHashMap<WeakMember<Resource>, WeakMember<Entry>> entries_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_SVG_SVG_EXTERNAL_DOCUMENT_CACHE_H_
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_external_document_cache_test.cc b/chromium/third_party/blink/renderer/core/svg/svg_external_document_cache_test.cc
new file mode 100644
index 00000000000..d4389f4ef92
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/svg/svg_external_document_cache_test.cc
@@ -0,0 +1,53 @@
+// 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/core/svg/svg_external_document_cache.h"
+
+#include "third_party/blink/renderer/core/dom/document.h"
+#include "third_party/blink/renderer/core/testing/sim/sim_request.h"
+#include "third_party/blink/renderer/core/testing/sim/sim_test.h"
+#include "third_party/blink/renderer/platform/loader/fetch/fetch_initiator_type_names.h"
+
+namespace blink {
+
+class DummyCacheClient : public GarbageCollected<DummyCacheClient>,
+ public SVGExternalDocumentCache::Client {
+ USING_GARBAGE_COLLECTED_MIXIN(DummyCacheClient);
+
+ public:
+ DummyCacheClient() = default;
+ void NotifyFinished(Document*) override {}
+};
+
+class SVGExternalDocumentCacheTest : public SimTest {};
+
+TEST_F(SVGExternalDocumentCacheTest, GetDocumentBeforeLoadComplete) {
+ SimRequest main_resource("https://example.com/test.html", "text/html");
+ LoadURL("https://example.com/test.html");
+ main_resource.Complete("<html><body></body></html>");
+
+ const char kSVGUrl[] = "https://example.com/svg.svg";
+ SimRequest::Params params;
+ params.response_http_headers = {{"Content-Type", "application/xml"}};
+ SimSubresourceRequest svg_resource(kSVGUrl, "application/xml", params);
+ DummyCacheClient* client = MakeGarbageCollected<DummyCacheClient>();
+
+ // Request a resource from the cache.
+ auto* entry =
+ SVGExternalDocumentCache::From(GetDocument())
+ ->Get(client, KURL(kSVGUrl), fetch_initiator_type_names::kCSS);
+
+ // Write part of the response. The document should not be initialized yet,
+ // because the response is not complete. The document would be invalid at this
+ // point.
+ svg_resource.Start();
+ svg_resource.Write("<sv");
+ EXPECT_EQ(nullptr, entry->GetDocument());
+
+ // Finish the response, the Document should now be accessible.
+ svg_resource.Complete("g></svg>");
+ EXPECT_NE(nullptr, entry->GetDocument());
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_fe_blend_element.idl b/chromium/third_party/blink/renderer/core/svg/svg_fe_blend_element.idl
index a59c5700909..e2494e64267 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_fe_blend_element.idl
+++ b/chromium/third_party/blink/renderer/core/svg/svg_fe_blend_element.idl
@@ -26,7 +26,8 @@
// https://drafts.fxtf.org/filter-effects/#InterfaceSVGFEBlendElement
[
- DoNotCheckConstants
+ DoNotCheckConstants,
+ Exposed=Window
] interface SVGFEBlendElement : SVGElement {
// Blend Mode Types
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_fe_color_matrix_element.idl b/chromium/third_party/blink/renderer/core/svg/svg_fe_color_matrix_element.idl
index 48a98cd81e1..57691cb3d64 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_fe_color_matrix_element.idl
+++ b/chromium/third_party/blink/renderer/core/svg/svg_fe_color_matrix_element.idl
@@ -26,7 +26,8 @@
// https://drafts.fxtf.org/filter-effects/#InterfaceSVGFEColorMatrixElement
[
- DoNotCheckConstants
+ DoNotCheckConstants,
+ Exposed=Window
] interface SVGFEColorMatrixElement : SVGElement {
// Color Matrix Types
[MeasureAs=SVG1DOMFilter] const unsigned short SVG_FECOLORMATRIX_TYPE_UNKNOWN = 0;
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_fe_component_transfer_element.idl b/chromium/third_party/blink/renderer/core/svg/svg_fe_component_transfer_element.idl
index dcb417db531..52a4341ea37 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_fe_component_transfer_element.idl
+++ b/chromium/third_party/blink/renderer/core/svg/svg_fe_component_transfer_element.idl
@@ -25,7 +25,9 @@
// https://drafts.fxtf.org/filter-effects/#InterfaceSVGFEComponentTransferElement
-interface SVGFEComponentTransferElement : SVGElement {
+[
+ Exposed=Window
+] interface SVGFEComponentTransferElement : SVGElement {
[MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedString in1;
};
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_fe_composite_element.idl b/chromium/third_party/blink/renderer/core/svg/svg_fe_composite_element.idl
index 4723b0184bc..9d0591f866b 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_fe_composite_element.idl
+++ b/chromium/third_party/blink/renderer/core/svg/svg_fe_composite_element.idl
@@ -26,7 +26,8 @@
// https://drafts.fxtf.org/filter-effects/#InterfaceSVGFECompositeElement
[
- DoNotCheckConstants
+ DoNotCheckConstants,
+ Exposed=Window
] interface SVGFECompositeElement : SVGElement {
// Composite Operators
[MeasureAs=SVG1DOMFilter] const unsigned short SVG_FECOMPOSITE_OPERATOR_UNKNOWN = 0;
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_fe_convolve_matrix_element.idl b/chromium/third_party/blink/renderer/core/svg/svg_fe_convolve_matrix_element.idl
index d1b8c08a9dc..132be88d825 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_fe_convolve_matrix_element.idl
+++ b/chromium/third_party/blink/renderer/core/svg/svg_fe_convolve_matrix_element.idl
@@ -26,7 +26,8 @@
// https://drafts.fxtf.org/filter-effects/#InterfaceSVGFEConvolveMatrixElement
[
- DoNotCheckConstants
+ DoNotCheckConstants,
+ Exposed=Window
] interface SVGFEConvolveMatrixElement : SVGElement {
// Edge Mode Values
[MeasureAs=SVG1DOMFilter] const unsigned short SVG_EDGEMODE_UNKNOWN = 0;
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_fe_diffuse_lighting_element.idl b/chromium/third_party/blink/renderer/core/svg/svg_fe_diffuse_lighting_element.idl
index b03edec17bd..593d161e87d 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_fe_diffuse_lighting_element.idl
+++ b/chromium/third_party/blink/renderer/core/svg/svg_fe_diffuse_lighting_element.idl
@@ -25,7 +25,9 @@
// https://drafts.fxtf.org/filter-effects/#InterfaceSVGFEDiffuseLightingElement
-interface SVGFEDiffuseLightingElement : SVGElement {
+[
+ Exposed=Window
+] interface SVGFEDiffuseLightingElement : SVGElement {
[MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedString in1;
[MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedNumber surfaceScale;
[MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedNumber diffuseConstant;
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_fe_displacement_map_element.idl b/chromium/third_party/blink/renderer/core/svg/svg_fe_displacement_map_element.idl
index c2879c4c7d1..d1c64314e84 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_fe_displacement_map_element.idl
+++ b/chromium/third_party/blink/renderer/core/svg/svg_fe_displacement_map_element.idl
@@ -26,7 +26,8 @@
// https://drafts.fxtf.org/filter-effects/#InterfaceSVGFEDisplacementMapElement
[
- DoNotCheckConstants
+ DoNotCheckConstants,
+ Exposed=Window
] interface SVGFEDisplacementMapElement : SVGElement {
// Channel Selectors
[MeasureAs=SVG1DOMFilter] const unsigned short SVG_CHANNEL_UNKNOWN = 0;
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_fe_distant_light_element.idl b/chromium/third_party/blink/renderer/core/svg/svg_fe_distant_light_element.idl
index 4c2cd05fbbb..0efa53094f8 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_fe_distant_light_element.idl
+++ b/chromium/third_party/blink/renderer/core/svg/svg_fe_distant_light_element.idl
@@ -25,7 +25,9 @@
// https://drafts.fxtf.org/filter-effects/#InterfaceSVGFEDistantLightElement
-interface SVGFEDistantLightElement : SVGElement {
+[
+ Exposed=Window
+] interface SVGFEDistantLightElement : SVGElement {
[MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedNumber azimuth;
[MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedNumber elevation;
};
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_fe_drop_shadow_element.idl b/chromium/third_party/blink/renderer/core/svg/svg_fe_drop_shadow_element.idl
index d07d5b45d87..7766e416c02 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_fe_drop_shadow_element.idl
+++ b/chromium/third_party/blink/renderer/core/svg/svg_fe_drop_shadow_element.idl
@@ -19,7 +19,9 @@
// https://drafts.fxtf.org/filter-effects/#InterfaceSVGFEDropShadowElement
-interface SVGFEDropShadowElement : SVGElement {
+[
+ Exposed=Window
+] interface SVGFEDropShadowElement : SVGElement {
[MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedString in1;
[MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedNumber dx;
[MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedNumber dy;
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_fe_flood_element.idl b/chromium/third_party/blink/renderer/core/svg/svg_fe_flood_element.idl
index 973cc2ed86d..e0b322edb93 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_fe_flood_element.idl
+++ b/chromium/third_party/blink/renderer/core/svg/svg_fe_flood_element.idl
@@ -25,7 +25,9 @@
// https://drafts.fxtf.org/filter-effects/#InterfaceSVGFEFloodElement
-interface SVGFEFloodElement : SVGElement {
+[
+ Exposed=Window
+] interface SVGFEFloodElement : SVGElement {
};
SVGFEFloodElement includes SVGFilterPrimitiveStandardAttributes;
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_fe_func_a_element.idl b/chromium/third_party/blink/renderer/core/svg/svg_fe_func_a_element.idl
index 1fab5298c26..4e5bed15567 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_fe_func_a_element.idl
+++ b/chromium/third_party/blink/renderer/core/svg/svg_fe_func_a_element.idl
@@ -25,5 +25,7 @@
// https://drafts.fxtf.org/filter-effects/#InterfaceSVGFEFuncAElement
-interface SVGFEFuncAElement : SVGComponentTransferFunctionElement {
+[
+ Exposed=Window
+] interface SVGFEFuncAElement : SVGComponentTransferFunctionElement {
};
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_fe_func_b_element.idl b/chromium/third_party/blink/renderer/core/svg/svg_fe_func_b_element.idl
index 094d6b97a38..62a8f86c932 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_fe_func_b_element.idl
+++ b/chromium/third_party/blink/renderer/core/svg/svg_fe_func_b_element.idl
@@ -25,5 +25,7 @@
// https://drafts.fxtf.org/filter-effects/#InterfaceSVGFEFuncBElement
-interface SVGFEFuncBElement : SVGComponentTransferFunctionElement {
+[
+ Exposed=Window
+] interface SVGFEFuncBElement : SVGComponentTransferFunctionElement {
};
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_fe_func_g_element.idl b/chromium/third_party/blink/renderer/core/svg/svg_fe_func_g_element.idl
index f6917930cec..4c55b1ca26d 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_fe_func_g_element.idl
+++ b/chromium/third_party/blink/renderer/core/svg/svg_fe_func_g_element.idl
@@ -25,5 +25,7 @@
// https://drafts.fxtf.org/filter-effects/#InterfaceSVGFEFuncGElement
-interface SVGFEFuncGElement : SVGComponentTransferFunctionElement {
+[
+ Exposed=Window
+] interface SVGFEFuncGElement : SVGComponentTransferFunctionElement {
};
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_fe_func_r_element.idl b/chromium/third_party/blink/renderer/core/svg/svg_fe_func_r_element.idl
index 4f943709a92..98e41f395ba 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_fe_func_r_element.idl
+++ b/chromium/third_party/blink/renderer/core/svg/svg_fe_func_r_element.idl
@@ -25,5 +25,7 @@
// https://drafts.fxtf.org/filter-effects/#InterfaceSVGFEFuncRElement
-interface SVGFEFuncRElement : SVGComponentTransferFunctionElement {
+[
+ Exposed=Window
+] interface SVGFEFuncRElement : SVGComponentTransferFunctionElement {
};
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_fe_gaussian_blur_element.idl b/chromium/third_party/blink/renderer/core/svg/svg_fe_gaussian_blur_element.idl
index a0fc0861410..31392491738 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_fe_gaussian_blur_element.idl
+++ b/chromium/third_party/blink/renderer/core/svg/svg_fe_gaussian_blur_element.idl
@@ -25,7 +25,9 @@
// https://drafts.fxtf.org/filter-effects/#InterfaceSVGFEGaussianBlurElement
-interface SVGFEGaussianBlurElement : SVGElement {
+[
+ Exposed=Window
+] interface SVGFEGaussianBlurElement : SVGElement {
[MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedString in1;
[MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedNumber stdDeviationX;
[MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedNumber stdDeviationY;
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_fe_image_element.cc b/chromium/third_party/blink/renderer/core/svg/svg_fe_image_element.cc
index e56a87a6e2f..daa126edaef 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_fe_image_element.cc
+++ b/chromium/third_party/blink/renderer/core/svg/svg_fe_image_element.cc
@@ -150,6 +150,13 @@ void SVGFEImageElement::ImageNotifyFinished(ImageResourceContent*) {
MarkForLayoutAndParentResourceInvalidation(*layout_object);
}
+const SVGElement* SVGFEImageElement::TargetElement() const {
+ if (cached_image_)
+ return nullptr;
+ return DynamicTo<SVGElement>(
+ TargetElementFromIRIString(HrefString(), GetTreeScope()));
+}
+
FilterEffect* SVGFEImageElement::Build(SVGFilterBuilder*, Filter* filter) {
if (cached_image_) {
// Don't use the broken image icon on image loading errors.
@@ -158,9 +165,7 @@ FilterEffect* SVGFEImageElement::Build(SVGFilterBuilder*, Filter* filter) {
return MakeGarbageCollected<FEImage>(
filter, image, preserve_aspect_ratio_->CurrentValue());
}
- const SVGElement* target = DynamicTo<SVGElement>(
- TargetElementFromIRIString(HrefString(), GetTreeScope()));
- return MakeGarbageCollected<FEImage>(filter, target,
+ return MakeGarbageCollected<FEImage>(filter, TargetElement(),
preserve_aspect_ratio_->CurrentValue());
}
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_fe_image_element.h b/chromium/third_party/blink/renderer/core/svg/svg_fe_image_element.h
index ce245c2c170..2366d7b9dac 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_fe_image_element.h
+++ b/chromium/third_party/blink/renderer/core/svg/svg_fe_image_element.h
@@ -48,6 +48,8 @@ class SVGFEImageElement final : public SVGFilterPrimitiveStandardAttributes,
return preserve_aspect_ratio_.Get();
}
+ const SVGElement* TargetElement() const;
+
void Dispose();
void Trace(Visitor*) override;
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_fe_image_element.idl b/chromium/third_party/blink/renderer/core/svg/svg_fe_image_element.idl
index b9c46617b18..69340c231ee 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_fe_image_element.idl
+++ b/chromium/third_party/blink/renderer/core/svg/svg_fe_image_element.idl
@@ -25,7 +25,9 @@
// https://drafts.fxtf.org/filter-effects/#InterfaceSVGFEImageElement
-interface SVGFEImageElement : SVGElement {
+[
+ Exposed=Window
+] interface SVGFEImageElement : SVGElement {
[MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedPreserveAspectRatio preserveAspectRatio;
};
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_fe_merge_element.idl b/chromium/third_party/blink/renderer/core/svg/svg_fe_merge_element.idl
index d53acdabbc6..ef23402f4db 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_fe_merge_element.idl
+++ b/chromium/third_party/blink/renderer/core/svg/svg_fe_merge_element.idl
@@ -25,7 +25,9 @@
// https://drafts.fxtf.org/filter-effects/#InterfaceSVGFEMergeElement
-interface SVGFEMergeElement : SVGElement {
+[
+ Exposed=Window
+] interface SVGFEMergeElement : SVGElement {
};
SVGFEMergeElement includes SVGFilterPrimitiveStandardAttributes;
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_fe_merge_node_element.idl b/chromium/third_party/blink/renderer/core/svg/svg_fe_merge_node_element.idl
index cbe50705fa0..5cdde1ff4d3 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_fe_merge_node_element.idl
+++ b/chromium/third_party/blink/renderer/core/svg/svg_fe_merge_node_element.idl
@@ -25,6 +25,8 @@
// https://drafts.fxtf.org/filter-effects/#InterfaceSVGFEMergeNodeElement
-interface SVGFEMergeNodeElement : SVGElement {
+[
+ Exposed=Window
+] interface SVGFEMergeNodeElement : SVGElement {
[MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedString in1;
};
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_fe_morphology_element.idl b/chromium/third_party/blink/renderer/core/svg/svg_fe_morphology_element.idl
index 9187763f4e5..bccff872c5f 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_fe_morphology_element.idl
+++ b/chromium/third_party/blink/renderer/core/svg/svg_fe_morphology_element.idl
@@ -26,7 +26,8 @@
// https://drafts.fxtf.org/filter-effects/#InterfaceSVGFEMorphologyElement
[
- DoNotCheckConstants
+ DoNotCheckConstants,
+ Exposed=Window
] interface SVGFEMorphologyElement : SVGElement {
// Morphology Operators
[MeasureAs=SVG1DOMFilter] const unsigned short SVG_MORPHOLOGY_OPERATOR_UNKNOWN = 0;
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_fe_offset_element.idl b/chromium/third_party/blink/renderer/core/svg/svg_fe_offset_element.idl
index 5278f274752..187b340e7ee 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_fe_offset_element.idl
+++ b/chromium/third_party/blink/renderer/core/svg/svg_fe_offset_element.idl
@@ -25,7 +25,9 @@
// https://drafts.fxtf.org/filter-effects/#InterfaceSVGFEOffsetElement
-interface SVGFEOffsetElement : SVGElement {
+[
+ Exposed=Window
+] interface SVGFEOffsetElement : SVGElement {
[MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedString in1;
[MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedNumber dx;
[MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedNumber dy;
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_fe_point_light_element.idl b/chromium/third_party/blink/renderer/core/svg/svg_fe_point_light_element.idl
index 4786632bc25..9ce287bc734 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_fe_point_light_element.idl
+++ b/chromium/third_party/blink/renderer/core/svg/svg_fe_point_light_element.idl
@@ -25,7 +25,9 @@
// https://drafts.fxtf.org/filter-effects/#InterfaceSVGFEPointLightElement
-interface SVGFEPointLightElement : SVGElement {
+[
+ Exposed=Window
+] interface SVGFEPointLightElement : SVGElement {
[MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedNumber x;
[MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedNumber y;
[MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedNumber z;
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_fe_specular_lighting_element.idl b/chromium/third_party/blink/renderer/core/svg/svg_fe_specular_lighting_element.idl
index 56470b1ea30..9a90e14b3be 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_fe_specular_lighting_element.idl
+++ b/chromium/third_party/blink/renderer/core/svg/svg_fe_specular_lighting_element.idl
@@ -25,7 +25,9 @@
// https://drafts.fxtf.org/filter-effects/#InterfaceSVGFESpecularLightingElement
-interface SVGFESpecularLightingElement : SVGElement {
+[
+ Exposed=Window
+] interface SVGFESpecularLightingElement : SVGElement {
[MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedString in1;
[MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedNumber surfaceScale;
[MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedNumber specularConstant;
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_fe_spot_light_element.idl b/chromium/third_party/blink/renderer/core/svg/svg_fe_spot_light_element.idl
index a6f634ecc23..bd4ee0c36c6 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_fe_spot_light_element.idl
+++ b/chromium/third_party/blink/renderer/core/svg/svg_fe_spot_light_element.idl
@@ -25,7 +25,9 @@
// https://drafts.fxtf.org/filter-effects/#InterfaceSVGFESpotLightElement
-interface SVGFESpotLightElement : SVGElement {
+[
+ Exposed=Window
+] interface SVGFESpotLightElement : SVGElement {
[MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedNumber x;
[MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedNumber y;
[MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedNumber z;
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_fe_tile_element.idl b/chromium/third_party/blink/renderer/core/svg/svg_fe_tile_element.idl
index 39cd9203036..ff6e867cc92 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_fe_tile_element.idl
+++ b/chromium/third_party/blink/renderer/core/svg/svg_fe_tile_element.idl
@@ -25,7 +25,9 @@
// https://drafts.fxtf.org/filter-effects/#InterfaceSVGFETileElement
-interface SVGFETileElement : SVGElement {
+[
+ Exposed=Window
+] interface SVGFETileElement : SVGElement {
[MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedString in1;
};
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_fe_turbulence_element.idl b/chromium/third_party/blink/renderer/core/svg/svg_fe_turbulence_element.idl
index 6259e4bb0c5..2351f3cd23f 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_fe_turbulence_element.idl
+++ b/chromium/third_party/blink/renderer/core/svg/svg_fe_turbulence_element.idl
@@ -26,7 +26,8 @@
// https://drafts.fxtf.org/filter-effects/#InterfaceSVGFETurbulenceElement
[
- DoNotCheckConstants
+ DoNotCheckConstants,
+ Exposed=Window
] interface SVGFETurbulenceElement : SVGElement {
// Turbulence Types
[MeasureAs=SVG1DOMFilter] const unsigned short SVG_TURBULENCE_TYPE_UNKNOWN = 0;
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_filter_element.idl b/chromium/third_party/blink/renderer/core/svg/svg_filter_element.idl
index 598013fc111..06e1295c078 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_filter_element.idl
+++ b/chromium/third_party/blink/renderer/core/svg/svg_filter_element.idl
@@ -26,7 +26,9 @@
// https://drafts.fxtf.org/filter-effects/#InterfaceSVGFilterElement
-interface SVGFilterElement : SVGElement {
+[
+ Exposed=Window
+] interface SVGFilterElement : SVGElement {
[MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedEnumeration filterUnits;
[MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedEnumeration primitiveUnits;
[MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedLength x;
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_geometry_element.cc b/chromium/third_party/blink/renderer/core/svg/svg_geometry_element.cc
index 78f2dbdb9d6..aad481f8d48 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_geometry_element.cc
+++ b/chromium/third_party/blink/renderer/core/svg/svg_geometry_element.cc
@@ -118,9 +118,17 @@ bool SVGGeometryElement::isPointInStroke(SVGPointTearOff* point) const {
layout_shape.ComputeNonScalingStrokeTransform();
path.Transform(transform);
local_point = transform.MapPoint(local_point);
+
+ // Un-scale to get back to the root-transform (cheaper than re-computing
+ // the root transform from scratch).
+ AffineTransform root_transform;
+ root_transform.Scale(layout_shape.StyleRef().EffectiveZoom())
+ .Multiply(transform);
+ return path.StrokeContains(local_point, stroke_data, root_transform);
}
// Path::StrokeContains will reject points with a non-finite component.
- return path.StrokeContains(local_point, stroke_data);
+ return path.StrokeContains(local_point, stroke_data,
+ layout_shape.ComputeRootTransform());
}
Path SVGGeometryElement::ToClipPath() const {
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_image_element.idl b/chromium/third_party/blink/renderer/core/svg/svg_image_element.idl
index e18c4ad3464..d99d7eed9f5 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_image_element.idl
+++ b/chromium/third_party/blink/renderer/core/svg/svg_image_element.idl
@@ -26,7 +26,8 @@
// https://svgwg.org/svg2-draft/embedded.html#InterfaceSVGImageElement
[
- ActiveScriptWrappable
+ ActiveScriptWrappable,
+ Exposed=Window
] interface SVGImageElement : SVGGraphicsElement {
[MeasureAs=SVG1DOMImageElement] readonly attribute SVGAnimatedLength x;
[MeasureAs=SVG1DOMImageElement] readonly attribute SVGAnimatedLength y;
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_length.cc b/chromium/third_party/blink/renderer/core/svg/svg_length.cc
index 9a0108d1c29..77535c4717d 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_length.cc
+++ b/chromium/third_party/blink/renderer/core/svg/svg_length.cc
@@ -85,27 +85,18 @@ SVGLength::SVGLength(const CSSPrimitiveValue& value, SVGLengthMode mode)
DCHECK_EQ(UnitMode(), mode);
}
-SVGLength::SVGLength(const SVGLength& o)
- : value_(o.value_), unit_mode_(o.unit_mode_) {}
-
void SVGLength::Trace(Visitor* visitor) {
visitor->Trace(value_);
SVGPropertyBase::Trace(visitor);
}
SVGLength* SVGLength::Clone() const {
- return MakeGarbageCollected<SVGLength>(*this);
+ return MakeGarbageCollected<SVGLength>(*value_, UnitMode());
}
SVGPropertyBase* SVGLength::CloneForAnimation(const String& value) const {
- auto* length = MakeGarbageCollected<SVGLength>();
- length->unit_mode_ = unit_mode_;
-
- if (length->SetValueAsString(value) != SVGParseStatus::kNoError) {
- length->value_ = CSSNumericLiteralValue::Create(
- 0, CSSPrimitiveValue::UnitType::kUserUnits);
- }
-
+ auto* length = MakeGarbageCollected<SVGLength>(UnitMode());
+ length->SetValueAsString(value);
return length;
}
@@ -165,10 +156,7 @@ static bool IsSupportedCalculationCategory(CalculationCategory category) {
case kCalcLength:
case kCalcNumber:
case kCalcPercent:
- case kCalcPercentNumber:
case kCalcPercentLength:
- case kCalcLengthNumber:
- case kCalcPercentLengthNumber:
return true;
default:
return false;
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_length.h b/chromium/third_party/blink/renderer/core/svg/svg_length.h
index 4b883d10f98..bb11984f65d 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_length.h
+++ b/chromium/third_party/blink/renderer/core/svg/svg_length.h
@@ -58,7 +58,6 @@ class CORE_EXPORT SVGLength final : public SVGPropertyBase {
explicit SVGLength(SVGLengthMode = SVGLengthMode::kOther);
SVGLength(Initial, SVGLengthMode);
SVGLength(const CSSPrimitiveValue&, SVGLengthMode);
- SVGLength(const SVGLength&);
void SetInitial(unsigned);
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_mask_element.idl b/chromium/third_party/blink/renderer/core/svg/svg_mask_element.idl
index 6cb896b983d..23415a02b0a 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_mask_element.idl
+++ b/chromium/third_party/blink/renderer/core/svg/svg_mask_element.idl
@@ -25,7 +25,9 @@
// https://drafts.fxtf.org/css-masking/#InterfaceSVGMaskElement
-interface SVGMaskElement : SVGElement {
+[
+ Exposed=Window
+] interface SVGMaskElement : SVGElement {
[MeasureAs=SVG1DOMMaskElement] readonly attribute SVGAnimatedEnumeration maskUnits;
[MeasureAs=SVG1DOMMaskElement] readonly attribute SVGAnimatedEnumeration maskContentUnits;
[MeasureAs=SVG1DOMMaskElement] readonly attribute SVGAnimatedLength x;
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_matrix.idl b/chromium/third_party/blink/renderer/core/svg/svg_matrix.idl
index 382fd1fa0a8..664fe2e4d0b 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_matrix.idl
+++ b/chromium/third_party/blink/renderer/core/svg/svg_matrix.idl
@@ -25,6 +25,7 @@
// TODO(foolip): SVGMatrix is gone from SVG 2, replaced by DOMMatrix.
// https://crbug.com/709001
[
+ Exposed=Window,
ImplementedAs=SVGMatrixTearOff
] interface SVGMatrix {
// FIXME: these attributes should all be floats but since we implement
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_mpath_element.idl b/chromium/third_party/blink/renderer/core/svg/svg_mpath_element.idl
index 332e69aa32f..330601854c2 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_mpath_element.idl
+++ b/chromium/third_party/blink/renderer/core/svg/svg_mpath_element.idl
@@ -25,7 +25,9 @@
// https://svgwg.org/specs/animations/#InterfaceSVGMPathElement
-interface SVGMPathElement : SVGElement {
+[
+ Exposed=Window
+] interface SVGMPathElement : SVGElement {
};
SVGMPathElement includes SVGURIReference;
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_point.idl b/chromium/third_party/blink/renderer/core/svg/svg_point.idl
index ed74a5a591f..1c8a6a9519f 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_point.idl
+++ b/chromium/third_party/blink/renderer/core/svg/svg_point.idl
@@ -25,6 +25,7 @@
// TODO(foolip): SVGPoint is gone from SVG 2, replaced by DOMPoint.
// https://crbug.com/709001
[
+ Exposed=Window,
ImplementedAs=SVGPointTearOff
] interface SVGPoint {
[RaisesException=Setter] attribute unrestricted float x;
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_poly_element.cc b/chromium/third_party/blink/renderer/core/svg/svg_poly_element.cc
index 741dda2047e..43555c37454 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_poly_element.cc
+++ b/chromium/third_party/blink/renderer/core/svg/svg_poly_element.cc
@@ -44,18 +44,18 @@ void SVGPolyElement::Trace(Visitor* visitor) {
Path SVGPolyElement::AsPathFromPoints() const {
Path path;
- SVGPointList* points_value = Points()->CurrentValue();
+ const SVGPointList* points_value = Points()->CurrentValue();
if (points_value->IsEmpty())
return path;
- SVGPointList::ConstIterator it = points_value->begin();
- SVGPointList::ConstIterator it_end = points_value->end();
+ const auto* it = points_value->begin();
+ const auto* it_end = points_value->end();
DCHECK(it != it_end);
- path.MoveTo(it->Value());
+ path.MoveTo((*it)->Value());
++it;
for (; it != it_end; ++it)
- path.AddLineTo(it->Value());
+ path.AddLineTo((*it)->Value());
return path;
}
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_rect.idl b/chromium/third_party/blink/renderer/core/svg/svg_rect.idl
index c9e10b7c053..4950068b4a8 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_rect.idl
+++ b/chromium/third_party/blink/renderer/core/svg/svg_rect.idl
@@ -25,6 +25,7 @@
// TODO(foolip): SVGRect is gone from SVG 2, replaced by DOMRect.
// https://crbug.com/709001
[
+ Exposed=Window,
ImplementedAs=SVGRectTearOff
] interface SVGRect {
[RaisesException=Setter] attribute unrestricted float x;
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_resource.cc b/chromium/third_party/blink/renderer/core/svg/svg_resource.cc
index 110d32b4748..b10a69917be 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_resource.cc
+++ b/chromium/third_party/blink/renderer/core/svg/svg_resource.cc
@@ -9,12 +9,9 @@
#include "third_party/blink/renderer/core/dom/id_target_observer.h"
#include "third_party/blink/renderer/core/dom/tree_scope.h"
#include "third_party/blink/renderer/core/layout/svg/layout_svg_resource_container.h"
-#include "third_party/blink/renderer/core/loader/resource/document_resource.h"
#include "third_party/blink/renderer/core/svg/svg_uri_reference.h"
#include "third_party/blink/renderer/platform/loader/fetch/fetch_initiator_type_names.h"
-#include "third_party/blink/renderer/platform/loader/fetch/fetch_parameters.h"
-#include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h"
-#include "third_party/blink/renderer/platform/loader/fetch/resource_loader_options.h"
+#include "third_party/blink/renderer/platform/loader/fetch/resource.h"
namespace blink {
@@ -132,35 +129,24 @@ void LocalSVGResource::Trace(Visitor* visitor) {
ExternalSVGResource::ExternalSVGResource(const KURL& url) : url_(url) {}
-void ExternalSVGResource::Load(const Document& document) {
- if (resource_document_)
+void ExternalSVGResource::Load(Document& document) {
+ if (cache_entry_)
return;
- ResourceLoaderOptions options;
- options.initiator_info.name = fetch_initiator_type_names::kCSS;
- FetchParameters params(ResourceRequest(url_), options);
- params.MutableResourceRequest().SetMode(
- network::mojom::blink::RequestMode::kSameOrigin);
- resource_document_ =
- DocumentResource::FetchSVGDocument(params, document, this);
+ cache_entry_ = SVGExternalDocumentCache::From(document)->Get(
+ this, url_, fetch_initiator_type_names::kCSS);
target_ = ResolveTarget();
}
-void ExternalSVGResource::LoadWithoutCSP(const Document& document) {
- if (resource_document_)
+void ExternalSVGResource::LoadWithoutCSP(Document& document) {
+ if (cache_entry_)
return;
- ResourceLoaderOptions options;
- options.initiator_info.name = fetch_initiator_type_names::kCSS;
- FetchParameters params(ResourceRequest(url_), options);
- params.SetContentSecurityCheck(
+ cache_entry_ = SVGExternalDocumentCache::From(document)->Get(
+ this, url_, fetch_initiator_type_names::kCSS,
network::mojom::blink::CSPDisposition::DO_NOT_CHECK);
- params.MutableResourceRequest().SetMode(
- network::mojom::blink::RequestMode::kSameOrigin);
- resource_document_ =
- DocumentResource::FetchSVGDocument(params, document, this);
target_ = ResolveTarget();
}
-void ExternalSVGResource::NotifyFinished(Resource*) {
+void ExternalSVGResource::NotifyFinished(Document*) {
Element* new_target = ResolveTarget();
if (new_target == target_)
return;
@@ -168,16 +154,12 @@ void ExternalSVGResource::NotifyFinished(Resource*) {
NotifyElementChanged();
}
-String ExternalSVGResource::DebugName() const {
- return "ExternalSVGResource";
-}
-
Element* ExternalSVGResource::ResolveTarget() {
- if (!resource_document_)
+ if (!cache_entry_)
return nullptr;
if (!url_.HasFragmentIdentifier())
return nullptr;
- Document* external_document = resource_document_->GetDocument();
+ Document* external_document = cache_entry_->GetDocument();
if (!external_document)
return nullptr;
AtomicString decoded_fragment(DecodeURLEscapeSequences(
@@ -186,9 +168,9 @@ Element* ExternalSVGResource::ResolveTarget() {
}
void ExternalSVGResource::Trace(Visitor* visitor) {
- visitor->Trace(resource_document_);
+ visitor->Trace(cache_entry_);
SVGResource::Trace(visitor);
- ResourceClient::Trace(visitor);
+ SVGExternalDocumentCache::Client::Trace(visitor);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_resource.h b/chromium/third_party/blink/renderer/core/svg/svg_resource.h
index aab5fd2da1a..15bc41f5e75 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_resource.h
+++ b/chromium/third_party/blink/renderer/core/svg/svg_resource.h
@@ -6,9 +6,9 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_SVG_SVG_RESOURCE_H_
#include "base/macros.h"
+#include "third_party/blink/renderer/core/svg/svg_external_document_cache.h"
#include "third_party/blink/renderer/core/svg/svg_resource_client.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
-#include "third_party/blink/renderer/platform/loader/fetch/resource_client.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
#include "third_party/blink/renderer/platform/wtf/hash_counted_set.h"
#include "third_party/blink/renderer/platform/wtf/hash_set.h"
@@ -17,7 +17,6 @@
namespace blink {
class Document;
-class DocumentResource;
class Element;
class IdTargetObserver;
class LayoutSVGResourceContainer;
@@ -63,8 +62,8 @@ class SVGResource : public GarbageCollected<SVGResource> {
public:
virtual ~SVGResource();
- virtual void Load(const Document&) {}
- virtual void LoadWithoutCSP(const Document&) {}
+ virtual void Load(Document&) {}
+ virtual void LoadWithoutCSP(Document&) {}
Element* Target() const { return target_; }
LayoutSVGResourceContainer* ResourceContainer() const;
@@ -111,26 +110,26 @@ class LocalSVGResource final : public SVGResource {
};
// External resource reference (see SVGResource.)
-class ExternalSVGResource final : public SVGResource, private ResourceClient {
+class ExternalSVGResource final : public SVGResource,
+ private SVGExternalDocumentCache::Client {
USING_GARBAGE_COLLECTED_MIXIN(ExternalSVGResource);
public:
explicit ExternalSVGResource(const KURL&);
- void Load(const Document&) override;
- void LoadWithoutCSP(const Document&) override;
+ void Load(Document&) override;
+ void LoadWithoutCSP(Document&) override;
void Trace(Visitor*) override;
private:
Element* ResolveTarget();
- // ResourceClient implementation
- String DebugName() const override;
- void NotifyFinished(Resource*) override;
+ // SVGExternalDocumentCache::Client implementation
+ void NotifyFinished(Document*) override;
+ Member<SVGExternalDocumentCache::Entry> cache_entry_;
KURL url_;
- Member<DocumentResource> resource_document_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_script_element.cc b/chromium/third_party/blink/renderer/core/svg/svg_script_element.cc
index 4efb5d34b65..3d274d2436b 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_script_element.cc
+++ b/chromium/third_party/blink/renderer/core/svg/svg_script_element.cc
@@ -147,6 +147,10 @@ Document& SVGScriptElement::GetDocument() const {
return Node::GetDocument();
}
+ExecutionContext* SVGScriptElement::GetExecutionContext() const {
+ return Node::GetExecutionContext();
+}
+
Element& SVGScriptElement::CloneWithoutAttributesAndChildren(
Document& factory) const {
CreateElementFlags flags =
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_script_element.h b/chromium/third_party/blink/renderer/core/svg/svg_script_element.h
index 91c98f76fb0..e24d3f074df 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_script_element.h
+++ b/chromium/third_party/blink/renderer/core/svg/svg_script_element.h
@@ -95,6 +95,7 @@ class SVGScriptElement final : public SVGElement,
const WTF::OrdinalNumber&,
const String& script_content) override;
Document& GetDocument() const override;
+ ExecutionContext* GetExecutionContext() const override;
void DispatchLoadEvent() override;
void DispatchErrorEvent() override;
void SetScriptElementForBinding(
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_set_element.idl b/chromium/third_party/blink/renderer/core/svg/svg_set_element.idl
index ecb0229c9bf..4fa9c80c9a8 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_set_element.idl
+++ b/chromium/third_party/blink/renderer/core/svg/svg_set_element.idl
@@ -25,5 +25,7 @@
// https://svgwg.org/specs/animations/#InterfaceSVGSetElement
-interface SVGSetElement : SVGAnimationElement {
+[
+ Exposed=Window
+] interface SVGSetElement : SVGAnimationElement {
};
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_static_string_list.cc b/chromium/third_party/blink/renderer/core/svg/svg_static_string_list.cc
index 9f39bfd8f40..f01b5cedb7f 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_static_string_list.cc
+++ b/chromium/third_party/blink/renderer/core/svg/svg_static_string_list.cc
@@ -53,12 +53,7 @@ void SVGStaticStringList::Trace(Visitor* visitor) {
SVGAnimatedPropertyBase::Trace(visitor);
}
-SVGPropertyBase* SVGStaticStringList::CurrentValueBase() {
- return value_.Get();
-}
-
const SVGPropertyBase& SVGStaticStringList::BaseValueBase() const {
- NOTREACHED();
return *value_;
}
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_static_string_list.h b/chromium/third_party/blink/renderer/core/svg/svg_static_string_list.h
index 55547c440ed..611736480b2 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_static_string_list.h
+++ b/chromium/third_party/blink/renderer/core/svg/svg_static_string_list.h
@@ -62,7 +62,6 @@ class SVGStaticStringList final : public GarbageCollected<SVGStaticStringList>,
~SVGStaticStringList() override;
// SVGAnimatedPropertyBase:
- SVGPropertyBase* CurrentValueBase() override;
const SVGPropertyBase& BaseValueBase() const override;
bool IsAnimating() const override;
SVGPropertyBase* CreateAnimatedValue() override;
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_svg_element.cc b/chromium/third_party/blink/renderer/core/svg/svg_svg_element.cc
index 78b88fee9ab..116c26092a3 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_svg_element.cc
+++ b/chromium/third_party/blink/renderer/core/svg/svg_svg_element.cc
@@ -506,6 +506,7 @@ void SVGSVGElement::AttachLayoutTree(AttachContext& context) {
LayoutObject* SVGSVGElement::CreateLayoutObject(const ComputedStyle&,
LegacyLayout) {
+ UseCounter::Count(GetDocument(), WebFeature::kLegacyLayoutBySVG);
if (IsOutermostSVGSVGElement())
return new LayoutSVGRoot(this);
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_transform_list.cc b/chromium/third_party/blink/renderer/core/svg/svg_transform_list.cc
index 91b88dab777..f621334240a 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_transform_list.cc
+++ b/chromium/third_party/blink/renderer/core/svg/svg_transform_list.cc
@@ -193,10 +193,8 @@ bool SVGTransformList::Concatenate(AffineTransform& result) const {
if (IsEmpty())
return false;
- ConstIterator it = begin();
- ConstIterator it_end = end();
- for (; it != it_end; ++it)
- result *= it->Matrix();
+ for (const auto& item : *this)
+ result *= item->Matrix();
return true;
}
@@ -294,10 +292,8 @@ const CSSValue* SVGTransformList::CssValue() const {
list->Append(*CreateTransformCSSValue(*at(0)));
return list;
}
- ConstIterator it = begin();
- ConstIterator it_end = end();
- for (; it != it_end; ++it)
- list->Append(*CreateTransformCSSValue(**it));
+ for (const auto& item : *this)
+ list->Append(*CreateTransformCSSValue(*item));
return list;
}
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_tree_scope_resources.cc b/chromium/third_party/blink/renderer/core/svg/svg_tree_scope_resources.cc
index 277bb59b4bd..9ad5d0a1c46 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_tree_scope_resources.cc
+++ b/chromium/third_party/blink/renderer/core/svg/svg_tree_scope_resources.cc
@@ -30,8 +30,7 @@ LocalSVGResource* SVGTreeScopeResources::ExistingResourceForId(
return resources_.at(id);
}
-void SVGTreeScopeResources::ProcessCustomWeakness(
- const WeakCallbackInfo& info) {
+void SVGTreeScopeResources::ProcessCustomWeakness(const LivenessBroker& info) {
// Unregister and remove any resources that are no longer alive.
Vector<AtomicString> to_remove;
for (auto& resource_entry : resources_) {
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_tree_scope_resources.h b/chromium/third_party/blink/renderer/core/svg/svg_tree_scope_resources.h
index f0273986798..5d3c32c85cd 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_tree_scope_resources.h
+++ b/chromium/third_party/blink/renderer/core/svg/svg_tree_scope_resources.h
@@ -29,7 +29,7 @@ class SVGTreeScopeResources final
void Trace(Visitor*);
private:
- void ProcessCustomWeakness(const WeakCallbackInfo&);
+ void ProcessCustomWeakness(const LivenessBroker&);
HeapHashMap<AtomicString, WeakMember<LocalSVGResource>> resources_;
Member<TreeScope> tree_scope_;
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_use_element.cc b/chromium/third_party/blink/renderer/core/svg/svg_use_element.cc
index 8cd5633c98c..70ece8b9cf4 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_use_element.cc
+++ b/chromium/third_party/blink/renderer/core/svg/svg_use_element.cc
@@ -33,6 +33,7 @@
#include "third_party/blink/renderer/core/dom/id_target_observer.h"
#include "third_party/blink/renderer/core/dom/shadow_root.h"
#include "third_party/blink/renderer/core/dom/xml_document.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/layout/svg/layout_svg_transformable_container.h"
#include "third_party/blink/renderer/core/svg/svg_g_element.h"
#include "third_party/blink/renderer/core/svg/svg_length_context.h"
@@ -90,11 +91,8 @@ SVGUseElement::SVGUseElement(Document& document)
SVGUseElement::~SVGUseElement() = default;
-void SVGUseElement::Dispose() {
- ClearResource();
-}
-
void SVGUseElement::Trace(Visitor* visitor) {
+ visitor->Trace(cache_entry_);
visitor->Trace(x_);
visitor->Trace(y_);
visitor->Trace(width_);
@@ -102,7 +100,7 @@ void SVGUseElement::Trace(Visitor* visitor) {
visitor->Trace(target_id_observer_);
SVGGraphicsElement::Trace(visitor);
SVGURIReference::Trace(visitor);
- ResourceClient::Trace(visitor);
+ SVGExternalDocumentCache::Client::Trace(visitor);
}
#if DCHECK_IS_ON()
@@ -133,6 +131,11 @@ void SVGUseElement::RemovedFrom(ContainerNode& root_parent) {
}
}
+void SVGUseElement::DidMoveToNewDocument(Document& old_document) {
+ SVGGraphicsElement::DidMoveToNewDocument(old_document);
+ UpdateTargetReference();
+}
+
static void TransferUseWidthAndHeightIfNeeded(
const SVGUseElement& use,
SVGElement& shadow_element,
@@ -190,33 +193,27 @@ void SVGUseElement::UpdateTargetReference() {
const String& url_string = HrefString();
element_url_ = GetDocument().CompleteURL(url_string);
element_url_is_local_ = url_string.StartsWith('#');
- if (!IsStructurallyExternal()) {
- ClearResource();
+ if (!IsStructurallyExternal() || !GetDocument().IsActive()) {
+ cache_entry_ = nullptr;
return;
}
if (!element_url_.HasFragmentIdentifier() ||
- (GetResource() &&
- EqualIgnoringFragmentIdentifier(element_url_, GetResource()->Url())))
+ (cache_entry_ &&
+ EqualIgnoringFragmentIdentifier(element_url_, cache_entry_->Url()))) {
return;
+ }
- ResourceLoaderOptions options;
- options.initiator_info.name = localName();
- FetchParameters params(ResourceRequest(element_url_), options);
- params.MutableResourceRequest().SetMode(
- network::mojom::RequestMode::kSameOrigin);
auto* context_document = &GetDocument();
if (GetDocument().ImportsController()) {
// For @imports from HTML imported Documents, we use the
// context document for getting origin and ResourceFetcher to use the
// main Document's origin, while using the element document for
// CompleteURL() to use imported Documents' base URLs.
- if (!GetDocument().ContextDocument()) {
- ClearResource();
- return;
- }
- context_document = GetDocument().ContextDocument();
+ context_document =
+ To<LocalDOMWindow>(GetDocument().GetExecutionContext())->document();
}
- DocumentResource::FetchSVGDocument(params, *context_document, this);
+ cache_entry_ = SVGExternalDocumentCache::From(*context_document)
+ ->Get(this, element_url_, localName());
}
void SVGUseElement::SvgAttributeChanged(const QualifiedName& attr_name) {
@@ -314,11 +311,9 @@ Element* SVGUseElement::ResolveTargetElement() {
WrapWeakPersistent(this)));
}
}
- if (!ResourceIsValid())
+ if (!cache_entry_ || !cache_entry_->GetDocument())
return nullptr;
- return To<DocumentResource>(GetResource())
- ->GetDocument()
- ->getElementById(element_identifier);
+ return cache_entry_->GetDocument()->getElementById(element_identifier);
}
SVGElement* SVGUseElement::InstanceRoot() const {
@@ -589,15 +584,14 @@ void SVGUseElement::DispatchPendingEvent() {
DispatchEvent(*Event::Create(event_type_names::kLoad));
}
-void SVGUseElement::NotifyFinished(Resource* resource) {
- DCHECK_EQ(GetResource(), resource);
+void SVGUseElement::NotifyFinished(Document* external_document) {
if (!isConnected())
return;
InvalidateShadowTree();
- if (!ResourceIsValid()) {
+ if (!external_document) {
DispatchEvent(*Event::Create(event_type_names::kError));
- } else if (!resource->WasCanceled()) {
+ } else {
if (have_fired_load_event_)
return;
if (!IsStructurallyExternal())
@@ -611,21 +605,4 @@ void SVGUseElement::NotifyFinished(Resource* resource) {
}
}
-bool SVGUseElement::ResourceIsValid() const {
- Resource* resource = GetResource();
- if (!resource || resource->ErrorOccurred())
- return false;
- // If the resource has not yet finished loading but is revalidating, consider
- // it to be valid if it actually carries a document. <use> elements that are
- // in the process of "loading" the revalidated resource (performing the
- // revalidation) will get a NotifyFinished() callback and invalidate as
- // needed. <use> elements that have already finished loading (a potentially
- // older version of the resource) will keep showing that until its shadow
- // tree is invalidated.
- // TODO(fs): Handle revalidations that return a new/different resource.
- if (!resource->IsLoaded() && !resource->IsCacheValidator())
- return false;
- return To<DocumentResource>(resource)->GetDocument();
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_use_element.h b/chromium/third_party/blink/renderer/core/svg/svg_use_element.h
index 6d20db0dd8d..d74a9b3d64f 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_use_element.h
+++ b/chromium/third_party/blink/renderer/core/svg/svg_use_element.h
@@ -24,8 +24,8 @@
#include "base/gtest_prod_util.h"
#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/core/loader/resource/document_resource.h"
#include "third_party/blink/renderer/core/svg/svg_animated_length.h"
+#include "third_party/blink/renderer/core/svg/svg_external_document_cache.h"
#include "third_party/blink/renderer/core/svg/svg_geometry_element.h"
#include "third_party/blink/renderer/core/svg/svg_graphics_element.h"
#include "third_party/blink/renderer/core/svg/svg_uri_reference.h"
@@ -35,10 +35,9 @@ namespace blink {
class SVGUseElement final : public SVGGraphicsElement,
public SVGURIReference,
- public ResourceClient {
+ public SVGExternalDocumentCache::Client {
DEFINE_WRAPPERTYPEINFO();
USING_GARBAGE_COLLECTED_MIXIN(SVGUseElement);
- USING_PRE_FINALIZER(SVGUseElement, Dispose);
public:
explicit SVGUseElement(Document&);
@@ -65,8 +64,6 @@ class SVGUseElement final : public SVGGraphicsElement,
void Trace(Visitor*) override;
private:
- void Dispose();
-
FloatRect GetBBox() override;
void CollectStyleForPresentationAttribute(
@@ -78,6 +75,7 @@ class SVGUseElement final : public SVGGraphicsElement,
InsertionNotificationRequest InsertedInto(ContainerNode&) override;
void RemovedFrom(ContainerNode&) override;
+ void DidMoveToNewDocument(Document&) override;
void SvgAttributeChanged(const QualifiedName&) override;
@@ -106,11 +104,11 @@ class SVGUseElement final : public SVGGraphicsElement,
bool HasCycleUseReferencing(const ContainerNode& target_instance,
const SVGElement& new_target) const;
- bool ResourceIsValid() const;
- void NotifyFinished(Resource*) override;
- String DebugName() const override { return "SVGUseElement"; }
+ void NotifyFinished(Document*) override;
void UpdateTargetReference();
+ Member<SVGExternalDocumentCache::Entry> cache_entry_;
+
Member<SVGAnimatedLength> x_;
Member<SVGAnimatedLength> y_;
Member<SVGAnimatedLength> width_;
diff --git a/chromium/third_party/blink/renderer/core/testing/core_unit_test_helper.cc b/chromium/third_party/blink/renderer/core/testing/core_unit_test_helper.cc
index 6a4181ec261..11517b14394 100644
--- a/chromium/third_party/blink/renderer/core/testing/core_unit_test_helper.cc
+++ b/chromium/third_party/blink/renderer/core/testing/core_unit_test_helper.cc
@@ -26,7 +26,8 @@ LocalFrame* SingleChildLocalFrameClient::CreateFrame(
MakeGarbageCollected<LocalFrameClientWithParent>(parent_frame);
child_ = MakeGarbageCollected<LocalFrame>(
child_client, *parent_frame->GetPage(), owner_element,
- &parent_frame->window_agent_factory(), nullptr);
+ base::UnguessableToken::Create(), &parent_frame->window_agent_factory(),
+ nullptr);
child_->CreateView(IntSize(500, 500), Color::kTransparent);
child_->Init();
@@ -49,9 +50,9 @@ void RenderingTestChromeClient::InjectGestureScrollEvent(
// would be added to the event queue and handled asynchronously but immediate
// handling is sufficient to test scrollbar dragging.
std::unique_ptr<WebGestureEvent> gesture_event =
- ui::GenerateInjectedScrollGesture(injected_type, base::TimeTicks::Now(),
- device, gfx::PointF(0, 0), delta,
- granularity);
+ WebGestureEvent::GenerateInjectedScrollGesture(
+ injected_type, base::TimeTicks::Now(), device, gfx::PointF(0, 0),
+ delta, granularity);
if (injected_type == WebInputEvent::Type::kGestureScrollBegin) {
gesture_event->data.scroll_begin.scrollable_area_element_id =
scrollable_area_element_id.GetStableId();
diff --git a/chromium/third_party/blink/renderer/core/testing/data/display_mode_listener.html b/chromium/third_party/blink/renderer/core/testing/data/display_mode_listener.html
new file mode 100644
index 00000000000..1c744ed5015
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/testing/data/display_mode_listener.html
@@ -0,0 +1,20 @@
+<!doctype html>
+<html>
+ <style>
+ #minimal { display: none; }
+</style>
+<body>
+
+<div id="minimal">minimal-ui</div>
+
+<div id="regular">regular-ui</div>
+
+<script>
+ function mediaquery() {
+ document.getElementById('minimal').style.display = "block";
+ document.getElementById('regular').style.display = "none";
+ }
+ window.matchMedia('(display-mode: minimal-ui)').addListener(mediaquery);
+</script>
+</body>
+</html>
diff --git a/chromium/third_party/blink/renderer/core/testing/data/fixed_layout.html b/chromium/third_party/blink/renderer/core/testing/data/fixed_layout.html
index 5e632b3ae48..6375e7c7157 100644
--- a/chromium/third_party/blink/renderer/core/testing/data/fixed_layout.html
+++ b/chromium/third_party/blink/renderer/core/testing/data/fixed_layout.html
@@ -1,10 +1,8 @@
<head>
+ <!-- Since tests are built with desktop viewport settings set the viewport
+ to behave like Android -->
+ <meta name="viewport" content="width=980">
<style>
- /* Since tests are built with desktop viewport settings set the viewport
- to behave like Android */
- @viewport {
- min-width: 980px;
- }
/* Use a font size large enough so autosizing kicks in. */
body {
font-size: 20px;
diff --git a/chromium/third_party/blink/renderer/core/testing/data/iframe-display_mode.html b/chromium/third_party/blink/renderer/core/testing/data/iframe-display_mode.html
new file mode 100644
index 00000000000..5f1b4bee45b
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/testing/data/iframe-display_mode.html
@@ -0,0 +1,6 @@
+<!doctype html>
+<html>
+ <body>
+ <iframe src="display_mode.html"></iframe>
+</body>
+</html>
diff --git a/chromium/third_party/blink/renderer/core/testing/data/iframe-display_mode_listener.html b/chromium/third_party/blink/renderer/core/testing/data/iframe-display_mode_listener.html
new file mode 100644
index 00000000000..735f30fd61f
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/testing/data/iframe-display_mode_listener.html
@@ -0,0 +1,6 @@
+<!doctype html>
+<html>
+ <body>
+ <iframe src="display_mode_listener.html"></iframe>
+</body>
+</html>
diff --git a/chromium/third_party/blink/renderer/core/testing/data/max-frames-detach.html b/chromium/third_party/blink/renderer/core/testing/data/max-frames-detach.html
deleted file mode 100644
index 908bab8c92b..00000000000
--- a/chromium/third_party/blink/renderer/core/testing/data/max-frames-detach.html
+++ /dev/null
@@ -1,7 +0,0 @@
-<body>
-<script>
-for(var x = 0; x < 1024; x++)
- document.body.appendChild(document.createElement("iframe"));
-document.body.innerText = "We pass if we don't crash";
-</script>
-</body>
diff --git a/chromium/third_party/blink/renderer/core/testing/data/mhtml/shadow.mht b/chromium/third_party/blink/renderer/core/testing/data/mhtml/shadow.mht
index 8669bcd787b..662c1609f44 100644
--- a/chromium/third_party/blink/renderer/core/testing/data/mhtml/shadow.mht
+++ b/chromium/third_party/blink/renderer/core/testing/data/mhtml/shadow.mht
@@ -18,9 +18,6 @@ Content-Location: http://localhost/shadow.html
<title>A page with shadow DOM content</title>
<h1>This page has shadow DOM content</h1>
-<p id=3D"h1">
- <template shadowmode=3D"v0">V0</template>
-</p>
<div id=3D"h2">
<template shadowmode=3D"open" shadowdelegatesfocus=3D"">Parent
<p id=3D"h3">
diff --git a/chromium/third_party/blink/renderer/core/testing/data/popup/select.html b/chromium/third_party/blink/renderer/core/testing/data/popup/select.html
index 22e2278d839..87ce01bb153 100644
--- a/chromium/third_party/blink/renderer/core/testing/data/popup/select.html
+++ b/chromium/third_party/blink/renderer/core/testing/data/popup/select.html
@@ -1,6 +1,8 @@
<!DOCTYPE html>
<select id="select">
<option>0</option>
-<option>1</option>
+<option selected="1">1</option>
<option>2</option>
</select>
+<select id="emptySelect">
+</select> \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/core/testing/data/popup/select_event_remove_frame_on_change.html b/chromium/third_party/blink/renderer/core/testing/data/popup/select_event_remove_frame_on_change.html
new file mode 100644
index 00000000000..4bc2e2bddfd
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/testing/data/popup/select_event_remove_frame_on_change.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+<body>
+<iframe srcdoc="<select><option>1</option><option>2></option></select>"></iframe>
+<script>
+const frame = document.querySelector('iframe');
+onload = function() {
+ frame.contentDocument.querySelector('select').onchange = () => { frame.remove(); };
+};
+</script>
+</body>
+</html> \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/core/testing/data/touch-action-tests.js b/chromium/third_party/blink/renderer/core/testing/data/touch-action-tests.js
index 73bf06e928d..a3ed94c7dc9 100644
--- a/chromium/third_party/blink/renderer/core/testing/data/touch-action-tests.js
+++ b/chromium/third_party/blink/renderer/core/testing/data/touch-action-tests.js
@@ -4,10 +4,6 @@ document.addEventListener('touchstart', function() {});
window.addEventListener('load', function() {
// Create any shadow DOM nodes requested by the test.
var shadowTrees = document.querySelectorAll('[make-shadow-dom]');
- if (shadowTrees.length > 0 && !HTMLElement.prototype.createShadowRoot) {
- document.body.innerHTML = 'ERROR: Shadow DOM not supported!';
- return;
- }
for (var i = 0; i < shadowTrees.length; i++) {
var tree = shadowTrees[i];
var host = tree.previousElementSibling;
@@ -16,7 +12,7 @@ window.addEventListener('load', function() {
return;
}
tree.parentElement.removeChild(tree);
- var shadowRoot = host.createShadowRoot();
+ var shadowRoot = host.attachShadow({mode: 'open'});
var style = document.createElement('style');
style.innerText = ' .ta-none { -ms-touch-action: none; touch-action: none; }';
shadowRoot.appendChild(style);
diff --git a/chromium/third_party/blink/renderer/core/testing/data/two_scrollable_area.html b/chromium/third_party/blink/renderer/core/testing/data/two_scrollable_area.html
index 81e1e37b489..26ceb4f5ddd 100644
--- a/chromium/third_party/blink/renderer/core/testing/data/two_scrollable_area.html
+++ b/chromium/third_party/blink/renderer/core/testing/data/two_scrollable_area.html
@@ -1,6 +1,14 @@
<!DOCTYPE html>
<style>
+.scroller {
+ /* Opaque background by default. */
+ background: blue;
+ /* Stacking context by default. */
+ position: relative;
+ z-index: 1;
+}
+
.transparent {
opacity: 0.5;
}
@@ -13,6 +21,10 @@
background: rgba(255, 0, 0, 0.5);
}
+.cant-paint-scrolling-background {
+ background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUg), white local
+}
+
.border-radius {
border: 2px solid;
border-radius: 20px;
@@ -23,13 +35,16 @@
clip: rect(0px,120px,120px,0px);
}
-.clip-path{
+.clip-path {
clip-path: circle(115px at 20px 20px);
}
.box-shadow {
box-shadow: 10px 10px 5px #888888;
- will-change:transform; /*This reason is not recorded for root layer*/
+}
+
+.inset-box-shadow {
+ box-shadow: 10px 10px 5px #888888 inset;
}
.composited {
@@ -40,6 +55,10 @@
height: 500px;
}
+.non-stacking-context {
+ z-index: auto;
+}
+
div {
overflow: scroll;
width: 200px;
@@ -52,9 +71,9 @@ body {
}
</style>
-<div id="scroller1">
+<div class="scroller" id="scroller1">
<div class="content" id="content1"></div>
</div>
-<div id="scroller2">
+<div class="scroller" id="scroller2">
<div class="content"></div>
</div>
diff --git a/chromium/third_party/blink/renderer/core/testing/data/viewport-and-media.html b/chromium/third_party/blink/renderer/core/testing/data/viewport-and-media.html
deleted file mode 100644
index 7cad8dd3491..00000000000
--- a/chromium/third_party/blink/renderer/core/testing/data/viewport-and-media.html
+++ /dev/null
@@ -1,16 +0,0 @@
-<!DOCTYPE html>
-<style>
- @viewport {
- width: 2000px;
- }
- @media (min-width: 2000px) {
- body {
- color: green;
- }
- }
-</style>
-<div></div>
-<div></div>
-<div></div>
-<div></div>
-<div></div>
diff --git a/chromium/third_party/blink/renderer/core/testing/data/viewport-inside-media.html b/chromium/third_party/blink/renderer/core/testing/data/viewport-inside-media.html
deleted file mode 100644
index c86ed03b9f3..00000000000
--- a/chromium/third_party/blink/renderer/core/testing/data/viewport-inside-media.html
+++ /dev/null
@@ -1,8 +0,0 @@
-<!DOCTYPE html>
-<style>
- @media (max-width: 1000px) {
- @viewport {
- width: 2000px;
- }
- }
-</style>
diff --git a/chromium/third_party/blink/renderer/core/testing/data/viewport-lengths.html b/chromium/third_party/blink/renderer/core/testing/data/viewport-lengths.html
deleted file mode 100644
index 46ec5166a17..00000000000
--- a/chromium/third_party/blink/renderer/core/testing/data/viewport-lengths.html
+++ /dev/null
@@ -1,7 +0,0 @@
-<!DOCTYPE html>
-<style>
- @viewport {
- width: 50vw;
- height: 50vh;
- }
-</style>
diff --git a/chromium/third_party/blink/renderer/core/testing/data/viewport/viewport-legacy-ordering-10.html b/chromium/third_party/blink/renderer/core/testing/data/viewport/viewport-legacy-ordering-10.html
deleted file mode 100644
index c24fea4f9d2..00000000000
--- a/chromium/third_party/blink/renderer/core/testing/data/viewport/viewport-legacy-ordering-10.html
+++ /dev/null
@@ -1,10 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
- <title>Empty @viewport not overriding Viewport Meta tag</title>
- <meta name="viewport" content="width=5000">
- <style>@viewport {}</style>
-</head>
-<body>
-</body>
-</html>
diff --git a/chromium/third_party/blink/renderer/core/testing/dictionary_test.cc b/chromium/third_party/blink/renderer/core/testing/dictionary_test.cc
index b8abbf50eef..29e6eda3d8b 100644
--- a/chromium/third_party/blink/renderer/core/testing/dictionary_test.cc
+++ b/chromium/third_party/blink/renderer/core/testing/dictionary_test.cc
@@ -46,10 +46,13 @@ void DictionaryTest::set(const InternalDictionary* testing_dictionary) {
unrestricted_double_member_ =
testing_dictionary->unrestrictedDoubleMember();
}
- string_member_ = testing_dictionary->stringMember();
+ if (testing_dictionary->hasStringMember())
+ string_member_ = testing_dictionary->stringMember();
string_member_with_default_ = testing_dictionary->stringMemberWithDefault();
- byte_string_member_ = testing_dictionary->byteStringMember();
- usv_string_member_ = testing_dictionary->usvStringMember();
+ if (testing_dictionary->hasByteStringMember())
+ byte_string_member_ = testing_dictionary->byteStringMember();
+ if (testing_dictionary->hasUsvStringMember())
+ usv_string_member_ = testing_dictionary->usvStringMember();
if (testing_dictionary->hasStringSequenceMember())
string_sequence_member_ = testing_dictionary->stringSequenceMember();
string_sequence_member_with_default_ =
@@ -58,14 +61,17 @@ void DictionaryTest::set(const InternalDictionary* testing_dictionary) {
string_sequence_or_null_member_ =
testing_dictionary->stringSequenceOrNullMember();
}
- enum_member_ = testing_dictionary->enumMember();
+ if (testing_dictionary->hasEnumMember())
+ enum_member_ = testing_dictionary->enumMember();
enum_member_with_default_ = testing_dictionary->enumMemberWithDefault();
- enum_or_null_member_ = testing_dictionary->enumOrNullMember();
+ if (testing_dictionary->hasEnumOrNullMember())
+ enum_or_null_member_ = testing_dictionary->enumOrNullMember();
if (testing_dictionary->hasElementMember())
element_member_ = testing_dictionary->elementMember();
if (testing_dictionary->hasElementOrNullMember())
element_or_null_member_ = testing_dictionary->elementOrNullMember();
- object_member_ = testing_dictionary->objectMember();
+ if (testing_dictionary->hasObjectMember())
+ object_member_ = testing_dictionary->objectMember();
object_or_null_member_with_default_ =
testing_dictionary->objectOrNullMemberWithDefault();
if (testing_dictionary->hasDoubleOrStringMember())
@@ -74,17 +80,20 @@ void DictionaryTest::set(const InternalDictionary* testing_dictionary) {
double_or_string_sequence_member_ =
testing_dictionary->doubleOrStringSequenceMember();
}
+ // eventTargetOrNullMember has a default null value.
event_target_or_null_member_ = testing_dictionary->eventTargetOrNullMember();
if (testing_dictionary->hasInternalEnumOrInternalEnumSequenceMember()) {
internal_enum_or_internal_enum_sequence_ =
testing_dictionary->internalEnumOrInternalEnumSequenceMember();
}
- any_member_ = testing_dictionary->anyMember();
- callback_function_member_ = testing_dictionary->callbackFunctionMember();
+ if (testing_dictionary->hasAnyMember())
+ any_member_ = testing_dictionary->anyMember();
+ if (testing_dictionary->hasCallbackFunctionMember())
+ callback_function_member_ = testing_dictionary->callbackFunctionMember();
}
-InternalDictionary* DictionaryTest::get() {
- InternalDictionary* result = InternalDictionary::Create();
+InternalDictionary* DictionaryTest::get(v8::Isolate* isolate) {
+ InternalDictionary* result = InternalDictionary::Create(isolate);
GetInternals(result);
return result;
}
@@ -99,8 +108,9 @@ void DictionaryTest::setDerived(const InternalDictionaryDerived* derived) {
required_boolean_member_ = derived->requiredBooleanMember();
}
-InternalDictionaryDerived* DictionaryTest::getDerived() {
- InternalDictionaryDerived* result = InternalDictionaryDerived::Create();
+InternalDictionaryDerived* DictionaryTest::getDerived(v8::Isolate* isolate) {
+ InternalDictionaryDerived* result =
+ InternalDictionaryDerived::Create(isolate);
GetDerivedInternals(result);
return result;
}
@@ -112,9 +122,10 @@ void DictionaryTest::setDerivedDerived(
derived_derived_string_member_ = derived->derivedDerivedStringMember();
}
-InternalDictionaryDerivedDerived* DictionaryTest::getDerivedDerived() {
+InternalDictionaryDerivedDerived* DictionaryTest::getDerivedDerived(
+ v8::Isolate* isolate) {
InternalDictionaryDerivedDerived* result =
- InternalDictionaryDerivedDerived::Create();
+ InternalDictionaryDerivedDerived::Create(isolate);
GetDerivedDerivedInternals(result);
return result;
}
@@ -129,8 +140,10 @@ void DictionaryTest::Reset() {
boolean_member_ = base::nullopt;
double_member_ = base::nullopt;
unrestricted_double_member_ = base::nullopt;
- string_member_ = String();
+ string_member_ = base::nullopt;
string_member_with_default_ = String("Should not be returned");
+ byte_string_member_ = base::nullopt;
+ usv_string_member_ = base::nullopt;
string_sequence_member_ = base::nullopt;
string_sequence_member_with_default_.Fill("Should not be returned", 1);
string_sequence_or_null_member_ = base::nullopt;
@@ -143,8 +156,9 @@ void DictionaryTest::Reset() {
object_or_null_member_with_default_ = ScriptValue();
double_or_string_member_ = DoubleOrString();
event_target_or_null_member_ = nullptr;
- derived_string_member_ = String();
+ derived_string_member_ = base::nullopt;
derived_string_member_with_default_ = String();
+ derived_derived_string_member_ = base::nullopt;
required_boolean_member_ = false;
dictionary_member_properties_ = base::nullopt;
internal_enum_or_internal_enum_sequence_ =
@@ -177,10 +191,13 @@ void DictionaryTest::GetInternals(InternalDictionary* dict) {
dict->setDoubleMember(double_member_.value());
if (unrestricted_double_member_)
dict->setUnrestrictedDoubleMember(unrestricted_double_member_.value());
- dict->setStringMember(string_member_);
+ if (string_member_)
+ dict->setStringMember(string_member_.value());
dict->setStringMemberWithDefault(string_member_with_default_);
- dict->setByteStringMember(byte_string_member_);
- dict->setUsvStringMember(usv_string_member_);
+ if (byte_string_member_)
+ dict->setByteStringMember(byte_string_member_.value());
+ if (usv_string_member_)
+ dict->setUsvStringMember(usv_string_member_.value());
if (string_sequence_member_)
dict->setStringSequenceMember(string_sequence_member_.value());
dict->setStringSequenceMemberWithDefault(
@@ -208,13 +225,15 @@ void DictionaryTest::GetInternals(InternalDictionary* dict) {
dict->setInternalEnumOrInternalEnumSequenceMember(
internal_enum_or_internal_enum_sequence_);
dict->setAnyMember(any_member_);
- dict->setCallbackFunctionMember(callback_function_member_);
+ if (callback_function_member_)
+ dict->setCallbackFunctionMember(callback_function_member_);
}
void DictionaryTest::GetDerivedInternals(InternalDictionaryDerived* dict) {
GetInternals(dict);
- dict->setDerivedStringMember(derived_string_member_);
+ if (derived_string_member_)
+ dict->setDerivedStringMember(derived_string_member_.value());
dict->setDerivedStringMemberWithDefault(derived_string_member_with_default_);
dict->setRequiredBooleanMember(required_boolean_member_);
}
@@ -223,7 +242,8 @@ void DictionaryTest::GetDerivedDerivedInternals(
InternalDictionaryDerivedDerived* dict) {
GetDerivedInternals(dict);
- dict->setDerivedDerivedStringMember(derived_derived_string_member_);
+ if (derived_derived_string_member_)
+ dict->setDerivedDerivedStringMember(derived_derived_string_member_.value());
}
void DictionaryTest::Trace(Visitor* visitor) {
diff --git a/chromium/third_party/blink/renderer/core/testing/dictionary_test.h b/chromium/third_party/blink/renderer/core/testing/dictionary_test.h
index af0516d5b24..8ed3ed80533 100644
--- a/chromium/third_party/blink/renderer/core/testing/dictionary_test.h
+++ b/chromium/third_party/blink/renderer/core/testing/dictionary_test.h
@@ -15,6 +15,7 @@
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/wtf/hash_map.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+#include "v8/include/v8.h"
namespace blink {
@@ -32,13 +33,13 @@ class DictionaryTest : public ScriptWrappable {
// Stores all members into corresponding fields
void set(const InternalDictionary*);
// Sets each member of the given TestDictionary from fields
- InternalDictionary* get();
+ InternalDictionary* get(v8::Isolate* isolate);
void setDerived(const InternalDictionaryDerived*);
- InternalDictionaryDerived* getDerived();
+ InternalDictionaryDerived* getDerived(v8::Isolate* isolate);
void setDerivedDerived(const InternalDictionaryDerivedDerived*);
- InternalDictionaryDerivedDerived* getDerivedDerived();
+ InternalDictionaryDerivedDerived* getDerivedDerived(v8::Isolate* isolate);
void Trace(Visitor*) override;
@@ -63,10 +64,10 @@ class DictionaryTest : public ScriptWrappable {
base::Optional<bool> boolean_member_;
base::Optional<double> double_member_;
base::Optional<double> unrestricted_double_member_;
- String string_member_;
+ base::Optional<String> string_member_;
String string_member_with_default_;
- String byte_string_member_;
- String usv_string_member_;
+ base::Optional<String> byte_string_member_;
+ base::Optional<String> usv_string_member_;
base::Optional<Vector<String>> string_sequence_member_;
Vector<String> string_sequence_member_with_default_;
base::Optional<Vector<String>> string_sequence_or_null_member_;
@@ -80,9 +81,9 @@ class DictionaryTest : public ScriptWrappable {
DoubleOrString double_or_string_member_;
base::Optional<HeapVector<DoubleOrString>> double_or_string_sequence_member_;
Member<EventTarget> event_target_or_null_member_;
- String derived_string_member_;
+ base::Optional<String> derived_string_member_;
String derived_string_member_with_default_;
- String derived_derived_string_member_;
+ base::Optional<String> derived_derived_string_member_;
bool required_boolean_member_;
base::Optional<HashMap<String, String>> dictionary_member_properties_;
InternalEnumOrInternalEnumSequence internal_enum_or_internal_enum_sequence_;
diff --git a/chromium/third_party/blink/renderer/core/testing/dictionary_test.idl b/chromium/third_party/blink/renderer/core/testing/dictionary_test.idl
index e759f144450..24efc582987 100644
--- a/chromium/third_party/blink/renderer/core/testing/dictionary_test.idl
+++ b/chromium/third_party/blink/renderer/core/testing/dictionary_test.idl
@@ -4,11 +4,11 @@
interface DictionaryTest {
void set(optional InternalDictionary testingDictionary = {});
- InternalDictionary get();
+ [CallWith=Isolate] InternalDictionary get();
void setDerived(InternalDictionaryDerived derived);
- InternalDictionaryDerived getDerived();
+ [CallWith=Isolate] InternalDictionaryDerived getDerived();
void setDerivedDerived(InternalDictionaryDerivedDerived derived);
- InternalDictionaryDerivedDerived getDerivedDerived();
+ [CallWith=Isolate] InternalDictionaryDerivedDerived getDerivedDerived();
};
diff --git a/chromium/third_party/blink/renderer/core/testing/dummy_modulator.cc b/chromium/third_party/blink/renderer/core/testing/dummy_modulator.cc
index b0556a8ac93..23f14bb37a8 100644
--- a/chromium/third_party/blink/renderer/core/testing/dummy_modulator.cc
+++ b/chromium/third_party/blink/renderer/core/testing/dummy_modulator.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/core/testing/dummy_modulator.h"
+#include "third_party/blink/renderer/bindings/core/v8/module_record.h"
#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
#include "third_party/blink/renderer/core/script/module_record_resolver.h"
@@ -168,9 +169,10 @@ Vector<Modulator::ModuleRequest> DummyModulator::ModuleRequestsFromModuleRecord(
return Vector<ModuleRequest>();
}
-ScriptValue DummyModulator::ExecuteModule(ModuleScript*, CaptureEvalErrorFlag) {
+ModuleEvaluationResult DummyModulator::ExecuteModule(ModuleScript*,
+ CaptureEvalErrorFlag) {
NOTREACHED();
- return ScriptValue();
+ return ModuleEvaluationResult::Empty();
}
ModuleScriptFetcher* DummyModulator::CreateModuleScriptFetcher(
diff --git a/chromium/third_party/blink/renderer/core/testing/dummy_modulator.h b/chromium/third_party/blink/renderer/core/testing/dummy_modulator.h
index 3b4646c107f..7b1d2f60bb3 100644
--- a/chromium/third_party/blink/renderer/core/testing/dummy_modulator.h
+++ b/chromium/third_party/blink/renderer/core/testing/dummy_modulator.h
@@ -74,7 +74,8 @@ class DummyModulator : public Modulator {
ScriptValue InstantiateModule(v8::Local<v8::Module>, const KURL&) override;
Vector<ModuleRequest> ModuleRequestsFromModuleRecord(
v8::Local<v8::Module>) override;
- ScriptValue ExecuteModule(ModuleScript*, CaptureEvalErrorFlag) override;
+ ModuleEvaluationResult ExecuteModule(ModuleScript*,
+ CaptureEvalErrorFlag) override;
ModuleScriptFetcher* CreateModuleScriptFetcher(
ModuleScriptCustomFetchType,
util::PassKey<ModuleScriptLoader>) override;
diff --git a/chromium/third_party/blink/renderer/core/testing/dummy_page_holder.cc b/chromium/third_party/blink/renderer/core/testing/dummy_page_holder.cc
index e9a7b07b0ba..b019f5b4916 100644
--- a/chromium/third_party/blink/renderer/core/testing/dummy_page_holder.cc
+++ b/chromium/third_party/blink/renderer/core/testing/dummy_page_holder.cc
@@ -81,11 +81,11 @@ DummyPageHolder::DummyPageHolder(
local_frame_client_ = MakeGarbageCollected<DummyLocalFrameClient>();
// Create new WindowAgentFactory as this page will be isolated from others.
- frame_ =
- MakeGarbageCollected<LocalFrame>(local_frame_client_.Get(), *page_,
- /* FrameOwner* */ nullptr,
- /* WindowAgentFactory* */ nullptr,
- /* InterfaceRegistry* */ nullptr, clock);
+ frame_ = MakeGarbageCollected<LocalFrame>(
+ local_frame_client_.Get(), *page_,
+ /* FrameOwner* */ nullptr, base::UnguessableToken::Create(),
+ /* WindowAgentFactory* */ nullptr,
+ /* InterfaceRegistry* */ nullptr, clock);
frame_->SetView(
MakeGarbageCollected<LocalFrameView>(*frame_, initial_view_size));
frame_->View()->GetPage()->GetVisualViewport().SetSize(initial_view_size);
diff --git a/chromium/third_party/blink/renderer/core/testing/fake_local_frame_host.cc b/chromium/third_party/blink/renderer/core/testing/fake_local_frame_host.cc
index 45b6becfab6..be8b023aa5e 100644
--- a/chromium/third_party/blink/renderer/core/testing/fake_local_frame_host.cc
+++ b/chromium/third_party/blink/renderer/core/testing/fake_local_frame_host.cc
@@ -163,6 +163,26 @@ void FakeLocalFrameHost::FocusedElementChanged(
bool is_editable_element,
const gfx::Rect& bounds_in_frame_widget) {}
+void FakeLocalFrameHost::ShowPopupMenu(
+ mojo::PendingRemote<mojom::blink::PopupMenuClient> popup_client,
+ const gfx::Rect& bounds,
+ int32_t item_height,
+ double font_size,
+ int32_t selected_item,
+ Vector<mojom::blink::MenuItemPtr> menu_items,
+ bool right_aligned,
+ bool allow_multiple_selection) {}
+
+void FakeLocalFrameHost::DidLoadResourceFromMemoryCache(
+ const KURL& url,
+ const WTF::String& http_method,
+ const WTF::String& mime_type,
+ network::mojom::blink::RequestDestination request_destination) {}
+
+void FakeLocalFrameHost::DidChangeFrameOwnerProperties(
+ const base::UnguessableToken& child_frame_token,
+ mojom::blink::FrameOwnerPropertiesPtr frame_owner_properties) {}
+
void FakeLocalFrameHost::BindFrameHostReceiver(
mojo::ScopedInterfaceEndpointHandle handle) {
receiver_.Bind(mojo::PendingAssociatedReceiver<mojom::blink::LocalFrameHost>(
diff --git a/chromium/third_party/blink/renderer/core/testing/fake_local_frame_host.h b/chromium/third_party/blink/renderer/core/testing/fake_local_frame_host.h
index 350d80505f2..ea9e15846b4 100644
--- a/chromium/third_party/blink/renderer/core/testing/fake_local_frame_host.h
+++ b/chromium/third_party/blink/renderer/core/testing/fake_local_frame_host.h
@@ -98,6 +98,23 @@ class FakeLocalFrameHost : public mojom::blink::LocalFrameHost {
void DownloadURL(mojom::blink::DownloadURLParamsPtr params) override;
void FocusedElementChanged(bool is_editable_element,
const gfx::Rect& bounds_in_frame_widget) override;
+ void ShowPopupMenu(
+ mojo::PendingRemote<mojom::blink::PopupMenuClient> popup_client,
+ const gfx::Rect& bounds,
+ int32_t item_height,
+ double font_size,
+ int32_t selected_item,
+ Vector<mojom::blink::MenuItemPtr> menu_items,
+ bool right_aligned,
+ bool allow_multiple_selection) override;
+ void DidLoadResourceFromMemoryCache(
+ const KURL& url,
+ const WTF::String& http_method,
+ const WTF::String& mime_type,
+ network::mojom::blink::RequestDestination request_destination) override;
+ void DidChangeFrameOwnerProperties(
+ const base::UnguessableToken& child_frame_token,
+ mojom::blink::FrameOwnerPropertiesPtr frame_owner_properties) override;
private:
void BindFrameHostReceiver(mojo::ScopedInterfaceEndpointHandle handle);
diff --git a/chromium/third_party/blink/renderer/core/testing/internals.cc b/chromium/third_party/blink/renderer/core/testing/internals.cc
index 01b71d85969..24f1f352a2d 100644
--- a/chromium/third_party/blink/renderer/core/testing/internals.cc
+++ b/chromium/third_party/blink/renderer/core/testing/internals.cc
@@ -112,7 +112,6 @@
#include "third_party/blink/renderer/core/html_names.h"
#include "third_party/blink/renderer/core/input/event_handler.h"
#include "third_party/blink/renderer/core/input/keyboard_event_manager.h"
-#include "third_party/blink/renderer/core/inspector/inspector_issue.h"
#include "third_party/blink/renderer/core/inspector/main_thread_debugger.h"
#include "third_party/blink/renderer/core/intersection_observer/intersection_observer.h"
#include "third_party/blink/renderer/core/layout/layout_object.h"
@@ -189,7 +188,7 @@
#include "third_party/blink/renderer/platform/wtf/text/string_buffer.h"
#include "third_party/blink/renderer/platform/wtf/text/text_encoding_registry.h"
#include "ui/base/cursor/cursor.h"
-#include "ui/base/mojom/cursor_type.mojom-blink.h"
+#include "ui/base/cursor/mojom/cursor_type.mojom-blink.h"
#include "ui/base/ui_base_features.h"
#include "v8/include/v8.h"
@@ -200,6 +199,8 @@ using ui::mojom::ImeTextSpanUnderlineStyle;
namespace {
+std::unique_ptr<ScopedMockOverlayScrollbars> g_mock_overlay_scrollbars;
+
class UseCounterHelperObserverImpl final : public UseCounterHelper::Observer {
public:
UseCounterHelperObserverImpl(ScriptPromiseResolver* resolver,
@@ -270,15 +271,9 @@ static ScrollableArea* ScrollableAreaForNode(Node* node) {
return ToLayoutBox(layout_object)->GetScrollableArea();
}
-static RuntimeEnabledFeatures::Backup* g_s_features_backup = nullptr;
-static std::unique_ptr<ScopedMockOverlayScrollbars> g_s_mock_overlay_scrollbars;
-
void Internals::ResetToConsistentState(Page* page) {
DCHECK(page);
- if (!g_s_features_backup)
- g_s_features_backup = new RuntimeEnabledFeatures::Backup;
- g_s_features_backup->Restore();
page->SetIsCursorVisible(true);
// Ensure the PageScaleFactor always stays within limits, if the test changed
// the limits. BlinkTestRunner will reset the limits to those set by
@@ -312,7 +307,7 @@ void Internals::ResetToConsistentState(Page* page) {
OverrideCapsLockState::kDefault);
IntersectionObserver::SetThrottleDelayEnabledForTesting(true);
- g_s_mock_overlay_scrollbars.reset();
+ g_mock_overlay_scrollbars.reset();
}
Internals::Internals(ExecutionContext* context)
@@ -1807,7 +1802,9 @@ unsigned Internals::touchEndOrCancelEventHandlerCount(
unsigned Internals::pointerEventHandlerCount(Document* document) const {
DCHECK(document);
- return EventHandlerCount(*document, EventHandlerRegistry::kPointerEvent);
+ return EventHandlerCount(*document, EventHandlerRegistry::kPointerEvent) +
+ EventHandlerCount(*document,
+ EventHandlerRegistry::kPointerRawUpdateEvent);
}
// Given a vector of rects, merge those that are adjacent, leaving empty rects
@@ -1970,9 +1967,8 @@ void Internals::triggerTestInspectorIssue(Document* document) {
DCHECK(document);
auto info = mojom::blink::InspectorIssueInfo::New(
mojom::InspectorIssueCode::kSameSiteCookieIssue,
- mojom::blink::InspectorIssueDetails::New(),
- mojom::blink::AffectedResources::New());
- document->AddInspectorIssue(InspectorIssue::Create(std::move(info)));
+ mojom::blink::InspectorIssueDetails::New());
+ document->GetFrame()->AddInspectorIssue(std::move(info));
}
AtomicString Internals::htmlNamespace() {
@@ -2166,6 +2162,7 @@ String Internals::layerTreeAsText(Document* document,
bool Internals::scrollsWithRespectTo(Element* element1,
Element* element2,
ExceptionState& exception_state) {
+ DCHECK(!RuntimeEnabledFeatures::CompositeAfterPaintEnabled());
DCHECK(element1 && element2);
element1->GetDocument().View()->UpdateAllLifecyclePhases(
DocumentUpdateReason::kTest);
@@ -3010,6 +3007,8 @@ bool Internals::loseSharedGraphicsContext3D() {
if (!shared_provider)
return false;
gpu::gles2::GLES2Interface* shared_gl = shared_provider->ContextGL();
+ if (!shared_gl)
+ return false;
shared_gl->LoseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_EXT,
GL_INNOCENT_CONTEXT_RESET_EXT);
// To prevent tests that call loseSharedGraphicsContext3D from being
@@ -3206,10 +3205,6 @@ void Internals::setScrollChain(ScrollState* scroll_state,
scroll_state->SetScrollChain(scroll_chain);
}
-void Internals::scheduleBlinkGC() {
- ThreadState::Current()->ScheduleForcedGCForTesting();
-}
-
String Internals::selectedHTMLForClipboard() {
if (!GetFrame())
return String();
@@ -3528,7 +3523,8 @@ String Internals::getAgentId(DOMWindow* window) {
}
void Internals::useMockOverlayScrollbars() {
- g_s_mock_overlay_scrollbars.reset(new ScopedMockOverlayScrollbars(true));
+ g_mock_overlay_scrollbars =
+ std::make_unique<ScopedMockOverlayScrollbars>(true);
}
bool Internals::overlayScrollbarsEnabled() const {
diff --git a/chromium/third_party/blink/renderer/core/testing/internals.h b/chromium/third_party/blink/renderer/core/testing/internals.h
index 75155f08ab6..0d9705d4e60 100644
--- a/chromium/third_party/blink/renderer/core/testing/internals.h
+++ b/chromium/third_party/blink/renderer/core/testing/internals.h
@@ -500,12 +500,6 @@ class Internals final : public ScriptWrappable {
const HeapVector<Member<Element>>& elements,
ExceptionState&);
- // Schedule a forced Blink GC run (Oilpan) at the end of event loop.
- // Note: This is designed to be only used from PerformanceTests/BlinkGC to
- // explicitly measure only Blink GC time. Normal web tests should use
- // gc() instead as it would trigger both Blink GC and V8 GC.
- void scheduleBlinkGC();
-
String selectedHTMLForClipboard();
String selectedTextForClipboard();
diff --git a/chromium/third_party/blink/renderer/core/testing/internals.idl b/chromium/third_party/blink/renderer/core/testing/internals.idl
index 1862cf93cb4..1de7a786821 100644
--- a/chromium/third_party/blink/renderer/core/testing/internals.idl
+++ b/chromium/third_party/blink/renderer/core/testing/internals.idl
@@ -326,7 +326,6 @@
UnionTypesTest unionTypesTest();
CallbackFunctionTest callbackFunctionTest();
[RaisesException] void setScrollChain(ScrollState scrollState, sequence<Element> elements);
- void scheduleBlinkGC();
DOMString selectedHTMLForClipboard();
DOMString selectedTextForClipboard();
diff --git a/chromium/third_party/blink/renderer/core/testing/mock_clipboard_host.cc b/chromium/third_party/blink/renderer/core/testing/mock_clipboard_host.cc
index 4235e6f74d6..99fcec76466 100644
--- a/chromium/third_party/blink/renderer/core/testing/mock_clipboard_host.cc
+++ b/chromium/third_party/blink/renderer/core/testing/mock_clipboard_host.cc
@@ -47,7 +47,7 @@ void MockClipboardHost::ReadAvailableTypes(
CHECK(!base::Contains(types, it.key));
types.push_back(it.key);
}
- std::move(callback).Run(types, false);
+ std::move(callback).Run(types);
}
void MockClipboardHost::IsFormatAvailable(
diff --git a/chromium/third_party/blink/renderer/core/testing/mock_clipboard_host.h b/chromium/third_party/blink/renderer/core/testing/mock_clipboard_host.h
index d380b83af26..4e58a442a25 100644
--- a/chromium/third_party/blink/renderer/core/testing/mock_clipboard_host.h
+++ b/chromium/third_party/blink/renderer/core/testing/mock_clipboard_host.h
@@ -21,6 +21,7 @@ class MockClipboardHost : public mojom::blink::ClipboardHost {
~MockClipboardHost() override;
void Bind(mojo::PendingReceiver<mojom::blink::ClipboardHost> receiver);
+ // Clears all clipboard data.
void Reset();
private:
diff --git a/chromium/third_party/blink/renderer/core/testing/null_execution_context.cc b/chromium/third_party/blink/renderer/core/testing/null_execution_context.cc
index 59cc8380b89..9318cc07315 100644
--- a/chromium/third_party/blink/renderer/core/testing/null_execution_context.cc
+++ b/chromium/third_party/blink/renderer/core/testing/null_execution_context.cc
@@ -27,7 +27,7 @@ NullExecutionContext::NullExecutionContext(
origin_trial_context,
MakeGarbageCollected<Agent>(v8::Isolate::GetCurrent(),
base::UnguessableToken::Null())),
- SecurityContext::kLocal),
+ SecurityContext::kWindow),
scheduler_(scheduler::CreateDummyFrameScheduler()) {
if (origin_trial_context)
origin_trial_context->BindExecutionContext(this);
diff --git a/chromium/third_party/blink/renderer/core/testing/null_execution_context.h b/chromium/third_party/blink/renderer/core/testing/null_execution_context.h
index 6fc27a4bead..fffe259cefd 100644
--- a/chromium/third_party/blink/renderer/core/testing/null_execution_context.h
+++ b/chromium/third_party/blink/renderer/core/testing/null_execution_context.h
@@ -7,6 +7,7 @@
#include <memory>
#include "base/single_thread_task_runner.h"
+#include "third_party/blink/public/mojom/devtools/inspector_issue.mojom-blink.h"
#include "third_party/blink/renderer/bindings/core/v8/source_location.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/execution_context/security_context.h"
@@ -41,6 +42,7 @@ class NullExecutionContext : public GarbageCollected<NullExecutionContext>,
void AddConsoleMessageImpl(ConsoleMessage*,
bool discard_duplicates) override {}
+ void AddInspectorIssue(mojom::blink::InspectorIssueInfoPtr) override {}
void ExceptionThrown(ErrorEvent*) override {}
void SetUpSecurityContextForTesting();
diff --git a/chromium/third_party/blink/renderer/core/testing/sim/sim_compositor.cc b/chromium/third_party/blink/renderer/core/testing/sim/sim_compositor.cc
index 6b7fa60a754..8ea3ac19296 100644
--- a/chromium/third_party/blink/renderer/core/testing/sim/sim_compositor.cc
+++ b/chromium/third_party/blink/renderer/core/testing/sim/sim_compositor.cc
@@ -73,8 +73,7 @@ SimCanvas::Commands SimCompositor::PaintFrame() {
return canvas.GetCommands();
}
-void SimCompositor::UpdateVisualState() {
- TestWebWidgetClient::UpdateVisualState();
+void SimCompositor::DidBeginMainFrame() {
*paint_commands_ = PaintFrame();
}
diff --git a/chromium/third_party/blink/renderer/core/testing/sim/sim_compositor.h b/chromium/third_party/blink/renderer/core/testing/sim/sim_compositor.h
index a2f3614a7c7..a99cbd5153c 100644
--- a/chromium/third_party/blink/renderer/core/testing/sim/sim_compositor.h
+++ b/chromium/third_party/blink/renderer/core/testing/sim/sim_compositor.h
@@ -7,7 +7,6 @@
#include "base/time/time.h"
#include "cc/trees/layer_tree_host.h"
-#include "content/test/stub_layer_tree_view_delegate.h"
#include "third_party/blink/renderer/core/frame/frame_test_helpers.h"
#include "third_party/blink/renderer/core/testing/sim/sim_canvas.h"
#include "third_party/blink/renderer/platform/graphics/apply_viewport_changes.h"
@@ -79,8 +78,8 @@ class SimCompositor final : public frame_test_helpers::TestWebWidgetClient {
base::TimeTicks LastFrameTime() const { return last_frame_time_; }
private:
- // content::LayerTreeViewDelegate implementation.
- void UpdateVisualState() override;
+ // TestWebWidgetClient overrides:
+ void DidBeginMainFrame() override;
WebViewImpl* web_view_ = nullptr;
frame_test_helpers::TestWebViewClient* test_web_view_client_ = nullptr;
diff --git a/chromium/third_party/blink/renderer/core/timezone/timezone_controller.cc b/chromium/third_party/blink/renderer/core/timezone/timezone_controller.cc
index 1600d8e07c6..799f6b86e73 100644
--- a/chromium/third_party/blink/renderer/core/timezone/timezone_controller.cc
+++ b/chromium/third_party/blink/renderer/core/timezone/timezone_controller.cc
@@ -6,7 +6,6 @@
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/remote.h"
-#include "services/service_manager/public/cpp/connector.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/public/platform/task_type.h"
diff --git a/chromium/third_party/blink/renderer/core/timing/BUILD.gn b/chromium/third_party/blink/renderer/core/timing/BUILD.gn
index 05dde8fa2da..1baaa6d1c4b 100644
--- a/chromium/third_party/blink/renderer/core/timing/BUILD.gn
+++ b/chromium/third_party/blink/renderer/core/timing/BUILD.gn
@@ -8,12 +8,16 @@ blink_core_sources("timing") {
sources = [
"dom_window_performance.cc",
"dom_window_performance.h",
+ "event_counts.cc",
+ "event_counts.h",
"event_timing.cc",
"event_timing.h",
"largest_contentful_paint.cc",
"largest_contentful_paint.h",
"layout_shift.cc",
"layout_shift.h",
+ "layout_shift_attribution.cc",
+ "layout_shift_attribution.h",
"measure_memory/measure_memory_delegate.cc",
"measure_memory/measure_memory_delegate.h",
"memory_info.cc",
diff --git a/chromium/third_party/blink/renderer/core/timing/event_counts.cc b/chromium/third_party/blink/renderer/core/timing/event_counts.cc
new file mode 100644
index 00000000000..45a3fca8734
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/timing/event_counts.cc
@@ -0,0 +1,103 @@
+// 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/core/timing/event_counts.h"
+
+#include "third_party/blink/renderer/platform/wtf/wtf.h"
+
+namespace blink {
+
+class EventCountsIterationSource final
+ : public PairIterable<AtomicString, unsigned>::IterationSource {
+ public:
+ explicit EventCountsIterationSource(const EventCounts& map)
+ : map_(map), iterator_(map_->Map().begin()) {}
+
+ bool Next(ScriptState* script_state,
+ AtomicString& map_key,
+ unsigned& map_value,
+ ExceptionState&) override {
+ if (iterator_ == map_->Map().end())
+ return false;
+ map_key = iterator_->key;
+ map_value = iterator_->value;
+ ++iterator_;
+ return true;
+ }
+
+ void Trace(Visitor* visitor) override {
+ visitor->Trace(map_);
+ PairIterable<AtomicString, unsigned>::IterationSource::Trace(visitor);
+ }
+
+ private:
+ // Needs to be kept alive while we're iterating over it.
+ const Member<const EventCounts> map_;
+ HashMap<AtomicString, unsigned>::const_iterator iterator_;
+};
+
+void EventCounts::Add(const AtomicString& event_type) {
+ auto iterator = event_count_map_.find(event_type);
+ DCHECK_NE(iterator, event_count_map_.end());
+ iterator->value++;
+}
+
+EventCounts::EventCounts() {
+ // Should contain the same types that would return true in
+ // IsEventTypeForEventTiming() in event_timing.cc. Note that this list differs
+ // from https://wicg.github.io/event-timing/#sec-events-exposed in that
+ // dragexit is not present since it's currently not implemented in Chrome.
+ DCHECK(IsMainThread());
+ DEFINE_STATIC_LOCAL(
+ const Vector<AtomicString>, event_types,
+ ({/* MouseEvents */
+ event_type_names::kAuxclick, event_type_names::kClick,
+ event_type_names::kContextmenu, event_type_names::kDblclick,
+ event_type_names::kMousedown, event_type_names::kMouseenter,
+ event_type_names::kMouseleave, event_type_names::kMouseout,
+ event_type_names::kMouseover, event_type_names::kMouseup,
+ /* PointerEvents */
+ event_type_names::kPointerover, event_type_names::kPointerenter,
+ event_type_names::kPointerdown, event_type_names::kPointerup,
+ event_type_names::kPointercancel, event_type_names::kPointerout,
+ event_type_names::kPointerleave, event_type_names::kGotpointercapture,
+ event_type_names::kLostpointercapture,
+ /* TouchEvents */
+ event_type_names::kTouchstart, event_type_names::kTouchend,
+ event_type_names::kTouchcancel,
+ /* KeyboardEvents */
+ event_type_names::kKeydown, event_type_names::kKeypress,
+ event_type_names::kKeyup,
+ /* InputEvents */
+ event_type_names::kBeforeinput, event_type_names::kInput,
+ /* CompositionEvents */
+ event_type_names::kCompositionstart,
+ event_type_names::kCompositionupdate, event_type_names::kCompositionend,
+ /* Drag & Drop Events */
+ event_type_names::kDragstart, event_type_names::kDragend,
+ event_type_names::kDragenter, event_type_names::kDragleave,
+ event_type_names::kDragover, event_type_names::kDrop}));
+ for (const auto& type : event_types) {
+ event_count_map_.insert(type, 0u);
+ }
+}
+
+PairIterable<AtomicString, unsigned>::IterationSource*
+EventCounts::StartIteration(ScriptState*, ExceptionState&) {
+ return MakeGarbageCollected<EventCountsIterationSource>(*this);
+}
+
+bool EventCounts::GetMapEntry(ScriptState*,
+ const AtomicString& key,
+ unsigned& value,
+ ExceptionState&) {
+ auto it = event_count_map_.find(key);
+ if (it == event_count_map_.end())
+ return false;
+
+ value = it->value;
+ return true;
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/timing/event_counts.h b/chromium/third_party/blink/renderer/core/timing/event_counts.h
new file mode 100644
index 00000000000..a2ae1431248
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/timing/event_counts.h
@@ -0,0 +1,49 @@
+// 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_CORE_TIMING_EVENT_COUNTS_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_TIMING_EVENT_COUNTS_H_
+
+#include "third_party/blink/renderer/bindings/core/v8/maplike.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
+#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
+
+namespace blink {
+
+class EventCounts final : public ScriptWrappable,
+ public Maplike<AtomicString, unsigned> {
+ DEFINE_WRAPPERTYPEINFO();
+
+ public:
+ EventCounts();
+
+ const HashMap<AtomicString, unsigned>& Map() const {
+ return event_count_map_;
+ }
+
+ // IDL attributes / methods
+ uint32_t size() const { return event_count_map_.size(); }
+
+ void Add(const AtomicString& event_type);
+
+ void Trace(Visitor* visitor) override { ScriptWrappable::Trace(visitor); }
+
+ private:
+ // Maplike implementation.
+ PairIterable<AtomicString, unsigned>::IterationSource* StartIteration(
+ ScriptState*,
+ ExceptionState&) override;
+ bool GetMapEntry(ScriptState*,
+ const AtomicString& key,
+ unsigned& value,
+ ExceptionState&) override;
+
+ HashMap<AtomicString, unsigned> event_count_map_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_KEYBOARD_KEYBOARD_event_count_map_H_
diff --git a/chromium/third_party/blink/renderer/core/timing/event_counts.idl b/chromium/third_party/blink/renderer/core/timing/event_counts.idl
new file mode 100644
index 00000000000..a78ac1fdc8a
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/timing/event_counts.idl
@@ -0,0 +1,4 @@
+[Exposed=Window, RuntimeEnabled=EventTiming]
+interface EventCounts {
+ readonly maplike<DOMString, unsigned long long>;
+};
diff --git a/chromium/third_party/blink/renderer/core/timing/event_timing.cc b/chromium/third_party/blink/renderer/core/timing/event_timing.cc
index 693a61a0140..4ced9145940 100644
--- a/chromium/third_party/blink/renderer/core/timing/event_timing.cc
+++ b/chromium/third_party/blink/renderer/core/timing/event_timing.cc
@@ -16,6 +16,7 @@
#include "third_party/blink/renderer/core/timing/performance_event_timing.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
+namespace blink {
namespace {
const base::TickClock* g_clock_for_testing = nullptr;
@@ -23,9 +24,6 @@ static base::TimeTicks Now() {
return g_clock_for_testing ? g_clock_for_testing->NowTicks()
: base::TimeTicks::Now();
}
-} // namespace
-
-namespace blink {
bool ShouldLogEvent(const Event& event) {
return event.type() == event_type_names::kPointerdown ||
@@ -36,11 +34,22 @@ bool ShouldLogEvent(const Event& event) {
}
bool IsEventTypeForEventTiming(const Event& event) {
- return (IsA<MouseEvent>(event) || IsA<PointerEvent>(event) ||
+ // Include only trusted events of certain kinds. Explicitly excluding input
+ // events that are considered continuous: event types for which the user agent
+ // may have timer-based dispatch under certain conditions. These are excluded
+ // since EventCounts cannot be used to properly computed percentiles on those.
+ // See spec: https://wicg.github.io/event-timing/#sec-events-exposed
+ return event.isTrusted() &&
+ (IsA<MouseEvent>(event) || IsA<PointerEvent>(event) ||
IsA<TouchEvent>(event) || IsA<KeyboardEvent>(event) ||
IsA<WheelEvent>(event) || event.IsInputEvent() ||
- event.IsCompositionEvent()) &&
- event.isTrusted();
+ event.IsCompositionEvent() || event.IsDragEvent()) &&
+ event.type() != event_type_names::kMousemove &&
+ event.type() != event_type_names::kPointermove &&
+ event.type() != event_type_names::kPointerrawupdate &&
+ event.type() != event_type_names::kTouchmove &&
+ event.type() != event_type_names::kWheel &&
+ event.type() != event_type_names::kDrag;
}
bool ShouldReportForEventTiming(WindowPerformance* performance) {
@@ -55,6 +64,8 @@ bool ShouldReportForEventTiming(WindowPerformance* performance) {
performance->HasObserverFor(PerformanceEntry::kEvent));
}
+} // namespace
+
EventTiming::EventTiming(base::TimeTicks processing_start,
base::TimeTicks event_timestamp,
WindowPerformance* performance)
@@ -82,10 +93,8 @@ std::unique_ptr<EventTiming> EventTiming::Create(LocalDOMWindow* window,
base::TimeTicks processing_start = Now();
if (should_log_event) {
- Document* document =
- Document::DynamicFrom(performance->GetExecutionContext());
InteractiveDetector* interactive_detector =
- InteractiveDetector::From(*document);
+ InteractiveDetector::From(*window->document());
if (interactive_detector) {
interactive_detector->HandleForInputDelay(event, event_timestamp,
processing_start);
@@ -99,9 +108,10 @@ std::unique_ptr<EventTiming> EventTiming::Create(LocalDOMWindow* window,
}
void EventTiming::DidDispatchEvent(const Event& event) {
+ Node* target = event.target() ? event.target()->ToNode() : nullptr;
performance_->RegisterEventTiming(event.type(), event_timestamp_,
processing_start_, Now(),
- event.cancelable());
+ event.cancelable(), target);
}
// static
diff --git a/chromium/third_party/blink/renderer/core/timing/largest_contentful_paint.cc b/chromium/third_party/blink/renderer/core/timing/largest_contentful_paint.cc
index 59dc537a024..f7c5f33e7a8 100644
--- a/chromium/third_party/blink/renderer/core/timing/largest_contentful_paint.cc
+++ b/chromium/third_party/blink/renderer/core/timing/largest_contentful_paint.cc
@@ -12,9 +12,9 @@
namespace blink {
LargestContentfulPaint::LargestContentfulPaint(double start_time,
- double render_time,
+ base::TimeDelta render_time,
uint64_t size,
- double load_time,
+ base::TimeDelta load_time,
const AtomicString& id,
const String& url,
Element* element)
@@ -51,8 +51,8 @@ Element* LargestContentfulPaint::element() const {
void LargestContentfulPaint::BuildJSONValue(V8ObjectBuilder& builder) const {
PerformanceEntry::BuildJSONValue(builder);
builder.Add("size", size_);
- builder.Add("renderTime", render_time_);
- builder.Add("loadTime", load_time_);
+ builder.Add("renderTime", render_time_.InMillisecondsF());
+ builder.Add("loadTime", load_time_.InMillisecondsF());
builder.Add("id", id_);
builder.Add("url", url_);
builder.Add("element", element());
diff --git a/chromium/third_party/blink/renderer/core/timing/largest_contentful_paint.h b/chromium/third_party/blink/renderer/core/timing/largest_contentful_paint.h
index 1c0e66fd233..cbfba5a201e 100644
--- a/chromium/third_party/blink/renderer/core/timing/largest_contentful_paint.h
+++ b/chromium/third_party/blink/renderer/core/timing/largest_contentful_paint.h
@@ -18,9 +18,9 @@ class CORE_EXPORT LargestContentfulPaint final : public PerformanceEntry {
public:
LargestContentfulPaint(double start_time,
- double render_time,
+ base::TimeDelta render_time,
uint64_t size,
- double load_time,
+ base::TimeDelta load_time,
const AtomicString& id,
const String& url,
Element*);
@@ -30,8 +30,10 @@ class CORE_EXPORT LargestContentfulPaint final : public PerformanceEntry {
PerformanceEntryType EntryTypeEnum() const override;
uint64_t size() const { return size_; }
- DOMHighResTimeStamp renderTime() const { return render_time_; }
- DOMHighResTimeStamp loadTime() const { return load_time_; }
+ DOMHighResTimeStamp renderTime() const {
+ return render_time_.InMillisecondsF();
+ }
+ DOMHighResTimeStamp loadTime() const { return load_time_.InMillisecondsF(); }
const AtomicString& id() const { return id_; }
const String& url() const { return url_; }
Element* element() const;
@@ -42,8 +44,8 @@ class CORE_EXPORT LargestContentfulPaint final : public PerformanceEntry {
void BuildJSONValue(V8ObjectBuilder&) const override;
uint64_t size_;
- DOMHighResTimeStamp render_time_;
- DOMHighResTimeStamp load_time_;
+ base::TimeDelta render_time_;
+ base::TimeDelta load_time_;
AtomicString id_;
String url_;
WeakMember<Element> element_;
diff --git a/chromium/third_party/blink/renderer/core/timing/layout_shift.cc b/chromium/third_party/blink/renderer/core/timing/layout_shift.cc
index 419dcb34c44..fb5ad66572f 100644
--- a/chromium/third_party/blink/renderer/core/timing/layout_shift.cc
+++ b/chromium/third_party/blink/renderer/core/timing/layout_shift.cc
@@ -10,14 +10,26 @@
namespace blink {
+// static
+LayoutShift* LayoutShift::Create(double start_time,
+ double value,
+ bool input_detected,
+ double input_timestamp,
+ AttributionList sources) {
+ return MakeGarbageCollected<LayoutShift>(start_time, value, input_detected,
+ input_timestamp, sources);
+}
+
LayoutShift::LayoutShift(double start_time,
double value,
bool input_detected,
- double input_timestamp)
+ double input_timestamp,
+ AttributionList sources)
: PerformanceEntry(g_empty_atom, start_time, start_time),
value_(value),
had_recent_input_(input_detected),
- most_recent_input_timestamp_(input_timestamp) {}
+ most_recent_input_timestamp_(input_timestamp),
+ sources_(sources) {}
LayoutShift::~LayoutShift() = default;
@@ -34,10 +46,17 @@ void LayoutShift::BuildJSONValue(V8ObjectBuilder& builder) const {
builder.Add("value", value_);
builder.Add("hadRecentInput", had_recent_input_);
builder.Add("lastInputTime", most_recent_input_timestamp_);
+
+ if (RuntimeEnabledFeatures::LayoutShiftAttributionEnabled()) {
+ ScriptState* script_state = builder.GetScriptState();
+ builder.Add("sources", FreezeV8Object(ToV8(sources_, script_state),
+ script_state->GetIsolate()));
+ }
}
void LayoutShift::Trace(Visitor* visitor) {
PerformanceEntry::Trace(visitor);
+ visitor->Trace(sources_);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/timing/layout_shift.h b/chromium/third_party/blink/renderer/core/timing/layout_shift.h
index 65479493b8b..d5d29f59659 100644
--- a/chromium/third_party/blink/renderer/core/timing/layout_shift.h
+++ b/chromium/third_party/blink/renderer/core/timing/layout_shift.h
@@ -7,6 +7,7 @@
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/dom/dom_high_res_time_stamp.h"
+#include "third_party/blink/renderer/core/timing/layout_shift_attribution.h"
#include "third_party/blink/renderer/core/timing/performance_entry.h"
namespace blink {
@@ -17,10 +18,24 @@ class CORE_EXPORT LayoutShift final : public PerformanceEntry {
DEFINE_WRAPPERTYPEINFO();
public:
- LayoutShift(double start_time,
- double value,
- bool input_detected,
- double input_timestamp);
+ // Maximum number of attributions (shifted elements) to record in any single
+ // animation frame.
+ static constexpr int kMaxAttributions = 5;
+ typedef HeapVector<Member<LayoutShiftAttribution>, kMaxAttributions>
+ AttributionList;
+
+ static LayoutShift* Create(double start_time,
+ double value,
+ bool input_detected,
+ double input_timestamp,
+ AttributionList sources);
+
+ explicit LayoutShift(double start_time,
+ double value,
+ bool input_detected,
+ double input_timestamp,
+ AttributionList sources);
+
~LayoutShift() override;
AtomicString entryType() const override;
@@ -30,6 +45,8 @@ class CORE_EXPORT LayoutShift final : public PerformanceEntry {
bool hadRecentInput() const { return had_recent_input_; }
double lastInputTime() const { return most_recent_input_timestamp_; }
+ AttributionList sources() const { return sources_; }
+
void Trace(Visitor*) override;
private:
@@ -38,6 +55,7 @@ class CORE_EXPORT LayoutShift final : public PerformanceEntry {
double value_;
bool had_recent_input_;
DOMHighResTimeStamp most_recent_input_timestamp_;
+ AttributionList sources_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/timing/layout_shift.idl b/chromium/third_party/blink/renderer/core/timing/layout_shift.idl
index 2170984ff92..053a6e14a0b 100644
--- a/chromium/third_party/blink/renderer/core/timing/layout_shift.idl
+++ b/chromium/third_party/blink/renderer/core/timing/layout_shift.idl
@@ -8,6 +8,7 @@ interface LayoutShift : PerformanceEntry {
readonly attribute double value;
readonly attribute boolean hadRecentInput;
readonly attribute DOMHighResTimeStamp lastInputTime;
+ [RuntimeEnabled=LayoutShiftAttribution, SameObject, SaveSameObject] readonly attribute FrozenArray<LayoutShiftAttribution> sources;
[CallWith=ScriptState, ImplementedAs=toJSONForBinding] object toJSON();
};
diff --git a/chromium/third_party/blink/renderer/core/timing/layout_shift_attribution.cc b/chromium/third_party/blink/renderer/core/timing/layout_shift_attribution.cc
new file mode 100644
index 00000000000..b9fc9107c01
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/timing/layout_shift_attribution.cc
@@ -0,0 +1,58 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/timing/layout_shift_attribution.h"
+
+#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_object_builder.h"
+#include "third_party/blink/renderer/core/dom/node.h"
+#include "third_party/blink/renderer/core/geometry/dom_rect_read_only.h"
+#include "third_party/blink/renderer/core/timing/performance.h"
+
+namespace blink {
+
+// static
+LayoutShiftAttribution* LayoutShiftAttribution::Create(
+ Node* node,
+ DOMRectReadOnly* previous,
+ DOMRectReadOnly* current) {
+ return MakeGarbageCollected<LayoutShiftAttribution>(node, previous, current);
+}
+
+LayoutShiftAttribution::LayoutShiftAttribution(Node* node,
+ DOMRectReadOnly* previous,
+ DOMRectReadOnly* current)
+ : node_(node), previous_rect_(previous), current_rect_(current) {}
+
+LayoutShiftAttribution::~LayoutShiftAttribution() = default;
+
+Node* LayoutShiftAttribution::node() const {
+ return Performance::CanExposeNode(node_) ? node_ : nullptr;
+}
+
+DOMRectReadOnly* LayoutShiftAttribution::previousRect() const {
+ return previous_rect_;
+}
+
+DOMRectReadOnly* LayoutShiftAttribution::currentRect() const {
+ return current_rect_;
+}
+
+ScriptValue LayoutShiftAttribution::toJSONForBinding(
+ ScriptState* script_state) const {
+ V8ObjectBuilder builder(script_state);
+ builder.Add("node", node());
+ builder.Add("previousRect", previous_rect_);
+ builder.Add("currentRect", current_rect_);
+ return builder.GetScriptValue();
+}
+
+void LayoutShiftAttribution::Trace(Visitor* visitor) {
+ visitor->Trace(node_);
+ visitor->Trace(previous_rect_);
+ visitor->Trace(current_rect_);
+ ScriptWrappable::Trace(visitor);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/timing/layout_shift_attribution.h b/chromium/third_party/blink/renderer/core/timing/layout_shift_attribution.h
new file mode 100644
index 00000000000..d68704bf200
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/timing/layout_shift_attribution.h
@@ -0,0 +1,43 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_TIMING_LAYOUT_SHIFT_ATTRIBUTION_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_TIMING_LAYOUT_SHIFT_ATTRIBUTION_H_
+
+#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+
+namespace blink {
+
+class DOMRectReadOnly;
+class ScriptState;
+class ScriptValue;
+
+class CORE_EXPORT LayoutShiftAttribution : public ScriptWrappable {
+ DEFINE_WRAPPERTYPEINFO();
+
+ public:
+ static LayoutShiftAttribution* Create(Node*,
+ DOMRectReadOnly* previous,
+ DOMRectReadOnly* current);
+ LayoutShiftAttribution(Node*,
+ DOMRectReadOnly* previous,
+ DOMRectReadOnly* current);
+ ~LayoutShiftAttribution() override;
+
+ Node* node() const;
+ DOMRectReadOnly* previousRect() const;
+ DOMRectReadOnly* currentRect() const;
+
+ ScriptValue toJSONForBinding(ScriptState*) const;
+ void Trace(Visitor*) override;
+
+ WeakMember<Node> node_;
+ Member<DOMRectReadOnly> previous_rect_;
+ Member<DOMRectReadOnly> current_rect_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_TIMING_LAYOUT_SHIFT_ATTRIBUTION_H_
diff --git a/chromium/third_party/blink/renderer/core/timing/layout_shift_attribution.idl b/chromium/third_party/blink/renderer/core/timing/layout_shift_attribution.idl
new file mode 100644
index 00000000000..c20bb1103d2
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/timing/layout_shift_attribution.idl
@@ -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.
+
+// https://wicg.github.io/layout-instability/#sec-layout-shift-attribution
+[Exposed=Window, RuntimeEnabled=LayoutShiftAttribution]
+interface LayoutShiftAttribution {
+ readonly attribute Node? node;
+ readonly attribute DOMRectReadOnly previousRect;
+ readonly attribute DOMRectReadOnly currentRect;
+
+ [CallWith=ScriptState, ImplementedAs=toJSONForBinding] object toJSON();
+};
diff --git a/chromium/third_party/blink/renderer/core/timing/measure_memory/measure_memory_delegate.cc b/chromium/third_party/blink/renderer/core/timing/measure_memory/measure_memory_delegate.cc
index dab967eed09..325bbf35aab 100644
--- a/chromium/third_party/blink/renderer/core/timing/measure_memory/measure_memory_delegate.cc
+++ b/chromium/third_party/blink/renderer/core/timing/measure_memory/measure_memory_delegate.cc
@@ -11,6 +11,7 @@
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/frame/frame.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/page/frame_tree.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"
@@ -77,13 +78,12 @@ namespace {
// Helper functions for constructing a memory measurement result.
const LocalFrame* GetFrame(v8::Local<v8::Context> context) {
- ExecutionContext* execution_context = ExecutionContext::From(context);
- if (!execution_context) {
+ LocalDOMWindow* window = ToLocalDOMWindow(context);
+ if (!window) {
// The context was detached. Ignore it.
return nullptr;
}
- DCHECK(execution_context->IsDocument());
- return Document::From(execution_context)->GetFrame();
+ return window->GetFrame();
}
String GetUrl(const LocalFrame* frame) {
diff --git a/chromium/third_party/blink/renderer/core/timing/memory_info.h b/chromium/third_party/blink/renderer/core/timing/memory_info.h
index 7cc0704a8f7..63cb4024343 100644
--- a/chromium/third_party/blink/renderer/core/timing/memory_info.h
+++ b/chromium/third_party/blink/renderer/core/timing/memory_info.h
@@ -62,9 +62,9 @@ class CORE_EXPORT MemoryInfo final : public ScriptWrappable {
explicit MemoryInfo(Precision precision);
- size_t totalJSHeapSize() const { return info_.total_js_heap_size; }
- size_t usedJSHeapSize() const { return info_.used_js_heap_size; }
- size_t jsHeapSizeLimit() const { return info_.js_heap_size_limit; }
+ uint64_t totalJSHeapSize() const { return info_.total_js_heap_size; }
+ uint64_t usedJSHeapSize() const { return info_.used_js_heap_size; }
+ uint64_t jsHeapSizeLimit() const { return info_.js_heap_size_limit; }
private:
FRIEND_TEST_ALL_PREFIXES(MemoryInfoTest, Bucketized);
diff --git a/chromium/third_party/blink/renderer/core/timing/performance.cc b/chromium/third_party/blink/renderer/core/timing/performance.cc
index 90e1f4a4d68..ba1ce5825d5 100644
--- a/chromium/third_party/blink/renderer/core/timing/performance.cc
+++ b/chromium/third_party/blink/renderer/core/timing/performance.cc
@@ -50,6 +50,7 @@
#include "third_party/blink/renderer/core/dom/dom_exception.h"
#include "third_party/blink/renderer/core/dom/events/event.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/inspector/console_message.h"
#include "third_party/blink/renderer/core/loader/document_load_timing.h"
@@ -88,13 +89,6 @@ const SecurityOrigin* GetSecurityOrigin(ExecutionContext* context) {
return nullptr;
}
-const Performance::UnifiedClock* DefaultUnifiedClock() {
- DEFINE_THREAD_SAFE_STATIC_LOCAL(Performance::UnifiedClock, unified_clock,
- (base::DefaultClock::GetInstance(),
- base::DefaultTickClock::GetInstance()));
- return &unified_clock;
-}
-
bool IsMeasureOptionsEmpty(const PerformanceMeasureOptions& options) {
return !options.hasDetail() && !options.hasEnd() && !options.hasStart() &&
!options.hasDuration();
@@ -119,7 +113,7 @@ Performance::Performance(
element_timing_buffer_max_size_(kDefaultElementTimingBufferSize),
user_timing_(nullptr),
time_origin_(time_origin),
- unified_clock_(DefaultUnifiedClock()),
+ tick_clock_(base::DefaultTickClock::GetInstance()),
observer_filter_options_(PerformanceEntry::kInvalid),
task_runner_(std::move(task_runner)),
deliver_observations_timer_(task_runner_,
@@ -128,7 +122,11 @@ Performance::Performance(
resource_timing_buffer_full_timer_(
task_runner_,
this,
- &Performance::FireResourceTimingBufferFull) {}
+ &Performance::FireResourceTimingBufferFull) {
+ unix_at_zero_monotonic_ = ConvertSecondsToDOMHighResTimeStamp(
+ base::DefaultClock::GetInstance()->Now().ToDoubleT() -
+ tick_clock_->NowTicks().since_origin().InSecondsF());
+}
Performance::~Performance() = default;
@@ -148,6 +146,10 @@ MemoryInfo* Performance::memory() const {
return nullptr;
}
+EventCounts* Performance::eventCounts() {
+ return nullptr;
+}
+
namespace {
bool IsMeasureMemoryAvailable(ScriptState* script_state) {
@@ -159,11 +161,11 @@ bool IsMeasureMemoryAvailable(ScriptState* script_state) {
}
// The window.crossOriginIsolated will be true only for the top-level frame.
// Until the flag is available we check for the top-level condition manually.
- ExecutionContext* execution_context = ExecutionContext::From(script_state);
- if (!execution_context->IsDocument()) {
+ LocalDOMWindow* window = LocalDOMWindow::From(script_state);
+ if (!window) {
return false;
}
- LocalFrame* local_frame = Document::From(execution_context)->GetFrame();
+ LocalFrame* local_frame = window->GetFrame();
if (!local_frame || !local_frame->IsMainFrame()) {
return false;
}
@@ -202,7 +204,7 @@ ScriptPromise Performance::measureMemory(
DOMHighResTimeStamp Performance::timeOrigin() const {
DCHECK(!time_origin_.is_null());
- return unified_clock_->GetUnixAtZeroMonotonic() +
+ return unix_at_zero_monotonic_ +
ConvertTimeTicksToDOMHighResTimeStamp(time_origin_);
}
@@ -278,6 +280,8 @@ PerformanceEntryVector Performance::getEntriesByTypeInternal(
case PerformanceEntry::kFirstInput:
UseCounter::Count(GetExecutionContext(),
WebFeature::kEventTimingExplicitlyRequested);
+ UseCounter::Count(GetExecutionContext(),
+ WebFeature::kEventTimingFirstInputExplicitlyRequested);
if (first_input_timing_)
entries.push_back(first_input_timing_);
break;
@@ -739,7 +743,7 @@ PerformanceMark* Performance::mark(ScriptState* script_state,
(mark_options->hasStartTime() || mark_options->hasDetail())) {
UseCounter::Count(GetExecutionContext(), WebFeature::kUserTimingL3);
}
- PerformanceMark* performance_mark = GetUserTiming().CreatePerformanceMark(
+ PerformanceMark* performance_mark = PerformanceMark::Create(
script_state, mark_name, mark_options, exception_state);
if (performance_mark) {
GetUserTiming().AddMarkToPerformanceTimeline(*performance_mark);
@@ -855,8 +859,7 @@ PerformanceMeasure* Performance::MeasureInternal(
return MeasureWithDetail(
script_state, measure_name, converted_start,
/* duration = */ base::nullopt,
- end_mark ? StringOrDouble::FromString(*end_mark)
- : NativeValueTraits<StringOrDouble>::NullValue(),
+ end_mark ? StringOrDouble::FromString(*end_mark) : StringOrDouble(),
ScriptValue::CreateNull(script_state->GetIsolate()), exception_state);
}
@@ -931,7 +934,8 @@ void Performance::NotifyObserversOfEntry(PerformanceEntry& entry) const {
RuntimeEnabledFeatures::EventTimingEnabled(GetExecutionContext()));
bool observer_found = false;
for (auto& observer : observers_) {
- if (observer->FilterOptions() & entry.EntryTypeEnum()) {
+ if (observer->FilterOptions() & entry.EntryTypeEnum() &&
+ observer->CanObserve(entry)) {
observer->EnqueuePerformanceEntry(entry);
observer_found = true;
}
@@ -992,14 +996,42 @@ DOMHighResTimeStamp Performance::MonotonicTimeToDOMHighResTimeStamp(
return ConvertSecondsToDOMHighResTimeStamp(clamped_time_in_seconds);
}
+// static
+base::TimeDelta Performance::MonotonicTimeToTimeDelta(
+ base::TimeTicks time_origin,
+ base::TimeTicks monotonic_time,
+ bool allow_negative_value) {
+ return base::TimeDelta::FromMillisecondsD(MonotonicTimeToDOMHighResTimeStamp(
+ time_origin, monotonic_time, allow_negative_value));
+}
+
DOMHighResTimeStamp Performance::MonotonicTimeToDOMHighResTimeStamp(
base::TimeTicks monotonic_time) const {
return MonotonicTimeToDOMHighResTimeStamp(time_origin_, monotonic_time,
false /* allow_negative_value */);
}
+base::TimeDelta Performance::MonotonicTimeToTimeDelta(
+ base::TimeTicks monotonic_time) const {
+ return MonotonicTimeToTimeDelta(time_origin_, monotonic_time,
+ false /* allow_negative_value */);
+}
+
DOMHighResTimeStamp Performance::now() const {
- return MonotonicTimeToDOMHighResTimeStamp(unified_clock_->NowTicks());
+ return MonotonicTimeToDOMHighResTimeStamp(tick_clock_->NowTicks());
+}
+
+// static
+bool Performance::CanExposeNode(Node* node) {
+ if (!node || !node->isConnected() || node->IsInShadowTree())
+ return false;
+
+ // Do not expose |node| when the document is not 'fully active'.
+ const Document& document = node->GetDocument();
+ if (!document.IsActive() || !document.GetFrame())
+ return false;
+
+ return true;
}
ScriptValue Performance::toJSONForBinding(ScriptState* script_state) const {
@@ -1032,25 +1064,13 @@ void Performance::Trace(Visitor* visitor) {
EventTargetWithInlineData::Trace(visitor);
}
-DOMHighResTimeStamp Performance::UnifiedClock::GetUnixAtZeroMonotonic() const {
- // When a Performance object is first queried, use the current system time
- // to calculate what the Unix time would be at the time the monotonic
- // clock time was zero, assuming no manual changes to the system clock.
- // This can be calculated as current_unix_time - current_monotonic_time.
- if (UNLIKELY(!unix_at_zero_monotonic_)) {
- unix_at_zero_monotonic_ = ConvertSecondsToDOMHighResTimeStamp(
- clock_->Now().ToDoubleT() -
- tick_clock_->NowTicks().since_origin().InSecondsF());
- }
- return unix_at_zero_monotonic_.value();
-}
-
-base::TimeTicks Performance::UnifiedClock::NowTicks() const {
- return tick_clock_->NowTicks();
-}
-
-void Performance::SetClocksForTesting(const UnifiedClock* clock) {
- unified_clock_ = clock;
+void Performance::SetClocksForTesting(const base::Clock* clock,
+ const base::TickClock* tick_clock) {
+ tick_clock_ = tick_clock;
+ // Recompute |unix_at_zero_monotonic_|.
+ unix_at_zero_monotonic_ = ConvertSecondsToDOMHighResTimeStamp(
+ clock->Now().ToDoubleT() -
+ tick_clock_->NowTicks().since_origin().InSecondsF());
}
void Performance::ResetTimeOriginForTesting(base::TimeTicks time_origin) {
diff --git a/chromium/third_party/blink/renderer/core/timing/performance.h b/chromium/third_party/blink/renderer/core/timing/performance.h
index 865d975beeb..70d4d20d51d 100644
--- a/chromium/third_party/blink/renderer/core/timing/performance.h
+++ b/chromium/third_party/blink/renderer/core/timing/performance.h
@@ -58,10 +58,12 @@ class TickClock;
namespace blink {
class PerformanceMarkOptions;
+class EventCounts;
class ExceptionState;
class LargestContentfulPaint;
class LayoutShift;
class MemoryInfo;
+class Node;
class PerformanceElementTiming;
class PerformanceEventTiming;
class PerformanceMark;
@@ -97,6 +99,7 @@ class CORE_EXPORT Performance : public EventTargetWithInlineData {
virtual MemoryInfo* memory() const;
virtual ScriptPromise measureMemory(ScriptState*,
ExceptionState& exception_state) const;
+ virtual EventCounts* eventCounts();
// Reduce the resolution to prevent timing attacks. See:
// http://www.w3.org/TR/hr-time-2/#privacy-security
@@ -107,6 +110,11 @@ class CORE_EXPORT Performance : public EventTargetWithInlineData {
base::TimeTicks monotonic_time,
bool allow_negative_value);
+ static base::TimeDelta MonotonicTimeToTimeDelta(
+ base::TimeTicks time_origin,
+ base::TimeTicks monotonic_time,
+ bool allow_negative_value);
+
// Translate given platform monotonic time in seconds into a high resolution
// DOMHighResTimeStamp in milliseconds. The result timestamp is relative to
// document's time origin and has a time resolution that is safe for
@@ -114,6 +122,12 @@ class CORE_EXPORT Performance : public EventTargetWithInlineData {
DOMHighResTimeStamp MonotonicTimeToDOMHighResTimeStamp(base::TimeTicks) const;
DOMHighResTimeStamp now() const;
+ // Translate given platform monotonic time in seconds into base::TimeDelta.
+ // The result timestamp is relative to document's time origin and is
+ // equivalent to the timestamp returned by the function
+ // MonotonicTimeToDOMHighResTimeStamp.
+ base::TimeDelta MonotonicTimeToTimeDelta(base::TimeTicks) const;
+
// High Resolution Time Level 3 timeOrigin.
// (https://www.w3.org/TR/hr-time-3/#dom-performance-timeorigin)
DOMHighResTimeStamp timeOrigin() const;
@@ -285,25 +299,16 @@ class CORE_EXPORT Performance : public EventTargetWithInlineData {
const SecurityOrigin&,
ExecutionContext*);
+ // Determine whether a given Node can be exposed via a Web Perf API.
+ static bool CanExposeNode(Node*);
+
ScriptValue toJSONForBinding(ScriptState*) const;
void Trace(Visitor*) override;
- class UnifiedClock {
- public:
- UnifiedClock(const base::Clock* clock, const base::TickClock* tick_clock)
- : clock_(clock), tick_clock_(tick_clock) {}
- DOMHighResTimeStamp GetUnixAtZeroMonotonic() const;
- base::TimeTicks NowTicks() const;
-
- private:
- const base::Clock* clock_;
- const base::TickClock* tick_clock_;
- mutable base::Optional<DOMHighResTimeStamp> unix_at_zero_monotonic_;
- };
-
// The caller owns the |clock|.
- void SetClocksForTesting(const UnifiedClock* clock);
+ void SetClocksForTesting(const base::Clock* clock,
+ const base::TickClock* tick_clock);
void ResetTimeOriginForTesting(base::TimeTicks time_origin);
private:
@@ -370,7 +375,8 @@ class CORE_EXPORT Performance : public EventTargetWithInlineData {
Member<PerformanceEventTiming> first_input_timing_;
base::TimeTicks time_origin_;
- const UnifiedClock* unified_clock_;
+ DOMHighResTimeStamp unix_at_zero_monotonic_;
+ const base::TickClock* tick_clock_;
PerformanceEntryTypeMask observer_filter_options_;
HeapLinkedHashSet<Member<PerformanceObserver>> observers_;
diff --git a/chromium/third_party/blink/renderer/core/timing/performance.idl b/chromium/third_party/blink/renderer/core/timing/performance.idl
index aaf65a0cc3d..4939cad8a26 100644
--- a/chromium/third_party/blink/renderer/core/timing/performance.idl
+++ b/chromium/third_party/blink/renderer/core/timing/performance.idl
@@ -58,12 +58,8 @@ interface Performance : EventTarget {
// User Timing
// https://w3c.github.io/user-timing/#extensions-performance-interface
- // TODO(https://crbug.com/996275): Once our IDL parser supports it, we need
- // to supply a default-value of '{}' to markOptions.
[MeasureAs=UserTiming, CallWith=ScriptState, RaisesException] PerformanceMark mark(DOMString markName, optional PerformanceMarkOptions markOptions = {});
[MeasureAs=UserTiming] void clearMarks(optional DOMString markName);
- // TODO(https://crbug.com/996275): Once our IDL parser supports it, we need
- // to supply a default-value of '{}' to startOrOptions.
[MeasureAs=UserTiming, CallWith=ScriptState, RaisesException] PerformanceMeasure measure(DOMString measureName, optional (DOMString or PerformanceMeasureOptions) startOrMeasureOptions = {}, optional DOMString endMark);
[MeasureAs=UserTiming] void clearMeasures(optional DOMString measureName);
@@ -77,5 +73,8 @@ interface Performance : EventTarget {
// https://github.com/WICG/js-self-profiling/
[MeasureAs=JSSelfProfiling, CallWith=ScriptState, RuntimeEnabled=ExperimentalJSProfiler, RaisesException] Promise<Profiler> profile(ProfilerInitOptions options);
+ // Event Timing
+ [Exposed=Window, SameObject, SaveSameObject, RuntimeEnabled=EventTiming] readonly attribute EventCounts eventCounts;
+
[CallWith=ScriptState, ImplementedAs=toJSONForBinding] object toJSON();
};
diff --git a/chromium/third_party/blink/renderer/core/timing/performance_element_timing.cc b/chromium/third_party/blink/renderer/core/timing/performance_element_timing.cc
index 69794a614e2..dddad84e15d 100644
--- a/chromium/third_party/blink/renderer/core/timing/performance_element_timing.cc
+++ b/chromium/third_party/blink/renderer/core/timing/performance_element_timing.cc
@@ -7,6 +7,7 @@
#include "third_party/blink/renderer/bindings/core/v8/v8_object_builder.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/performance_entry_names.h"
+#include "third_party/blink/renderer/core/timing/performance.h"
namespace blink {
@@ -67,15 +68,7 @@ PerformanceEntryType PerformanceElementTiming::EntryTypeEnum() const {
}
Element* PerformanceElementTiming::element() const {
- if (!element_ || !element_->isConnected() || element_->IsInShadowTree())
- return nullptr;
-
- // Do not expose |element_| when the document is not 'fully active'.
- const Document& document = element_->GetDocument();
- if (!document.IsActive() || !document.GetFrame())
- return nullptr;
-
- return element_;
+ return Performance::CanExposeNode(element_) ? element_ : nullptr;
}
void PerformanceElementTiming::BuildJSONValue(V8ObjectBuilder& builder) const {
diff --git a/chromium/third_party/blink/renderer/core/timing/performance_event_timing.cc b/chromium/third_party/blink/renderer/core/timing/performance_event_timing.cc
index fa09ed52a68..85dd00b9251 100644
--- a/chromium/third_party/blink/renderer/core/timing/performance_event_timing.cc
+++ b/chromium/third_party/blink/renderer/core/timing/performance_event_timing.cc
@@ -5,7 +5,9 @@
#include "third_party/blink/renderer/core/timing/performance_event_timing.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_object_builder.h"
+#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/performance_entry_names.h"
+#include "third_party/blink/renderer/core/timing/performance.h"
namespace blink {
@@ -15,13 +17,14 @@ PerformanceEventTiming* PerformanceEventTiming::Create(
DOMHighResTimeStamp start_time,
DOMHighResTimeStamp processing_start,
DOMHighResTimeStamp processing_end,
- bool cancelable) {
+ bool cancelable,
+ Node* target) {
// TODO(npm): enable this DCHECK once https://crbug.com/852846 is fixed.
// DCHECK_LE(start_time, processing_start);
DCHECK_LE(processing_start, processing_end);
return MakeGarbageCollected<PerformanceEventTiming>(
event_type, performance_entry_names::kEvent, start_time, processing_start,
- processing_end, cancelable);
+ processing_end, cancelable, target);
}
// static
@@ -31,7 +34,7 @@ PerformanceEventTiming* PerformanceEventTiming::CreateFirstInputTiming(
MakeGarbageCollected<PerformanceEventTiming>(
entry->name(), performance_entry_names::kFirstInput,
entry->startTime(), entry->processingStart(), entry->processingEnd(),
- entry->cancelable());
+ entry->cancelable(), entry->target());
first_input->SetDuration(entry->duration());
return first_input;
}
@@ -42,12 +45,14 @@ PerformanceEventTiming::PerformanceEventTiming(
DOMHighResTimeStamp start_time,
DOMHighResTimeStamp processing_start,
DOMHighResTimeStamp processing_end,
- bool cancelable)
+ bool cancelable,
+ Node* target)
: PerformanceEntry(event_type, start_time, 0.0),
entry_type_(entry_type),
processing_start_(processing_start),
processing_end_(processing_end),
- cancelable_(cancelable) {}
+ cancelable_(cancelable),
+ target_(target) {}
PerformanceEventTiming::~PerformanceEventTiming() = default;
@@ -65,6 +70,10 @@ DOMHighResTimeStamp PerformanceEventTiming::processingEnd() const {
return processing_end_;
}
+Node* PerformanceEventTiming::target() const {
+ return Performance::CanExposeNode(target_) ? target_ : nullptr;
+}
+
void PerformanceEventTiming::SetDuration(double duration) {
// TODO(npm): enable this DCHECK once https://crbug.com/852846 is fixed.
// DCHECK_LE(0, duration);
@@ -76,10 +85,12 @@ void PerformanceEventTiming::BuildJSONValue(V8ObjectBuilder& builder) const {
builder.AddNumber("processingStart", processingStart());
builder.AddNumber("processingEnd", processingEnd());
builder.AddBoolean("cancelable", cancelable_);
+ builder.Add("target", target());
}
void PerformanceEventTiming::Trace(Visitor* visitor) {
PerformanceEntry::Trace(visitor);
+ visitor->Trace(target_);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/timing/performance_event_timing.h b/chromium/third_party/blink/renderer/core/timing/performance_event_timing.h
index 4ef864526ee..bb05e7c6da0 100644
--- a/chromium/third_party/blink/renderer/core/timing/performance_event_timing.h
+++ b/chromium/third_party/blink/renderer/core/timing/performance_event_timing.h
@@ -20,7 +20,8 @@ class CORE_EXPORT PerformanceEventTiming final : public PerformanceEntry {
DOMHighResTimeStamp start_time,
DOMHighResTimeStamp processing_start,
DOMHighResTimeStamp processing_end,
- bool cancelable);
+ bool cancelable,
+ Node* target);
static PerformanceEventTiming* CreateFirstInputTiming(
PerformanceEventTiming* entry);
@@ -30,7 +31,8 @@ class CORE_EXPORT PerformanceEventTiming final : public PerformanceEntry {
DOMHighResTimeStamp start_time,
DOMHighResTimeStamp processing_start,
DOMHighResTimeStamp processing_end,
- bool cancelable);
+ bool cancelable,
+ Node* target);
~PerformanceEventTiming() override;
AtomicString entryType() const override { return entry_type_; }
@@ -41,6 +43,8 @@ class CORE_EXPORT PerformanceEventTiming final : public PerformanceEntry {
DOMHighResTimeStamp processingStart() const;
DOMHighResTimeStamp processingEnd() const;
+ Node* target() const;
+
void SetDuration(double duration);
void BuildJSONValue(V8ObjectBuilder&) const override;
@@ -52,6 +56,7 @@ class CORE_EXPORT PerformanceEventTiming final : public PerformanceEntry {
DOMHighResTimeStamp processing_start_;
DOMHighResTimeStamp processing_end_;
bool cancelable_;
+ WeakMember<Node> target_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/timing/performance_event_timing.idl b/chromium/third_party/blink/renderer/core/timing/performance_event_timing.idl
index 13fecf6532e..17b3db120b1 100644
--- a/chromium/third_party/blink/renderer/core/timing/performance_event_timing.idl
+++ b/chromium/third_party/blink/renderer/core/timing/performance_event_timing.idl
@@ -8,6 +8,7 @@ interface PerformanceEventTiming : PerformanceEntry {
readonly attribute DOMHighResTimeStamp processingStart;
readonly attribute DOMHighResTimeStamp processingEnd;
readonly attribute boolean cancelable;
+ [RuntimeEnabled=EventTiming] readonly attribute Node? target;
[CallWith=ScriptState, ImplementedAs=toJSONForBinding] object toJSON();
};
diff --git a/chromium/third_party/blink/renderer/core/timing/performance_navigation.cc b/chromium/third_party/blink/renderer/core/timing/performance_navigation.cc
index 815fbd5ba74..2a7f72bb96f 100644
--- a/chromium/third_party/blink/renderer/core/timing/performance_navigation.cc
+++ b/chromium/third_party/blink/renderer/core/timing/performance_navigation.cc
@@ -40,7 +40,7 @@
namespace blink {
PerformanceNavigation::PerformanceNavigation(LocalFrame* frame)
- : DOMWindowClient(frame) {}
+ : ExecutionContextClient(frame) {}
uint8_t PerformanceNavigation::type() const {
if (!GetFrame())
@@ -85,7 +85,7 @@ ScriptValue PerformanceNavigation::toJSONForBinding(
void PerformanceNavigation::Trace(Visitor* visitor) {
ScriptWrappable::Trace(visitor);
- DOMWindowClient::Trace(visitor);
+ ExecutionContextClient::Trace(visitor);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/timing/performance_navigation.h b/chromium/third_party/blink/renderer/core/timing/performance_navigation.h
index 6a7367a39d8..f2ae0ce1212 100644
--- a/chromium/third_party/blink/renderer/core/timing/performance_navigation.h
+++ b/chromium/third_party/blink/renderer/core/timing/performance_navigation.h
@@ -44,7 +44,7 @@ class ScriptValue;
// Legacy support for NT1(https://www.w3.org/TR/navigation-timing/).
class CORE_EXPORT PerformanceNavigation final : public ScriptWrappable,
- public DOMWindowClient {
+ public ExecutionContextClient {
DEFINE_WRAPPERTYPEINFO();
USING_GARBAGE_COLLECTED_MIXIN(PerformanceNavigation);
diff --git a/chromium/third_party/blink/renderer/core/timing/performance_navigation_timing.cc b/chromium/third_party/blink/renderer/core/timing/performance_navigation_timing.cc
index 634f5451f58..0fd8f9f87dd 100644
--- a/chromium/third_party/blink/renderer/core/timing/performance_navigation_timing.cc
+++ b/chromium/third_party/blink/renderer/core/timing/performance_navigation_timing.cc
@@ -7,6 +7,7 @@
#include "third_party/blink/renderer/bindings/core/v8/v8_object_builder.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/document_timing.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/loader/document_load_timing.h"
#include "third_party/blink/renderer/core/loader/document_loader.h"
@@ -151,7 +152,7 @@ AtomicString PerformanceNavigationTiming::initiatorType() const {
bool PerformanceNavigationTiming::GetAllowRedirectDetails() const {
blink::ExecutionContext* context =
- GetFrame() ? GetFrame()->GetDocument()->ToExecutionContext() : nullptr;
+ GetFrame() ? GetFrame()->DomWindow() : nullptr;
const blink::SecurityOrigin* security_origin = nullptr;
if (context)
security_origin = context->GetSecurityOrigin();
diff --git a/chromium/third_party/blink/renderer/core/timing/performance_navigation_timing_test.cc b/chromium/third_party/blink/renderer/core/timing/performance_navigation_timing_test.cc
index 393622c91cc..101e22c606e 100644
--- a/chromium/third_party/blink/renderer/core/timing/performance_navigation_timing_test.cc
+++ b/chromium/third_party/blink/renderer/core/timing/performance_navigation_timing_test.cc
@@ -17,13 +17,13 @@ class PerformanceNavigationTimingTest : public PageTestBase {
};
TEST_F(PerformanceNavigationTimingTest, GetNavigationType) {
- GetPage().SetVisibilityState(PageVisibilityState::kHidden,
+ GetPage().SetVisibilityState(mojom::blink::PageVisibilityState::kHidden,
/*initial_state=*/false);
AtomicString returned_type =
GetNavigationType(kWebNavigationTypeBackForward, &GetDocument());
EXPECT_EQ(returned_type, "back_forward");
- GetPage().SetVisibilityState(PageVisibilityState::kVisible,
+ GetPage().SetVisibilityState(mojom::blink::PageVisibilityState::kVisible,
/*initial_state=*/false);
returned_type =
GetNavigationType(kWebNavigationTypeFormResubmitted, &GetDocument());
diff --git a/chromium/third_party/blink/renderer/core/timing/performance_observer.cc b/chromium/third_party/blink/renderer/core/timing/performance_observer.cc
index 2031f3cd699..67ab1a64478 100644
--- a/chromium/third_party/blink/renderer/core/timing/performance_observer.cc
+++ b/chromium/third_party/blink/renderer/core/timing/performance_observer.cc
@@ -102,9 +102,11 @@ void PerformanceObserver::observe(const PerformanceObserverInit* observer_init,
bool is_buffered = false;
if (observer_init->hasEntryTypes()) {
if (observer_init->hasType()) {
- exception_state.ThrowDOMException(DOMExceptionCode::kSyntaxError,
- "An observe() call must not include "
- "both entryTypes and type arguments.");
+ UseCounter::Count(GetExecutionContext(),
+ WebFeature::kPerformanceObserverTypeError);
+ exception_state.ThrowTypeError(
+ "An observe() call must not include "
+ "both entryTypes and type arguments.");
return;
}
if (type_ == PerformanceObserverType::kTypeObserver) {
@@ -134,7 +136,9 @@ void PerformanceObserver::observe(const PerformanceObserverInit* observer_init,
if (entry_types == PerformanceEntry::kInvalid) {
return;
}
- if (observer_init->buffered()) {
+ if (observer_init->buffered() || observer_init->hasDurationThreshold()) {
+ UseCounter::Count(GetExecutionContext(),
+ WebFeature::kPerformanceObserverEntryTypesAndBuffered);
String message =
"The PerformanceObserver does not support buffered flag with "
"the entryTypes argument.";
@@ -146,9 +150,11 @@ void PerformanceObserver::observe(const PerformanceObserverInit* observer_init,
filter_options_ = entry_types;
} else {
if (!observer_init->hasType()) {
- exception_state.ThrowDOMException(DOMExceptionCode::kSyntaxError,
- "An observe() call must include either "
- "entryTypes or type arguments.");
+ UseCounter::Count(GetExecutionContext(),
+ WebFeature::kPerformanceObserverTypeError);
+ exception_state.ThrowTypeError(
+ "An observe() call must include either "
+ "entryTypes or type arguments.");
return;
}
if (type_ == PerformanceObserverType::kEntryTypesObserver) {
@@ -179,6 +185,11 @@ void PerformanceObserver::observe(const PerformanceObserverInit* observer_init,
PerformanceEntry::StartTimeCompareLessThan);
is_buffered = true;
}
+ if (entry_type == PerformanceEntry::kEvent &&
+ observer_init->hasDurationThreshold()) {
+ // TODO(npm): should we do basic validation (like negative values etc?).
+ duration_threshold_ = std::max(16.0, observer_init->durationThreshold());
+ }
filter_options_ |= entry_type;
}
if (filter_options_ & PerformanceEntry::kLayoutShift) {
@@ -225,6 +236,12 @@ void PerformanceObserver::EnqueuePerformanceEntry(PerformanceEntry& entry) {
performance_->ActivateObserver(*this);
}
+bool PerformanceObserver::CanObserve(const PerformanceEntry& entry) const {
+ if (entry.EntryTypeEnum() != PerformanceEntry::kEvent)
+ return true;
+ return entry.duration() >= duration_threshold_;
+}
+
bool PerformanceObserver::HasPendingActivity() const {
return is_registered_;
}
diff --git a/chromium/third_party/blink/renderer/core/timing/performance_observer.h b/chromium/third_party/blink/renderer/core/timing/performance_observer.h
index 390dc410f61..14c3f6f2348 100644
--- a/chromium/third_party/blink/renderer/core/timing/performance_observer.h
+++ b/chromium/third_party/blink/renderer/core/timing/performance_observer.h
@@ -37,6 +37,7 @@ class CORE_EXPORT PerformanceObserver final
static PerformanceObserver* Create(ScriptState*,
V8PerformanceObserverCallback*);
static Vector<AtomicString> supportedEntryTypes(ScriptState*);
+ static constexpr DOMHighResTimeStamp kDefaultDurationThreshold = 104;
PerformanceObserver(ExecutionContext*,
Performance*,
@@ -47,6 +48,7 @@ class CORE_EXPORT PerformanceObserver final
PerformanceEntryVector takeRecords();
void EnqueuePerformanceEntry(PerformanceEntry&);
PerformanceEntryTypeMask FilterOptions() const { return filter_options_; }
+ bool CanObserve(const PerformanceEntry&) const;
// ScriptWrappable
bool HasPendingActivity() const final;
@@ -77,6 +79,11 @@ class CORE_EXPORT PerformanceObserver final
PerformanceEntryTypeMask filter_options_;
PerformanceObserverType type_;
bool is_registered_;
+ // PerformanceEventTiming entries with a duration that is as long as this
+ // threshold are regarded as long-latency events by the Event Timing API.
+ // Shorter-latency events are ignored. Default value can be overriden via a
+ // call to observe().
+ DOMHighResTimeStamp duration_threshold_ = kDefaultDurationThreshold;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/timing/performance_observer_init.idl b/chromium/third_party/blink/renderer/core/timing/performance_observer_init.idl
index 78a74f70a6d..f4169cd8cfa 100644
--- a/chromium/third_party/blink/renderer/core/timing/performance_observer_init.idl
+++ b/chromium/third_party/blink/renderer/core/timing/performance_observer_init.idl
@@ -8,4 +8,5 @@ dictionary PerformanceObserverInit {
sequence<DOMString> entryTypes;
DOMString type;
boolean buffered = false;
+ [RuntimeEnabled=EventTiming] DOMHighResTimeStamp durationThreshold;
};
diff --git a/chromium/third_party/blink/renderer/core/timing/performance_observer_test.cc b/chromium/third_party/blink/renderer/core/timing/performance_observer_test.cc
index cc57dcdf9be..78bdb38618c 100644
--- a/chromium/third_party/blink/renderer/core/timing/performance_observer_test.cc
+++ b/chromium/third_party/blink/renderer/core/timing/performance_observer_test.cc
@@ -74,7 +74,8 @@ TEST_F(PerformanceObserverTest, ObserveWithBufferedFlag) {
EXPECT_EQ(0, NumPerformanceEntries());
// add a layout-shift to performance so getEntries() returns it
- auto* entry = MakeGarbageCollected<LayoutShift>(0.0, 1234, true, 5678);
+ auto* entry = LayoutShift::Create(0.0, 1234, true, 5678,
+ LayoutShift::AttributionList());
base_->AddLayoutShiftBuffer(*entry);
// call observe with the buffered flag
diff --git a/chromium/third_party/blink/renderer/core/timing/performance_timing.cc b/chromium/third_party/blink/renderer/core/timing/performance_timing.cc
index a661f3f6e6c..7258c4089bd 100644
--- a/chromium/third_party/blink/renderer/core/timing/performance_timing.cc
+++ b/chromium/third_party/blink/renderer/core/timing/performance_timing.cc
@@ -63,7 +63,7 @@ static uint64_t ToIntegerMilliseconds(base::TimeDelta duration) {
}
PerformanceTiming::PerformanceTiming(LocalFrame* frame)
- : DOMWindowClient(frame) {}
+ : ExecutionContextClient(frame) {}
uint64_t PerformanceTiming::navigationStart() const {
DocumentLoadTiming* timing = GetDocumentLoadTiming();
@@ -655,7 +655,7 @@ uint64_t PerformanceTiming::MonotonicTimeToIntegerMilliseconds(
void PerformanceTiming::Trace(Visitor* visitor) {
ScriptWrappable::Trace(visitor);
- DOMWindowClient::Trace(visitor);
+ ExecutionContextClient::Trace(visitor);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/timing/performance_timing.h b/chromium/third_party/blink/renderer/core/timing/performance_timing.h
index 29ce0e4dd48..cd707b2b5e3 100644
--- a/chromium/third_party/blink/renderer/core/timing/performance_timing.h
+++ b/chromium/third_party/blink/renderer/core/timing/performance_timing.h
@@ -55,7 +55,7 @@ class ScriptValue;
// Legacy support for NT1(https://www.w3.org/TR/navigation-timing/).
class CORE_EXPORT PerformanceTiming final : public ScriptWrappable,
- public DOMWindowClient {
+ public ExecutionContextClient {
DEFINE_WRAPPERTYPEINFO();
USING_GARBAGE_COLLECTED_MIXIN(PerformanceTiming);
diff --git a/chromium/third_party/blink/renderer/core/timing/performance_user_timing.cc b/chromium/third_party/blink/renderer/core/timing/performance_user_timing.cc
index e7fe5a559f5..b1533768d44 100644
--- a/chromium/third_party/blink/renderer/core/timing/performance_user_timing.cc
+++ b/chromium/third_party/blink/renderer/core/timing/performance_user_timing.cc
@@ -60,15 +60,6 @@ static void ClearPeformanceEntries(PerformanceEntryMap& performance_entry_map,
performance_entry_map.erase(name);
}
-PerformanceMark* UserTiming::CreatePerformanceMark(
- ScriptState* script_state,
- const AtomicString& mark_name,
- PerformanceMarkOptions* mark_options,
- ExceptionState& exception_state) {
- return PerformanceMark::Create(script_state, mark_name, mark_options,
- exception_state);
-}
-
void UserTiming::AddMarkToPerformanceTimeline(PerformanceMark& mark) {
if (performance_->timing()) {
TRACE_EVENT_COPY_MARK1("blink.user_timing", mark.name().Utf8().c_str(),
diff --git a/chromium/third_party/blink/renderer/core/timing/performance_user_timing.h b/chromium/third_party/blink/renderer/core/timing/performance_user_timing.h
index 3c2377900b6..6a249d8ecd5 100644
--- a/chromium/third_party/blink/renderer/core/timing/performance_user_timing.h
+++ b/chromium/third_party/blink/renderer/core/timing/performance_user_timing.h
@@ -42,11 +42,6 @@ class UserTiming final : public GarbageCollected<UserTiming> {
public:
explicit UserTiming(Performance&);
- PerformanceMark* CreatePerformanceMark(ScriptState*,
- const AtomicString& mark_name,
- PerformanceMarkOptions*,
- ExceptionState&);
-
void ClearMarks(const AtomicString& mark_name);
PerformanceMeasure* Measure(ScriptState*,
diff --git a/chromium/third_party/blink/renderer/core/timing/profiler.cc b/chromium/third_party/blink/renderer/core/timing/profiler.cc
index 795eb9d7fe0..f9161ac7024 100644
--- a/chromium/third_party/blink/renderer/core/timing/profiler.cc
+++ b/chromium/third_party/blink/renderer/core/timing/profiler.cc
@@ -5,26 +5,24 @@
#include "third_party/blink/renderer/core/timing/profiler.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
+#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/timing/profiler_group.h"
namespace blink {
-Profiler::~Profiler() {
- Dispose();
-}
-
void Profiler::Trace(Visitor* visitor) {
visitor->Trace(profiler_group_);
+ visitor->Trace(script_state_);
ScriptWrappable::Trace(visitor);
}
-void Profiler::Dispose() {
+void Profiler::DisposeAsync() {
if (profiler_group_) {
- // It's safe to touch |profiler_group_| in Profiler's destructor as
+ // It's safe to touch |profiler_group_| in Profiler's pre-finalizer as
// |profiler_group_| is guaranteed to outlive the Profiler, if set. This is
// due to ProfilerGroup nulling out this field for all attached Profilers
// prior to destruction.
- profiler_group_->CancelProfiler(this);
+ profiler_group_->CancelProfilerAsync(script_state_, this);
profiler_group_ = nullptr;
}
}
diff --git a/chromium/third_party/blink/renderer/core/timing/profiler.h b/chromium/third_party/blink/renderer/core/timing/profiler.h
index b9de2f198c1..e35646ba1d4 100644
--- a/chromium/third_party/blink/renderer/core/timing/profiler.h
+++ b/chromium/third_party/blink/renderer/core/timing/profiler.h
@@ -12,6 +12,7 @@
#include "third_party/blink/renderer/core/timing/profiler_group.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
#include "third_party/blink/renderer/platform/heap/member.h"
+#include "third_party/blink/renderer/platform/heap/thread_state.h"
#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
#include "third_party/blink/renderer/platform/wtf/forward.h"
@@ -24,24 +25,27 @@ class ScriptState;
// isolate until stopped.
class CORE_EXPORT Profiler final : public ScriptWrappable {
DEFINE_WRAPPERTYPEINFO();
+ USING_PRE_FINALIZER(Profiler, DisposeAsync);
public:
Profiler(ProfilerGroup* profiler_group,
+ ScriptState* script_state,
const String& profiler_id,
int target_sample_rate,
scoped_refptr<const SecurityOrigin> source_origin,
base::TimeTicks time_origin)
: profiler_group_(profiler_group),
+ script_state_(script_state),
profiler_id_(profiler_id),
target_sample_rate_(target_sample_rate),
source_origin_(source_origin),
time_origin_(time_origin) {}
- ~Profiler() override;
+ ~Profiler() override = default;
void Trace(Visitor* visitor) override;
- void Dispose();
+ void DisposeAsync();
String ProfilerId() const { return profiler_id_; }
int TargetSampleRate() const { return target_sample_rate_; }
@@ -52,8 +56,11 @@ class CORE_EXPORT Profiler final : public ScriptWrappable {
bool stopped() const { return !profiler_group_; }
ScriptPromise stop(ScriptState*);
+ void RemovedFromProfilerGroup() { profiler_group_ = nullptr; }
+
private:
Member<ProfilerGroup> profiler_group_;
+ Member<ScriptState> script_state_;
const String profiler_id_;
const int target_sample_rate_;
const scoped_refptr<const SecurityOrigin> source_origin_;
diff --git a/chromium/third_party/blink/renderer/core/timing/profiler_group.cc b/chromium/third_party/blink/renderer/core/timing/profiler_group.cc
index 98fe86e0a4a..f17a821d650 100644
--- a/chromium/third_party/blink/renderer/core/timing/profiler_group.cc
+++ b/chromium/third_party/blink/renderer/core/timing/profiler_group.cc
@@ -6,6 +6,7 @@
#include "base/time/time.h"
#include "build/build_config.h"
+#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/renderer/bindings/core/v8/profiler_trace_builder.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_profiler_init_options.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_profiler_trace.h"
@@ -15,6 +16,7 @@
#include "third_party/blink/renderer/platform/bindings/script_state.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
+#include "third_party/blink/renderer/platform/wtf/functional.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
#include "v8/include/v8-profiler.h"
#include "v8/include/v8.h"
@@ -107,9 +109,9 @@ Profiler* ProfilerGroup::CreateProfiler(ScriptState* script_state,
effective_sample_interval_ms % kBaseSampleIntervalMs);
}
- auto* profiler = MakeGarbageCollected<Profiler>(this, profiler_id,
- effective_sample_interval_ms,
- source_origin, time_origin);
+ auto* profiler = MakeGarbageCollected<Profiler>(
+ this, script_state, profiler_id, effective_sample_interval_ms,
+ source_origin, time_origin);
profilers_.insert(profiler);
num_active_profilers_++;
@@ -125,7 +127,8 @@ ProfilerGroup::~ProfilerGroup() {
void ProfilerGroup::WillBeDestroyed() {
for (auto& profiler : profilers_) {
DCHECK(profiler);
- profiler->Dispose();
+ CancelProfiler(profiler);
+ profiler->RemovedFromProfilerGroup();
DCHECK(profiler->stopped());
}
@@ -183,11 +186,24 @@ void ProfilerGroup::StopProfiler(ScriptState* script_state,
void ProfilerGroup::CancelProfiler(Profiler* profiler) {
DCHECK(cpu_profiler_);
DCHECK(!profiler->stopped());
+ CancelProfilerImpl(profiler->ProfilerId());
+}
+
+void ProfilerGroup::CancelProfilerAsync(ScriptState* script_state,
+ Profiler* profiler) {
+ DCHECK(cpu_profiler_);
+ DCHECK(!profiler->stopped());
+ ExecutionContext::From(script_state)
+ ->GetTaskRunner(TaskType::kInternalDefault)
+ ->PostTask(FROM_HERE,
+ WTF::Bind(&ProfilerGroup::CancelProfilerImpl,
+ WrapPersistent(this), profiler->ProfilerId()));
+}
+void ProfilerGroup::CancelProfilerImpl(String profiler_id) {
v8::HandleScope scope(isolate_);
- v8::Local<v8::String> profiler_id =
- V8String(isolate_, profiler->ProfilerId());
- auto* profile = cpu_profiler_->StopProfiling(profiler_id);
+ v8::Local<v8::String> v8_profiler_id = V8String(isolate_, profiler_id);
+ auto* profile = cpu_profiler_->StopProfiling(v8_profiler_id);
profile->Delete();
diff --git a/chromium/third_party/blink/renderer/core/timing/profiler_group.h b/chromium/third_party/blink/renderer/core/timing/profiler_group.h
index 93374ec33bd..7f9cc217aae 100644
--- a/chromium/third_party/blink/renderer/core/timing/profiler_group.h
+++ b/chromium/third_party/blink/renderer/core/timing/profiler_group.h
@@ -53,6 +53,10 @@ class CORE_EXPORT ProfilerGroup
// Cancels a profiler, discarding its associated trace.
void CancelProfiler(Profiler*);
+ // Asynchronously cancels a profiler. Invoked on Profiler descrution.
+ void CancelProfilerAsync(ScriptState*, Profiler*);
+ // Internal implementation of cancel.
+ void CancelProfilerImpl(String profiler_id);
// Generates an unused string identifier to use for a new profiling session.
String NextProfilerId();
diff --git a/chromium/third_party/blink/renderer/core/timing/window_performance.cc b/chromium/third_party/blink/renderer/core/timing/window_performance.cc
index 3725580274d..6dc40bff1f7 100644
--- a/chromium/third_party/blink/renderer/core/timing/window_performance.cc
+++ b/chromium/third_party/blink/renderer/core/timing/window_performance.cc
@@ -46,6 +46,7 @@
#include "third_party/blink/renderer/core/timing/layout_shift.h"
#include "third_party/blink/renderer/core/timing/performance_element_timing.h"
#include "third_party/blink/renderer/core/timing/performance_event_timing.h"
+#include "third_party/blink/renderer/core/timing/performance_observer.h"
#include "third_party/blink/renderer/core/timing/performance_timing.h"
#include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_timing_info.h"
@@ -60,11 +61,6 @@ namespace blink {
namespace {
-// Events taking longer than this threshold to finish being processed are
-// regarded as long-latency events by event-timing. Shorter-latency events are
-// ignored to reduce performance impact.
-constexpr int kEventTimingDurationThresholdInMs = 104;
-
String GetFrameAttribute(HTMLFrameOwnerElement* frame_owner,
const QualifiedName& attr_name,
bool truncate) {
@@ -79,17 +75,17 @@ String GetFrameAttribute(HTMLFrameOwnerElement* frame_owner,
AtomicString GetFrameOwnerType(HTMLFrameOwnerElement* frame_owner) {
switch (frame_owner->OwnerType()) {
- case FrameOwnerElementType::kNone:
+ case mojom::blink::FrameOwnerElementType::kNone:
return "window";
- case FrameOwnerElementType::kIframe:
+ case mojom::blink::FrameOwnerElementType::kIframe:
return "iframe";
- case FrameOwnerElementType::kObject:
+ case mojom::blink::FrameOwnerElementType::kObject:
return "object";
- case FrameOwnerElementType::kEmbed:
+ case mojom::blink::FrameOwnerElementType::kEmbed:
return "embed";
- case FrameOwnerElementType::kFrame:
+ case mojom::blink::FrameOwnerElementType::kFrame:
return "frame";
- case FrameOwnerElementType::kPortal:
+ case mojom::blink::FrameOwnerElementType::kPortal:
return "portal";
}
NOTREACHED();
@@ -98,7 +94,7 @@ AtomicString GetFrameOwnerType(HTMLFrameOwnerElement* frame_owner) {
String GetFrameSrc(HTMLFrameOwnerElement* frame_owner) {
switch (frame_owner->OwnerType()) {
- case FrameOwnerElementType::kObject:
+ case mojom::blink::FrameOwnerElementType::kObject:
return GetFrameAttribute(frame_owner, html_names::kDataAttr, false);
default:
return GetFrameAttribute(frame_owner, html_names::kSrcAttr, false);
@@ -158,7 +154,7 @@ WindowPerformance::WindowPerformance(LocalDOMWindow* window)
: Performance(
ToTimeOrigin(window),
window->document()->GetTaskRunner(TaskType::kPerformanceTimeline)),
- DOMWindowClient(window) {
+ ExecutionContextClient(window) {
DCHECK(GetFrame());
DCHECK(GetFrame()->GetPerformanceMonitor());
GetFrame()->GetPerformanceMonitor()->Subscribe(
@@ -170,7 +166,7 @@ WindowPerformance::~WindowPerformance() = default;
ExecutionContext* WindowPerformance::GetExecutionContext() const {
if (!GetFrame())
return nullptr;
- return GetFrame()->GetDocument()->ToExecutionContext();
+ return GetFrame()->DomWindow();
}
PerformanceTiming* WindowPerformance::timing() const {
@@ -227,11 +223,12 @@ void WindowPerformance::BuildJSONValue(V8ObjectBuilder& builder) const {
void WindowPerformance::Trace(Visitor* visitor) {
visitor->Trace(event_timings_);
visitor->Trace(first_pointer_down_event_timing_);
+ visitor->Trace(event_counts_);
visitor->Trace(navigation_);
visitor->Trace(timing_);
Performance::Trace(visitor);
PerformanceMonitor::Client::Trace(visitor);
- DOMWindowClient::Trace(visitor);
+ ExecutionContextClient::Trace(visitor);
}
static bool CanAccessOrigin(Frame* frame1, Frame* frame2) {
@@ -259,15 +256,15 @@ std::pair<AtomicString, DOMWindow*> WindowPerformance::SanitizedAttribution(
return std::make_pair(kAmbiguousAttribution, nullptr);
}
- Document* document = Document::DynamicFrom(task_context);
- if (!document || !document->GetFrame()) {
+ LocalDOMWindow* window = DynamicTo<LocalDOMWindow>(task_context);
+ if (!window || !window->GetFrame()) {
// Unable to attribute as no script was involved.
DEFINE_STATIC_LOCAL(const AtomicString, kUnknownAttribution, ("unknown"));
return std::make_pair(kUnknownAttribution, nullptr);
}
// Exactly one culprit location, attribute based on origin boundary.
- Frame* culprit_frame = document->GetFrame();
+ Frame* culprit_frame = window->GetFrame();
DCHECK(culprit_frame);
if (CanAccessOrigin(observer_frame, culprit_frame)) {
// From accessible frames or same origin, return culprit location URL.
@@ -333,7 +330,8 @@ void WindowPerformance::RegisterEventTiming(const AtomicString& event_type,
base::TimeTicks start_time,
base::TimeTicks processing_start,
base::TimeTicks processing_end,
- bool cancelable) {
+ bool cancelable,
+ Node* target) {
// |start_time| could be null in some tests that inject input.
DCHECK(!processing_start.is_null());
DCHECK(!processing_end.is_null());
@@ -341,10 +339,13 @@ void WindowPerformance::RegisterEventTiming(const AtomicString& event_type,
if (!GetFrame())
return;
+ if (!event_counts_)
+ event_counts_ = MakeGarbageCollected<EventCounts>();
+ event_counts_->Add(event_type);
PerformanceEventTiming* entry = PerformanceEventTiming::Create(
event_type, MonotonicTimeToDOMHighResTimeStamp(start_time),
MonotonicTimeToDOMHighResTimeStamp(processing_start),
- MonotonicTimeToDOMHighResTimeStamp(processing_end), cancelable);
+ MonotonicTimeToDOMHighResTimeStamp(processing_end), cancelable, target);
event_timings_.push_back(entry);
// Only queue a swap promise when |event_timings_| was empty. All of the
// elements in |event_timings_| will be processed in a single call of
@@ -378,8 +379,7 @@ void WindowPerformance::ReportEventTimings(WebSwapResult result,
PerformanceEventTiming::CreateFirstInputTiming(entry));
}
}
- if (duration_in_ms < kEventTimingDurationThresholdInMs ||
- !event_timing_enabled)
+ if (!event_timing_enabled)
continue;
if (HasObserverFor(PerformanceEntry::kEvent)) {
@@ -388,8 +388,13 @@ void WindowPerformance::ReportEventTimings(WebSwapResult result,
NotifyObserversOfEntry(*entry);
}
- if (!IsEventTimingBufferFull())
+ // Only buffer really slow events to keep memory usage low.
+ // TODO(npm): is 104 a reasonable buffering threshold or should it be
+ // relaxed?
+ if (duration_in_ms >= PerformanceObserver::kDefaultDurationThreshold &&
+ !IsEventTimingBufferFull()) {
AddEventTimingBuffer(*entry);
+ }
}
event_timings_.clear();
}
@@ -421,6 +426,8 @@ void WindowPerformance::DispatchFirstInputTiming(
if (HasObserverFor(PerformanceEntry::kFirstInput)) {
UseCounter::Count(GetExecutionContext(),
WebFeature::kEventTimingExplicitlyRequested);
+ UseCounter::Count(GetExecutionContext(),
+ WebFeature::kEventTimingFirstInputExplicitlyRequested);
NotifyObserversOfEntry(*entry);
}
@@ -428,18 +435,19 @@ void WindowPerformance::DispatchFirstInputTiming(
first_input_timing_ = entry;
}
-void WindowPerformance::AddLayoutShiftValue(double value,
- bool input_detected,
- base::TimeTicks input_timestamp) {
- auto* entry = MakeGarbageCollected<LayoutShift>(
- now(), value, input_detected,
- input_detected ? MonotonicTimeToDOMHighResTimeStamp(input_timestamp)
- : 0.0);
+void WindowPerformance::AddLayoutShiftEntry(LayoutShift* entry) {
if (HasObserverFor(PerformanceEntry::kLayoutShift))
NotifyObserversOfEntry(*entry);
AddLayoutShiftBuffer(*entry);
}
+EventCounts* WindowPerformance::eventCounts() {
+ DCHECK(RuntimeEnabledFeatures::EventTimingEnabled(GetExecutionContext()));
+ if (!event_counts_)
+ event_counts_ = MakeGarbageCollected<EventCounts>();
+ return event_counts_;
+}
+
void WindowPerformance::OnLargestContentfulPaintUpdated(
base::TimeTicks paint_time,
uint64_t paint_size,
@@ -447,13 +455,13 @@ void WindowPerformance::OnLargestContentfulPaintUpdated(
const AtomicString& id,
const String& url,
Element* element) {
- double render_timestamp = MonotonicTimeToDOMHighResTimeStamp(paint_time);
- double load_timestamp = MonotonicTimeToDOMHighResTimeStamp(load_time);
- double start_timestamp =
- render_timestamp != 0.0 ? render_timestamp : load_timestamp;
+ base::TimeDelta render_timestamp = MonotonicTimeToTimeDelta(paint_time);
+ base::TimeDelta load_timestamp = MonotonicTimeToTimeDelta(load_time);
+ base::TimeDelta start_timestamp =
+ render_timestamp.is_zero() ? load_timestamp : render_timestamp;
auto* entry = MakeGarbageCollected<LargestContentfulPaint>(
- start_timestamp, render_timestamp, paint_size, load_timestamp, id, url,
- element);
+ start_timestamp.InMillisecondsF(), render_timestamp, paint_size,
+ load_timestamp, id, url, element);
if (HasObserverFor(PerformanceEntry::kLargestContentfulPaint))
NotifyObserversOfEntry(*entry);
AddLargestContentfulPaint(entry);
diff --git a/chromium/third_party/blink/renderer/core/timing/window_performance.h b/chromium/third_party/blink/renderer/core/timing/window_performance.h
index 891cab42ced..6c79d80650c 100644
--- a/chromium/third_party/blink/renderer/core/timing/window_performance.h
+++ b/chromium/third_party/blink/renderer/core/timing/window_performance.h
@@ -36,6 +36,7 @@
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.h"
#include "third_party/blink/renderer/core/frame/performance_monitor.h"
+#include "third_party/blink/renderer/core/timing/event_counts.h"
#include "third_party/blink/renderer/core/timing/memory_info.h"
#include "third_party/blink/renderer/core/timing/performance.h"
#include "third_party/blink/renderer/core/timing/performance_navigation.h"
@@ -46,7 +47,7 @@ namespace blink {
class CORE_EXPORT WindowPerformance final : public Performance,
public PerformanceMonitor::Client,
- public DOMWindowClient {
+ public ExecutionContextClient {
USING_GARBAGE_COLLECTED_MIXIN(WindowPerformance);
friend class WindowPerformanceTest;
@@ -61,6 +62,8 @@ class CORE_EXPORT WindowPerformance final : public Performance,
MemoryInfo* memory() const override;
+ EventCounts* eventCounts() override;
+
bool FirstInputDetected() const { return !!first_input_timing_; }
// This method creates a PerformanceEventTiming and if needed creates a swap
@@ -70,7 +73,8 @@ class CORE_EXPORT WindowPerformance final : public Performance,
base::TimeTicks start_time,
base::TimeTicks processing_start,
base::TimeTicks processing_end,
- bool cancelable);
+ bool cancelable,
+ Node*);
void AddElementTiming(const AtomicString& name,
const String& url,
@@ -82,9 +86,7 @@ class CORE_EXPORT WindowPerformance final : public Performance,
const AtomicString& id,
Element*);
- void AddLayoutShiftValue(double value,
- bool input_detected,
- base::TimeTicks input_timestamp);
+ void AddLayoutShiftEntry(LayoutShift*);
void OnLargestContentfulPaintUpdated(base::TimeTicks paint_time,
uint64_t paint_size,
@@ -122,6 +124,7 @@ class CORE_EXPORT WindowPerformance final : public Performance,
// |duration| has not been resolved.
HeapVector<Member<PerformanceEventTiming>> event_timings_;
Member<PerformanceEventTiming> first_pointer_down_event_timing_;
+ Member<EventCounts> event_counts_;
mutable Member<PerformanceNavigation> navigation_;
mutable Member<PerformanceTiming> timing_;
};
diff --git a/chromium/third_party/blink/renderer/core/timing/window_performance_test.cc b/chromium/third_party/blink/renderer/core/timing/window_performance_test.cc
index 6c08be70d09..7e0dcd1b1d6 100644
--- a/chromium/third_party/blink/renderer/core/timing/window_performance_test.cc
+++ b/chromium/third_party/blink/renderer/core/timing/window_performance_test.cc
@@ -55,7 +55,7 @@ class WindowPerformanceTest : public testing::Test {
void SimulateDidProcessLongTask() {
auto* monitor = GetFrame()->GetPerformanceMonitor();
- monitor->WillExecuteScript(GetDocument()->ToExecutionContext());
+ monitor->WillExecuteScript(GetWindow());
monitor->DidExecuteScript();
monitor->DidProcessTask(
base::TimeTicks(), base::TimeTicks() + base::TimeDelta::FromSeconds(1));
@@ -67,7 +67,7 @@ class WindowPerformanceTest : public testing::Test {
LocalFrame* GetFrame() const { return &page_holder_->GetFrame(); }
- Document* GetDocument() const { return &page_holder_->GetDocument(); }
+ LocalDOMWindow* GetWindow() const { return GetFrame()->DomWindow(); }
String SanitizedAttribution(ExecutionContext* context,
bool has_multiple_contexts,
@@ -84,10 +84,8 @@ class WindowPerformanceTest : public testing::Test {
LocalDOMWindow* window = LocalDOMWindow::From(GetScriptState());
performance_ = DOMWindowPerformance::performance(*window);
- unified_clock_ = std::make_unique<Performance::UnifiedClock>(
- test_task_runner_->GetMockClock(),
- test_task_runner_->GetMockTickClock());
- performance_->SetClocksForTesting(unified_clock_.get());
+ performance_->SetClocksForTesting(test_task_runner_->GetMockClock(),
+ test_task_runner_->GetMockTickClock());
performance_->time_origin_ = GetTimeOrigin();
}
@@ -98,7 +96,6 @@ class WindowPerformanceTest : public testing::Test {
Persistent<WindowPerformance> performance_;
std::unique_ptr<DummyPageHolder> page_holder_;
scoped_refptr<base::TestMockTimeTaskRunner> test_task_runner_;
- std::unique_ptr<Performance::UnifiedClock> unified_clock_;
};
TEST_F(WindowPerformanceTest, LongTaskObserverInstrumentation) {
@@ -120,13 +117,11 @@ TEST_F(WindowPerformanceTest, SanitizedLongTaskName) {
EXPECT_EQ("unknown", SanitizedAttribution(nullptr, false, GetFrame()));
// Attribute for same context (and same origin).
- EXPECT_EQ("self", SanitizedAttribution(GetDocument()->ToExecutionContext(),
- false, GetFrame()));
+ EXPECT_EQ("self", SanitizedAttribution(GetWindow(), false, GetFrame()));
// Unable to attribute, when multiple script execution contents are involved.
EXPECT_EQ("multiple-contexts",
- SanitizedAttribution(GetDocument()->ToExecutionContext(), true,
- GetFrame()));
+ SanitizedAttribution(GetWindow(), true, GetFrame()));
}
TEST_F(WindowPerformanceTest, SanitizedLongTaskName_CrossOrigin) {
@@ -138,10 +133,9 @@ TEST_F(WindowPerformanceTest, SanitizedLongTaskName_CrossOrigin) {
EXPECT_EQ("unknown", SanitizedAttribution(nullptr, false, GetFrame()));
// Attribute for same context (and same origin).
- EXPECT_EQ(
- "cross-origin-unreachable",
- SanitizedAttribution(another_page.GetDocument().ToExecutionContext(),
- false, GetFrame()));
+ EXPECT_EQ("cross-origin-unreachable",
+ SanitizedAttribution(another_page.GetFrame().DomWindow(), false,
+ GetFrame()));
}
// https://crbug.com/706798: Checks that after navigation that have replaced the
@@ -183,8 +177,7 @@ TEST(PerformanceLifetimeTest, SurviveContextSwitch) {
page_holder->GetFrame().DomWindow()->InstallNewDocument(
DocumentInit::Create()
.WithDocumentLoader(document_loader)
- .WithTypeFrom("text/html"),
- false);
+ .WithTypeFrom("text/html"));
EXPECT_EQ(perf, DOMWindowPerformance::performance(
*page_holder->GetFrame().DomWindow()));
@@ -239,7 +232,7 @@ TEST_F(WindowPerformanceTest, EventTimingEntryBuffering) {
base::TimeTicks processing_end =
GetTimeOrigin() + base::TimeDelta::FromSecondsD(3.8);
performance_->RegisterEventTiming("click", start_time, processing_start,
- processing_end, false);
+ processing_end, false, nullptr);
base::TimeTicks swap_time =
GetTimeOrigin() + base::TimeDelta::FromSecondsD(6.0);
SimulateSwapPromise(swap_time);
@@ -251,7 +244,7 @@ TEST_F(WindowPerformanceTest, EventTimingEntryBuffering) {
->GetTiming()
.MarkLoadEventStart();
performance_->RegisterEventTiming("click", start_time, processing_start,
- processing_end, true);
+ processing_end, true, nullptr);
SimulateSwapPromise(swap_time);
EXPECT_EQ(2u, performance_->getBufferedEntriesByType("event").size());
@@ -259,7 +252,7 @@ TEST_F(WindowPerformanceTest, EventTimingEntryBuffering) {
GetFrame()->DetachDocument();
EXPECT_FALSE(page_holder_->GetFrame().Loader().GetDocumentLoader());
performance_->RegisterEventTiming("click", start_time, processing_start,
- processing_end, false);
+ processing_end, false, nullptr);
SimulateSwapPromise(swap_time);
EXPECT_EQ(3u, performance_->getBufferedEntriesByType("event").size());
}
@@ -273,12 +266,12 @@ TEST_F(WindowPerformanceTest, Expose100MsEvents) {
base::TimeTicks processing_end =
processing_start + base::TimeDelta::FromMilliseconds(10);
performance_->RegisterEventTiming("mousedown", start_time, processing_start,
- processing_end, false);
+ processing_end, false, nullptr);
base::TimeTicks start_time2 =
start_time + base::TimeDelta::FromMicroseconds(200);
performance_->RegisterEventTiming("click", start_time2, processing_start,
- processing_end, false);
+ processing_end, false, nullptr);
// The swap time is 100.1 ms after |start_time| but only 99.9 ms after
// |start_time2|.
@@ -301,24 +294,24 @@ TEST_F(WindowPerformanceTest, EventTimingDuration) {
base::TimeTicks processing_end =
GetTimeOrigin() + base::TimeDelta::FromMilliseconds(1002);
performance_->RegisterEventTiming("click", start_time, processing_start,
- processing_end, false);
+ processing_end, false, nullptr);
base::TimeTicks short_swap_time =
GetTimeOrigin() + base::TimeDelta::FromMilliseconds(1003);
SimulateSwapPromise(short_swap_time);
EXPECT_EQ(0u, performance_->getBufferedEntriesByType("event").size());
performance_->RegisterEventTiming("click", start_time, processing_start,
- processing_end, true);
+ processing_end, true, nullptr);
base::TimeTicks long_swap_time =
GetTimeOrigin() + base::TimeDelta::FromMilliseconds(2000);
SimulateSwapPromise(long_swap_time);
EXPECT_EQ(1u, performance_->getBufferedEntriesByType("event").size());
performance_->RegisterEventTiming("click", start_time, processing_start,
- processing_end, true);
+ processing_end, true, nullptr);
SimulateSwapPromise(short_swap_time);
performance_->RegisterEventTiming("click", start_time, processing_start,
- processing_end, false);
+ processing_end, false, nullptr);
SimulateSwapPromise(long_swap_time);
EXPECT_EQ(2u, performance_->getBufferedEntriesByType("event").size());
}
@@ -335,7 +328,7 @@ TEST_F(WindowPerformanceTest, MultipleEventsSameSwap) {
base::TimeTicks processing_end =
start_time + base::TimeDelta::FromMilliseconds(200);
performance_->RegisterEventTiming("click", start_time, processing_start,
- processing_end, false);
+ processing_end, false, nullptr);
EXPECT_EQ(0u, performance_->getBufferedEntriesByType("event").size());
}
base::TimeTicks swap_time =
@@ -351,14 +344,13 @@ TEST_F(WindowPerformanceTest, FirstInput) {
bool should_report;
} inputs[] = {{"click", true}, {"keydown", true},
{"keypress", false}, {"pointerdown", false},
- {"mousedown", true}, {"mousemove", false},
- {"mouseover", false}};
+ {"mousedown", true}, {"mouseover", false}};
for (const auto& input : inputs) {
// first-input does not have a |duration| threshold so use close values.
performance_->RegisterEventTiming(
input.event_type, GetTimeOrigin(),
GetTimeOrigin() + base::TimeDelta::FromMilliseconds(1),
- GetTimeOrigin() + base::TimeDelta::FromMilliseconds(2), false);
+ GetTimeOrigin() + base::TimeDelta::FromMilliseconds(2), false, nullptr);
SimulateSwapPromise(GetTimeOrigin() + base::TimeDelta::FromMilliseconds(3));
PerformanceEntryVector firstInputs =
performance_->getEntriesByType("first-input");
@@ -371,12 +363,12 @@ TEST_F(WindowPerformanceTest, FirstInput) {
// Test that the 'firstInput' is populated after some irrelevant events are
// ignored.
TEST_F(WindowPerformanceTest, FirstInputAfterIgnored) {
- AtomicString several_events[] = {"mousemove", "mouseover", "mousedown"};
+ AtomicString several_events[] = {"mouseover", "mousedown", "pointerup"};
for (const auto& event : several_events) {
performance_->RegisterEventTiming(
event, GetTimeOrigin(),
GetTimeOrigin() + base::TimeDelta::FromMilliseconds(1),
- GetTimeOrigin() + base::TimeDelta::FromMilliseconds(2), false);
+ GetTimeOrigin() + base::TimeDelta::FromMilliseconds(2), false, nullptr);
}
SimulateSwapPromise(GetTimeOrigin() + base::TimeDelta::FromMilliseconds(3));
ASSERT_EQ(1u, performance_->getEntriesByType("first-input").size());
@@ -394,11 +386,11 @@ TEST_F(WindowPerformanceTest, FirstPointerUp) {
base::TimeTicks swap_time =
GetTimeOrigin() + base::TimeDelta::FromMilliseconds(3);
performance_->RegisterEventTiming("pointerdown", start_time, processing_start,
- processing_end, false);
+ processing_end, false, nullptr);
SimulateSwapPromise(swap_time);
EXPECT_EQ(0u, performance_->getEntriesByType("first-input").size());
performance_->RegisterEventTiming("pointerup", start_time, processing_start,
- processing_end, false);
+ processing_end, false, nullptr);
SimulateSwapPromise(swap_time);
EXPECT_EQ(1u, performance_->getEntriesByType("first-input").size());
// The name of the entry should be "pointerdown".
diff --git a/chromium/third_party/blink/renderer/core/trustedtypes/trusted_html.idl b/chromium/third_party/blink/renderer/core/trustedtypes/trusted_html.idl
index 6db167e3b1d..7eabd4d4ddd 100644
--- a/chromium/third_party/blink/renderer/core/trustedtypes/trusted_html.idl
+++ b/chromium/third_party/blink/renderer/core/trustedtypes/trusted_html.idl
@@ -8,8 +8,7 @@ typedef [StringContext=TrustedHTML] DOMString HTMLString;
[
Exposed=Window,
- RuntimeEnabled=TrustedDOMTypes,
- SecureContext
+ RuntimeEnabled=TrustedDOMTypes
] interface TrustedHTML {
stringifier;
};
diff --git a/chromium/third_party/blink/renderer/core/trustedtypes/trusted_script.idl b/chromium/third_party/blink/renderer/core/trustedtypes/trusted_script.idl
index 34f29afa302..081bb4b58f6 100644
--- a/chromium/third_party/blink/renderer/core/trustedtypes/trusted_script.idl
+++ b/chromium/third_party/blink/renderer/core/trustedtypes/trusted_script.idl
@@ -8,8 +8,7 @@ typedef [StringContext=TrustedScript] DOMString ScriptString;
[
Exposed=Window,
- RuntimeEnabled=TrustedDOMTypes,
- SecureContext
+ RuntimeEnabled=TrustedDOMTypes
] interface TrustedScript {
stringifier;
};
diff --git a/chromium/third_party/blink/renderer/core/trustedtypes/trusted_script_url.idl b/chromium/third_party/blink/renderer/core/trustedtypes/trusted_script_url.idl
index 84695e2cfa6..711b491833f 100644
--- a/chromium/third_party/blink/renderer/core/trustedtypes/trusted_script_url.idl
+++ b/chromium/third_party/blink/renderer/core/trustedtypes/trusted_script_url.idl
@@ -8,8 +8,7 @@ typedef [StringContext=TrustedScriptURL] USVString ScriptURLString;
[
Exposed=Window,
- RuntimeEnabled=TrustedDOMTypes,
- SecureContext
+ RuntimeEnabled=TrustedDOMTypes
] interface TrustedScriptURL {
stringifier;
};
diff --git a/chromium/third_party/blink/renderer/core/trustedtypes/trusted_type_policy.idl b/chromium/third_party/blink/renderer/core/trustedtypes/trusted_type_policy.idl
index 32798ed1e83..22b48f331ba 100644
--- a/chromium/third_party/blink/renderer/core/trustedtypes/trusted_type_policy.idl
+++ b/chromium/third_party/blink/renderer/core/trustedtypes/trusted_type_policy.idl
@@ -8,8 +8,7 @@ typedef (DOMString or TrustedHTML or TrustedScript or TrustedScriptURL) TrustedS
[
Exposed=Window,
- RuntimeEnabled=TrustedDOMTypes,
- SecureContext
+ RuntimeEnabled=TrustedDOMTypes
] interface TrustedTypePolicy {
readonly attribute DOMString name;
[CallWith=ScriptState, RaisesException] TrustedHTML createHTML(DOMString input, any... args);
diff --git a/chromium/third_party/blink/renderer/core/trustedtypes/trusted_type_policy_factory.cc b/chromium/third_party/blink/renderer/core/trustedtypes/trusted_type_policy_factory.cc
index aa29f891a4f..4935a61fe88 100644
--- a/chromium/third_party/blink/renderer/core/trustedtypes/trusted_type_policy_factory.cc
+++ b/chromium/third_party/blink/renderer/core/trustedtypes/trusted_type_policy_factory.cc
@@ -54,12 +54,14 @@ TrustedTypePolicy* TrustedTypePolicyFactory::createPolicy(
exception_state.ThrowTypeError(message);
return nullptr;
}
-
+ UseCounter::Count(GetExecutionContext(),
+ WebFeature::kTrustedTypesPolicyCreated);
if (policy_name == "default") {
DCHECK(!policy_map_.Contains("default"));
UseCounter::Count(GetExecutionContext(),
- WebFeature::kTrustedTypesDefaultPolicyUsed);
+ WebFeature::kTrustedTypesDefaultPolicyCreated);
}
+
auto* policy = MakeGarbageCollected<TrustedTypePolicy>(
policy_name, const_cast<TrustedTypePolicyOptions*>(policy_options));
policy_map_.insert(policy_name, policy);
diff --git a/chromium/third_party/blink/renderer/core/trustedtypes/trusted_type_policy_factory.idl b/chromium/third_party/blink/renderer/core/trustedtypes/trusted_type_policy_factory.idl
index 02fbefc46ff..5a9cdc32adf 100644
--- a/chromium/third_party/blink/renderer/core/trustedtypes/trusted_type_policy_factory.idl
+++ b/chromium/third_party/blink/renderer/core/trustedtypes/trusted_type_policy_factory.idl
@@ -6,8 +6,7 @@
[
Exposed=(Window, Worker),
- RuntimeEnabled=TrustedDOMTypes,
- SecureContext
+ RuntimeEnabled=TrustedDOMTypes
] interface TrustedTypePolicyFactory {
[RaisesException] TrustedTypePolicy createPolicy(DOMString policyName, TrustedTypePolicyOptions policyOptions);
readonly attribute TrustedTypePolicy defaultPolicy;
diff --git a/chromium/third_party/blink/renderer/core/trustedtypes/trusted_types_util.cc b/chromium/third_party/blink/renderer/core/trustedtypes/trusted_types_util.cc
index 23103e70b68..0858ac2a1f1 100644
--- a/chromium/third_party/blink/renderer/core/trustedtypes/trusted_types_util.cc
+++ b/chromium/third_party/blink/renderer/core/trustedtypes/trusted_types_util.cc
@@ -10,9 +10,8 @@
#include "third_party/blink/renderer/bindings/core/v8/string_or_trusted_html_or_trusted_script_or_trusted_script_url.h"
#include "third_party/blink/renderer/bindings/core/v8/string_or_trusted_script.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
-#include "third_party/blink/renderer/bindings/core/v8/window_proxy_manager.h"
+#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/frame/csp/content_security_policy.h"
-#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/script/script_element_base.h"
#include "third_party/blink/renderer/core/trustedtypes/trusted_html.h"
#include "third_party/blink/renderer/core/trustedtypes/trusted_script.h"
@@ -178,18 +177,16 @@ TrustedTypePolicy* GetDefaultPolicy(const ExecutionContext* execution_context) {
// for each case.
String GetStringFromScriptHelper(
const String& script,
- Document* doc,
+ ExecutionContext* context,
// Parameters to customize error messages:
const char* element_name_for_exception,
const char* attribute_name_for_exception,
TrustedTypeViolationKind violation_kind,
TrustedTypeViolationKind violation_kind_when_default_policy_failed) {
- if (!doc)
+ if (!context)
return script;
- bool require_trusted_type =
- RequireTrustedTypesCheck(doc->ToExecutionContext());
- if (!require_trusted_type)
+ if (!RequireTrustedTypesCheck(context))
return script;
// Set up JS context & friends.
@@ -206,21 +203,16 @@ String GetStringFromScriptHelper(
// Unlike the various ScriptController::Execute* and ..::Eval* methods,
// we are not executing a source String, but an already compiled callback
// function.
- v8::HandleScope handle_scope(doc->GetIsolate());
+ v8::HandleScope handle_scope(context->GetIsolate());
ScriptState::Scope script_state_scope(
- ScriptState::From(static_cast<LocalWindowProxyManager*>(
- doc->GetFrame()->GetWindowProxyManager())
- ->MainWorldProxy()
- ->ContextIfInitialized()));
+ ToScriptState(context, DOMWrapperWorld::MainWorld()));
ExceptionState exception_state(
- doc->GetIsolate(), ExceptionState::kUnknownContext,
+ context->GetIsolate(), ExceptionState::kUnknownContext,
element_name_for_exception, attribute_name_for_exception);
- TrustedTypePolicy* default_policy =
- GetDefaultPolicy(doc->ToExecutionContext());
+ TrustedTypePolicy* default_policy = GetDefaultPolicy(context);
if (!default_policy) {
- if (TrustedTypeFail(violation_kind, doc->ToExecutionContext(),
- exception_state, script)) {
+ if (TrustedTypeFail(violation_kind, context, exception_state, script)) {
exception_state.ClearException();
return String();
}
@@ -228,8 +220,8 @@ String GetStringFromScriptHelper(
}
TrustedScript* result = default_policy->CreateScript(
- doc->GetIsolate(), script,
- GetDefaultCallbackArgs(doc->GetIsolate(), "TrustedScript",
+ context->GetIsolate(), script,
+ GetDefaultCallbackArgs(context->GetIsolate(), "TrustedScript",
exception_state),
exception_state);
if (exception_state.HadException()) {
@@ -238,8 +230,8 @@ String GetStringFromScriptHelper(
}
if (result->toString().IsNull()) {
- if (TrustedTypeFail(violation_kind_when_default_policy_failed,
- doc->ToExecutionContext(), exception_state, script)) {
+ if (TrustedTypeFail(violation_kind_when_default_policy_failed, context,
+ exception_state, script)) {
exception_state.ClearException();
return String();
}
@@ -301,14 +293,6 @@ String TrustedTypesCheckForHTML(const String& html,
return result->toString();
}
-String TrustedTypesCheckForHTML(const String& html,
- const Document* document,
- ExceptionState& exception_state) {
- return TrustedTypesCheckForHTML(
- html, document ? document->GetExecutionContext() : nullptr,
- exception_state);
-}
-
String TrustedTypesCheckForScript(const String& script,
const ExecutionContext* execution_context,
ExceptionState& exception_state) {
@@ -477,17 +461,17 @@ String TrustedTypesCheckFor(SpecificTrustedType type,
String CORE_EXPORT
GetStringForScriptExecution(const String& script,
const ScriptElementBase::Type type,
- Document* doc) {
- return GetStringFromScriptHelper(script, doc, GetElementName(type), "text",
- kScriptExecution,
+ ExecutionContext* context) {
+ return GetStringFromScriptHelper(script, context, GetElementName(type),
+ "text", kScriptExecution,
kScriptExecutionAndDefaultPolicyFailed);
}
String TrustedTypesCheckForJavascriptURLinNavigation(
const String& javascript_url,
- Document* doc) {
+ ExecutionContext* context) {
return GetStringFromScriptHelper(
- javascript_url, doc, "Location", "href", kNavigateToJavascriptURL,
+ javascript_url, context, "Location", "href", kNavigateToJavascriptURL,
kNavigateToJavascriptURLAndDefaultPolicyFailed);
}
diff --git a/chromium/third_party/blink/renderer/core/trustedtypes/trusted_types_util.h b/chromium/third_party/blink/renderer/core/trustedtypes/trusted_types_util.h
index 2169c32ba87..4f825a887cf 100644
--- a/chromium/third_party/blink/renderer/core/trustedtypes/trusted_types_util.h
+++ b/chromium/third_party/blink/renderer/core/trustedtypes/trusted_types_util.h
@@ -11,7 +11,6 @@
namespace blink {
-class Document;
class ExecutionContext;
class ExceptionState;
class StringOrTrustedHTMLOrTrustedScriptOrTrustedScriptURL;
@@ -24,12 +23,6 @@ enum class SpecificTrustedType {
kScriptURL,
};
-// TODO(crbug.com/1029822): Temporary helpers to ease migrating ExecutionContext
-// to LocalDOMWindow.
-CORE_EXPORT String TrustedTypesCheckForHTML(const String&,
- const Document*,
- ExceptionState&);
-
// Perform Trusted Type checks, with the IDL union types as input. All of these
// will call String& versions below to do the heavy lifting.
CORE_EXPORT String TrustedTypesCheckFor(
@@ -65,10 +58,11 @@ CORE_EXPORT String TrustedTypesCheckForScriptURL(const String&,
// Functionally equivalent to TrustedTypesCheckForScript(const String&, ...),
// but with setup & error handling suitable for the asynchronous execution
// cases.
-String TrustedTypesCheckForJavascriptURLinNavigation(const String&, Document*);
+String TrustedTypesCheckForJavascriptURLinNavigation(const String&,
+ ExecutionContext*);
CORE_EXPORT String GetStringForScriptExecution(const String&,
ScriptElementBase::Type,
- Document*);
+ ExecutionContext*);
// Determine whether a Trusted Types check is needed in this execution context.
//
diff --git a/chromium/third_party/blink/renderer/core/trustedtypes/trusted_types_util_test.cc b/chromium/third_party/blink/renderer/core/trustedtypes/trusted_types_util_test.cc
index a484b9688c1..030078ebe7a 100644
--- a/chromium/third_party/blink/renderer/core/trustedtypes/trusted_types_util_test.cc
+++ b/chromium/third_party/blink/renderer/core/trustedtypes/trusted_types_util_test.cc
@@ -9,39 +9,32 @@
#include "third_party/blink/renderer/bindings/core/v8/string_or_trusted_html_or_trusted_script_or_trusted_script_url.h"
#include "third_party/blink/renderer/bindings/core/v8/string_or_trusted_script.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h"
-#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/frame/csp/content_security_policy.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/testing/dummy_page_holder.h"
#include "third_party/blink/renderer/core/trustedtypes/trusted_html.h"
#include "third_party/blink/renderer/core/trustedtypes/trusted_script.h"
#include "third_party/blink/renderer/core/trustedtypes/trusted_script_url.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
-#include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
namespace blink {
void TrustedTypesCheckForHTMLThrows(const String& string) {
auto dummy_page_holder = std::make_unique<DummyPageHolder>(IntSize(800, 600));
- KURL url("https://example.site");
- dummy_page_holder->GetFrame().Loader().CommitNavigation(
- WebNavigationParams::CreateWithHTMLBuffer(SharedBuffer::Create(), url),
- nullptr /* extra_data */);
- blink::test::RunPendingTasks();
-
- Document& document = dummy_page_holder->GetDocument();
+ LocalDOMWindow* window = dummy_page_holder->GetFrame().DomWindow();
V8TestingScope scope;
DummyExceptionStateForTesting exception_state;
ASSERT_FALSE(exception_state.HadException());
- String s = TrustedTypesCheckForHTML(string, &document, exception_state);
+ String s = TrustedTypesCheckForHTML(string, window, exception_state);
EXPECT_FALSE(exception_state.HadException());
- document.GetContentSecurityPolicy()->DidReceiveHeader(
+ window->GetContentSecurityPolicy()->DidReceiveHeader(
"require-trusted-types-for 'script'",
network::mojom::ContentSecurityPolicyType::kEnforce,
network::mojom::ContentSecurityPolicySource::kMeta);
ASSERT_FALSE(exception_state.HadException());
- String s1 = TrustedTypesCheckForHTML(string, &document, exception_state);
+ String s1 = TrustedTypesCheckForHTML(string, window, exception_state);
EXPECT_TRUE(exception_state.HadException());
EXPECT_EQ(ESErrorType::kTypeError, exception_state.CodeAs<ESErrorType>());
exception_state.ClearException();
@@ -49,27 +42,19 @@ void TrustedTypesCheckForHTMLThrows(const String& string) {
void TrustedTypesCheckForScriptThrows(const String& string) {
auto dummy_page_holder = std::make_unique<DummyPageHolder>(IntSize(800, 600));
- KURL url("https://example.site");
- dummy_page_holder->GetFrame().Loader().CommitNavigation(
- WebNavigationParams::CreateWithHTMLBuffer(SharedBuffer::Create(), url),
- nullptr /* extra_data */);
- blink::test::RunPendingTasks();
-
- Document& document = dummy_page_holder->GetDocument();
+ LocalDOMWindow* window = dummy_page_holder->GetFrame().DomWindow();
V8TestingScope scope;
DummyExceptionStateForTesting exception_state;
ASSERT_FALSE(exception_state.HadException());
- String s = TrustedTypesCheckForScript(string, document.ToExecutionContext(),
- exception_state);
+ String s = TrustedTypesCheckForScript(string, window, exception_state);
EXPECT_FALSE(exception_state.HadException());
- document.GetContentSecurityPolicy()->DidReceiveHeader(
+ window->GetContentSecurityPolicy()->DidReceiveHeader(
"require-trusted-types-for 'script'",
network::mojom::ContentSecurityPolicyType::kEnforce,
network::mojom::ContentSecurityPolicySource::kMeta);
ASSERT_FALSE(exception_state.HadException());
- String s1 = TrustedTypesCheckForScript(string, document.ToExecutionContext(),
- exception_state);
+ String s1 = TrustedTypesCheckForScript(string, window, exception_state);
EXPECT_TRUE(exception_state.HadException());
EXPECT_EQ(ESErrorType::kTypeError, exception_state.CodeAs<ESErrorType>());
exception_state.ClearException();
@@ -77,27 +62,19 @@ void TrustedTypesCheckForScriptThrows(const String& string) {
void TrustedTypesCheckForScriptURLThrows(const String& string) {
auto dummy_page_holder = std::make_unique<DummyPageHolder>(IntSize(800, 600));
- KURL url("https://example.site");
- dummy_page_holder->GetFrame().Loader().CommitNavigation(
- WebNavigationParams::CreateWithHTMLBuffer(SharedBuffer::Create(), url),
- nullptr /* extra_data */);
- blink::test::RunPendingTasks();
-
- Document& document = dummy_page_holder->GetDocument();
+ LocalDOMWindow* window = dummy_page_holder->GetFrame().DomWindow();
V8TestingScope scope;
DummyExceptionStateForTesting exception_state;
ASSERT_FALSE(exception_state.HadException());
- String s = TrustedTypesCheckForScriptURL(
- string, document.ToExecutionContext(), exception_state);
+ String s = TrustedTypesCheckForScriptURL(string, window, exception_state);
EXPECT_FALSE(exception_state.HadException());
- document.GetContentSecurityPolicy()->DidReceiveHeader(
+ window->GetContentSecurityPolicy()->DidReceiveHeader(
"require-trusted-types-for 'script'",
network::mojom::ContentSecurityPolicyType::kEnforce,
network::mojom::ContentSecurityPolicySource::kMeta);
ASSERT_FALSE(exception_state.HadException());
- String s1 = TrustedTypesCheckForScriptURL(
- string, document.ToExecutionContext(), exception_state);
+ String s1 = TrustedTypesCheckForScriptURL(string, window, exception_state);
EXPECT_TRUE(exception_state.HadException());
EXPECT_EQ(ESErrorType::kTypeError, exception_state.CodeAs<ESErrorType>());
exception_state.ClearException();
@@ -107,11 +84,11 @@ void TrustedTypesCheckForScriptWorks(
const StringOrTrustedScript& string_or_trusted_script,
String expected) {
auto dummy_page_holder = std::make_unique<DummyPageHolder>(IntSize(800, 600));
- Document& document = dummy_page_holder->GetDocument();
+ LocalDOMWindow* window = dummy_page_holder->GetFrame().DomWindow();
V8TestingScope scope;
DummyExceptionStateForTesting exception_state;
- String s = TrustedTypesCheckForScript(
- string_or_trusted_script, document.ToExecutionContext(), exception_state);
+ String s = TrustedTypesCheckForScript(string_or_trusted_script, window,
+ exception_state);
ASSERT_EQ(s, expected);
}
diff --git a/chromium/third_party/blink/renderer/core/typed_arrays/array_buffer/array_buffer_contents.cc b/chromium/third_party/blink/renderer/core/typed_arrays/array_buffer/array_buffer_contents.cc
index 095ca3db051..fe4485a3479 100644
--- a/chromium/third_party/blink/renderer/core/typed_arrays/array_buffer/array_buffer_contents.cc
+++ b/chromium/third_party/blink/renderer/core/typed_arrays/array_buffer/array_buffer_contents.cc
@@ -29,6 +29,7 @@
#include <string.h>
#include "base/allocator/partition_allocator/partition_alloc.h"
+#include "third_party/blink/renderer/platform/instrumentation/instance_counters.h"
#include "third_party/blink/renderer/platform/wtf/allocator/partitions.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h"
@@ -118,6 +119,8 @@ void* ArrayBufferContents::AllocateMemoryWithFlags(size_t size,
void* data = PartitionAllocGenericFlags(
WTF::Partitions::ArrayBufferPartition(), flags, size,
WTF_HEAP_PROFILER_TYPE_NAME(ArrayBufferContents));
+ InstanceCounters::IncrementCounter(
+ InstanceCounters::kArrayBufferContentsCounter);
return data;
}
@@ -127,6 +130,8 @@ void* ArrayBufferContents::AllocateMemoryOrNull(size_t size,
}
void ArrayBufferContents::FreeMemory(void* data) {
+ InstanceCounters::DecrementCounter(
+ InstanceCounters::kArrayBufferContentsCounter);
WTF::Partitions::ArrayBufferPartition()->Free(data);
}
diff --git a/chromium/third_party/blink/renderer/core/workers/abstract_worker.cc b/chromium/third_party/blink/renderer/core/workers/abstract_worker.cc
index eb5eef37994..a53c674b831 100644
--- a/chromium/third_party/blink/renderer/core/workers/abstract_worker.cc
+++ b/chromium/third_party/blink/renderer/core/workers/abstract_worker.cc
@@ -43,10 +43,12 @@ AbstractWorker::AbstractWorker(ExecutionContext* context)
AbstractWorker::~AbstractWorker() = default;
// static
-KURL AbstractWorker::ResolveURL(ExecutionContext* execution_context,
- const String& url,
- ExceptionState& exception_state,
- mojom::RequestContextType request_context) {
+KURL AbstractWorker::ResolveURL(
+ ExecutionContext* execution_context,
+ const String& url,
+ ExceptionState& exception_state,
+ mojom::RequestContextType request_context,
+ network::mojom::RequestDestination request_destination) {
KURL script_url = execution_context->CompleteURL(url);
if (!script_url.IsValid()) {
exception_state.ThrowDOMException(DOMExceptionCode::kSyntaxError,
@@ -67,7 +69,8 @@ KURL AbstractWorker::ResolveURL(ExecutionContext* execution_context,
if (ContentSecurityPolicy* csp =
execution_context->GetContentSecurityPolicy()) {
- if (!csp->AllowRequestWithoutIntegrity(request_context, script_url) ||
+ if (!csp->AllowRequestWithoutIntegrity(request_context, request_destination,
+ script_url) ||
!csp->AllowWorkerContextFromSource(script_url)) {
exception_state.ThrowSecurityError(
"Access to the script at '" + script_url.ElidedString() +
diff --git a/chromium/third_party/blink/renderer/core/workers/abstract_worker.h b/chromium/third_party/blink/renderer/core/workers/abstract_worker.h
index 96ffa1dbe0f..51d9911fba1 100644
--- a/chromium/third_party/blink/renderer/core/workers/abstract_worker.h
+++ b/chromium/third_party/blink/renderer/core/workers/abstract_worker.h
@@ -31,6 +31,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_WORKERS_ABSTRACT_WORKER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_WORKERS_ABSTRACT_WORKER_H_
+#include "services/network/public/mojom/fetch_api.mojom.h"
#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink-forward.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/dom/events/event_listener.h"
@@ -70,10 +71,12 @@ class CORE_EXPORT AbstractWorker
protected:
// Helper function that converts a URL to an absolute URL and checks the
// result for validity.
- static KURL ResolveURL(ExecutionContext*,
- const String& url,
- ExceptionState&,
- mojom::RequestContextType);
+ static KURL ResolveURL(
+ ExecutionContext*,
+ const String& url,
+ ExceptionState&,
+ mojom::RequestContextType,
+ network::mojom::RequestDestination request_destination);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/workers/dedicated_worker.cc b/chromium/third_party/blink/renderer/core/workers/dedicated_worker.cc
index 86f200fecc0..c2d425c152c 100644
--- a/chromium/third_party/blink/renderer/core/workers/dedicated_worker.cc
+++ b/chromium/third_party/blink/renderer/core/workers/dedicated_worker.cc
@@ -25,6 +25,7 @@
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/fetch/request.h"
#include "third_party/blink/renderer/core/fileapi/public_url_manager.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/local_frame_client.h"
#include "third_party/blink/renderer/core/frame/web_frame_widget_base.h"
@@ -63,8 +64,9 @@ DedicatedWorker* DedicatedWorker::Create(ExecutionContext* context,
return nullptr;
}
- KURL script_request_url = ResolveURL(context, url, exception_state,
- mojom::RequestContextType::SCRIPT);
+ KURL script_request_url = ResolveURL(
+ context, url, exception_state, mojom::RequestContextType::SCRIPT,
+ network::mojom::RequestDestination::kScript);
if (!script_request_url.IsValid()) {
// Don't throw an exception here because it's already thrown in
// ResolveURL().
@@ -255,12 +257,12 @@ void DedicatedWorker::terminate() {
BeginFrameProviderParams DedicatedWorker::CreateBeginFrameProviderParams() {
DCHECK(GetExecutionContext()->IsContextThread());
- // If we don't have a frame or we are not in Document, some of the SinkIds
+ // If we don't have a frame or we are not in window, some of the SinkIds
// won't be initialized. If that's the case, the Worker will initialize it by
// itself later.
BeginFrameProviderParams begin_frame_provider_params;
- if (auto* document = Document::DynamicFrom(GetExecutionContext())) {
- LocalFrame* frame = document->GetFrame();
+ if (auto* window = DynamicTo<LocalDOMWindow>(GetExecutionContext())) {
+ LocalFrame* frame = window->GetFrame();
if (frame) {
WebFrameWidgetBase* widget =
WebLocalFrameImpl::FromFrame(frame)->LocalRootFrameWidget();
@@ -322,9 +324,8 @@ void DedicatedWorker::DispatchErrorEventForScriptFetchFailure() {
std::unique_ptr<WebContentSettingsClient>
DedicatedWorker::CreateWebContentSettingsClient() {
std::unique_ptr<WebContentSettingsClient> content_settings_client;
- if (auto* document = Document::DynamicFrom(GetExecutionContext())) {
- LocalFrame* frame = document->GetFrame();
- return frame->Client()->CreateWorkerContentSettingsClient();
+ if (auto* window = DynamicTo<LocalDOMWindow>(GetExecutionContext())) {
+ return window->GetFrame()->Client()->CreateWorkerContentSettingsClient();
} else if (GetExecutionContext()->IsWorkerGlobalScope()) {
WebContentSettingsClient* web_worker_content_settings_client =
To<WorkerGlobalScope>(GetExecutionContext())->ContentSettingsClient();
@@ -390,14 +391,14 @@ DedicatedWorker::CreateGlobalScopeCreationParams(
base::UnguessableToken parent_devtools_token;
std::unique_ptr<WorkerSettings> settings;
UserAgentMetadata ua_metadata;
- if (auto* document = Document::DynamicFrom(GetExecutionContext())) {
- auto* frame = document->GetFrame();
+ if (auto* window = DynamicTo<LocalDOMWindow>(GetExecutionContext())) {
+ auto* frame = window->GetFrame();
if (frame) {
parent_devtools_token = frame->GetDevToolsFrameToken();
ua_metadata = frame->Loader().UserAgentMetadata().value_or(
blink::UserAgentMetadata());
}
- settings = std::make_unique<WorkerSettings>(document->GetSettings());
+ settings = std::make_unique<WorkerSettings>(frame->GetSettings());
} else {
WorkerGlobalScope* worker_global_scope =
To<WorkerGlobalScope>(GetExecutionContext());
@@ -431,10 +432,10 @@ DedicatedWorker::CreateGlobalScopeCreationParams(
scoped_refptr<WebWorkerFetchContext>
DedicatedWorker::CreateWebWorkerFetchContext() {
- // This worker is being created by the document.
- if (auto* document = Document::DynamicFrom(GetExecutionContext())) {
+ // This worker is being created by the window.
+ if (auto* window = DynamicTo<LocalDOMWindow>(GetExecutionContext())) {
scoped_refptr<WebWorkerFetchContext> web_worker_fetch_context;
- LocalFrame* frame = document->GetFrame();
+ LocalFrame* frame = window->GetFrame();
if (base::FeatureList::IsEnabled(features::kPlzDedicatedWorker)) {
web_worker_fetch_context =
frame->Client()->CreateWorkerFetchContextForPlzDedicatedWorker(
diff --git a/chromium/third_party/blink/renderer/core/workers/dedicated_worker_global_scope.cc b/chromium/third_party/blink/renderer/core/workers/dedicated_worker_global_scope.cc
index d57ebc459c9..71d37009caf 100644
--- a/chromium/third_party/blink/renderer/core/workers/dedicated_worker_global_scope.cc
+++ b/chromium/third_party/blink/renderer/core/workers/dedicated_worker_global_scope.cc
@@ -38,7 +38,6 @@
#include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_post_message_options.h"
#include "third_party/blink/renderer/bindings/core/v8/worker_or_worklet_script_controller.h"
-#include "third_party/blink/renderer/core/core_initializer.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/frame/csp/content_security_policy.h"
#include "third_party/blink/renderer/core/inspector/worker_thread_debugger.h"
@@ -109,7 +108,6 @@ DedicatedWorkerGlobalScope::DedicatedWorkerGlobalScope(
MakeGarbageCollected<WorkerAnimationFrameProvider>(
this,
begin_frame_provider_params)) {
- CoreInitializer::GetInstance().ProvideLocalFileSystemToWorker(*this);
// Dedicated workers don't need to pause after script fetch.
ReadyToRunWorkerScript();
diff --git a/chromium/third_party/blink/renderer/core/workers/dedicated_worker_test.cc b/chromium/third_party/blink/renderer/core/workers/dedicated_worker_test.cc
index f505b02d1c2..0d9cafcf2d4 100644
--- a/chromium/third_party/blink/renderer/core/workers/dedicated_worker_test.cc
+++ b/chromium/third_party/blink/renderer/core/workers/dedicated_worker_test.cc
@@ -11,6 +11,7 @@
#include "third_party/blink/renderer/bindings/core/v8/sanitize_script_errors.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_cache_options.h"
#include "third_party/blink/renderer/core/events/message_event.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/inspector/console_message_storage.h"
#include "third_party/blink/renderer/core/inspector/thread_debugger.h"
#include "third_party/blink/renderer/core/script/script.h"
@@ -128,7 +129,7 @@ class DedicatedWorkerMessagingProxyForTest
{"contentSecurityPolicy",
network::mojom::ContentSecurityPolicyType::kReport}};
auto worker_settings = std::make_unique<WorkerSettings>(
- Document::From(GetExecutionContext())->GetSettings());
+ To<LocalDOMWindow>(GetExecutionContext())->GetFrame()->GetSettings());
InitializeWorkerThread(
std::make_unique<GlobalScopeCreationParams>(
script_url, mojom::ScriptType::kClassic, "fake global scope name",
@@ -175,7 +176,7 @@ class DedicatedWorkerTest : public PageTestBase {
PageTestBase::SetUp(IntSize());
worker_messaging_proxy_ =
MakeGarbageCollected<DedicatedWorkerMessagingProxyForTest>(
- GetDocument().ToExecutionContext());
+ GetFrame().DomWindow());
}
void TearDown() override {
diff --git a/chromium/third_party/blink/renderer/core/workers/main_thread_worklet_reporting_proxy.cc b/chromium/third_party/blink/renderer/core/workers/main_thread_worklet_reporting_proxy.cc
index 07030d36f0a..296702d83a4 100644
--- a/chromium/third_party/blink/renderer/core/workers/main_thread_worklet_reporting_proxy.cc
+++ b/chromium/third_party/blink/renderer/core/workers/main_thread_worklet_reporting_proxy.cc
@@ -4,28 +4,28 @@
#include "third_party/blink/renderer/core/workers/main_thread_worklet_reporting_proxy.h"
-#include "third_party/blink/renderer/core/dom/document.h"
+#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/frame/deprecation.h"
#include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
namespace blink {
MainThreadWorkletReportingProxy::MainThreadWorkletReportingProxy(
- Document* document)
- : document_(document) {}
+ ExecutionContext* context)
+ : context_(context) {}
void MainThreadWorkletReportingProxy::CountFeature(WebFeature feature) {
DCHECK(IsMainThread());
- // A parent document is on the same thread, so just record API use in the
- // document's UseCounter.
- UseCounter::Count(document_, feature);
+ // A parent context is on the same thread, so just record API use in the
+ // context's UseCounter.
+ UseCounter::Count(context_, feature);
}
void MainThreadWorkletReportingProxy::CountDeprecation(WebFeature feature) {
DCHECK(IsMainThread());
- // A parent document is on the same thread, so just record API use in the
- // document's UseCounter.
- Deprecation::CountDeprecation(document_, feature);
+ // A parent context is on the same thread, so just record API use in the
+ // context's UseCounter.
+ Deprecation::CountDeprecation(context_, feature);
}
void MainThreadWorkletReportingProxy::DidTerminateWorkerThread() {
diff --git a/chromium/third_party/blink/renderer/core/workers/main_thread_worklet_reporting_proxy.h b/chromium/third_party/blink/renderer/core/workers/main_thread_worklet_reporting_proxy.h
index 7913c8ca964..aeb69f3ca93 100644
--- a/chromium/third_party/blink/renderer/core/workers/main_thread_worklet_reporting_proxy.h
+++ b/chromium/third_party/blink/renderer/core/workers/main_thread_worklet_reporting_proxy.h
@@ -10,12 +10,12 @@
namespace blink {
-class Document;
+class ExecutionContext;
class CORE_EXPORT MainThreadWorkletReportingProxy
: public WorkerReportingProxy {
public:
- explicit MainThreadWorkletReportingProxy(Document*);
+ explicit MainThreadWorkletReportingProxy(ExecutionContext*);
~MainThreadWorkletReportingProxy() override = default;
// Implements WorkerReportingProxy.
@@ -24,7 +24,7 @@ class CORE_EXPORT MainThreadWorkletReportingProxy
void DidTerminateWorkerThread() override;
private:
- Persistent<Document> document_;
+ Persistent<ExecutionContext> context_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/workers/main_thread_worklet_test.cc b/chromium/third_party/blink/renderer/core/workers/main_thread_worklet_test.cc
index 02ea3808611..66e6f5ec091 100644
--- a/chromium/third_party/blink/renderer/core/workers/main_thread_worklet_test.cc
+++ b/chromium/third_party/blink/renderer/core/workers/main_thread_worklet_test.cc
@@ -7,6 +7,7 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/origin_trials/origin_trial_context.h"
#include "third_party/blink/renderer/core/script/script.h"
#include "third_party/blink/renderer/core/testing/page_test_base.h"
@@ -22,8 +23,8 @@ namespace blink {
class MainThreadWorkletReportingProxyForTest final
: public MainThreadWorkletReportingProxy {
public:
- explicit MainThreadWorkletReportingProxyForTest(Document* document)
- : MainThreadWorkletReportingProxy(document) {}
+ explicit MainThreadWorkletReportingProxyForTest(LocalDOMWindow* window)
+ : MainThreadWorkletReportingProxy(window) {}
void CountFeature(WebFeature feature) override {
// Any feature should be reported only one time.
@@ -52,7 +53,7 @@ class MainThreadWorkletTest : public PageTestBase {
void SetUpScope(const String& csp_header) {
PageTestBase::SetUp(IntSize());
NavigateTo(KURL("https://example.com/"));
- Document* document = &GetDocument();
+ LocalDOMWindow* window = GetFrame().DomWindow();
// Set up the CSP for Document before starting MainThreadWorklet because
// MainThreadWorklet inherits the owner Document's CSP.
@@ -60,26 +61,29 @@ class MainThreadWorkletTest : public PageTestBase {
csp->DidReceiveHeader(csp_header,
network::mojom::ContentSecurityPolicyType::kEnforce,
network::mojom::ContentSecurityPolicySource::kHTTP);
- document->InitContentSecurityPolicy(csp);
+ window->document()->InitContentSecurityPolicy(csp);
reporting_proxy_ =
- std::make_unique<MainThreadWorkletReportingProxyForTest>(document);
+ std::make_unique<MainThreadWorkletReportingProxyForTest>(window);
auto creation_params = std::make_unique<GlobalScopeCreationParams>(
- document->Url(), mojom::ScriptType::kModule, "MainThreadWorklet",
- document->UserAgent(),
- document->GetFrame()->Loader().UserAgentMetadata(),
+ window->Url(), mojom::ScriptType::kModule, "MainThreadWorklet",
+ window->UserAgent(), window->GetFrame()->Loader().UserAgentMetadata(),
nullptr /* web_worker_fetch_context */,
- document->GetContentSecurityPolicy()->Headers(),
- document->GetReferrerPolicy(), document->GetSecurityOrigin(),
- document->IsSecureContext(), document->GetHttpsState(),
+ window->GetContentSecurityPolicy()->Headers(),
+ window->GetReferrerPolicy(), window->GetSecurityOrigin(),
+ window->IsSecureContext(), window->GetHttpsState(),
nullptr /* worker_clients */, nullptr /* content_settings_client */,
- document->GetSecurityContext().AddressSpace(),
- OriginTrialContext::GetTokens(document->ToExecutionContext()).get(),
+ window->GetSecurityContext().AddressSpace(),
+ OriginTrialContext::GetTokens(window).get(),
base::UnguessableToken::Create(), nullptr /* worker_settings */,
kV8CacheOptionsDefault,
- MakeGarbageCollected<WorkletModuleResponsesMap>());
+ MakeGarbageCollected<WorkletModuleResponsesMap>(),
+ mojo::NullRemote() /* browser_interface_broker */,
+ BeginFrameProviderParams(), nullptr /* parent_feature_policy */,
+ window->GetAgentClusterID());
global_scope_ = MakeGarbageCollected<WorkletGlobalScope>(
- std::move(creation_params), *reporting_proxy_, &GetFrame());
+ std::move(creation_params), *reporting_proxy_, &GetFrame(),
+ false /* create_microtask_queue */);
EXPECT_TRUE(global_scope_->IsMainThreadWorkletGlobalScope());
EXPECT_FALSE(global_scope_->IsThreadedWorkletGlobalScope());
}
@@ -103,6 +107,13 @@ TEST_F(MainThreadWorkletTest, SecurityOrigin) {
EXPECT_FALSE(global_scope_->DocumentSecurityOrigin()->IsOpaque());
}
+TEST_F(MainThreadWorkletTest, AgentCluster) {
+ // The worklet should be in the owner window's agent cluster.
+ ASSERT_TRUE(GetFrame().DomWindow()->GetAgentClusterID());
+ EXPECT_EQ(global_scope_->GetAgentClusterID(),
+ GetFrame().DomWindow()->GetAgentClusterID());
+}
+
TEST_F(MainThreadWorkletTest, ContentSecurityPolicy) {
ContentSecurityPolicy* csp = global_scope_->GetContentSecurityPolicy();
diff --git a/chromium/third_party/blink/renderer/core/workers/shared_worker.cc b/chromium/third_party/blink/renderer/core/workers/shared_worker.cc
index 87f09b78782..b814a575ad2 100644
--- a/chromium/third_party/blink/renderer/core/workers/shared_worker.cc
+++ b/chromium/third_party/blink/renderer/core/workers/shared_worker.cc
@@ -40,6 +40,7 @@
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/fetch/request.h"
#include "third_party/blink/renderer/core/fileapi/public_url_manager.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/messaging/message_channel.h"
#include "third_party/blink/renderer/core/messaging/message_port.h"
#include "third_party/blink/renderer/core/probe/core_probes.h"
@@ -54,11 +55,11 @@ namespace blink {
namespace {
-void RecordSharedWorkerUsage(Document* document) {
- UseCounter::Count(document, WebFeature::kSharedWorkerStart);
+void RecordSharedWorkerUsage(LocalDOMWindow* window) {
+ UseCounter::Count(window, WebFeature::kSharedWorkerStart);
- if (document->IsCrossSiteSubframe())
- UseCounter::Count(document, WebFeature::kThirdPartySharedWorker);
+ if (window->IsCrossSiteSubframe())
+ UseCounter::Count(window, WebFeature::kThirdPartySharedWorker);
}
} // namespace
@@ -77,11 +78,10 @@ SharedWorker* SharedWorker::Create(ExecutionContext* context,
DCHECK(IsMainThread());
// We don't currently support nested workers, so workers can only be created
- // from documents.
- Document* document = Document::From(context);
- DCHECK(document);
+ // from windows.
+ LocalDOMWindow* window = To<LocalDOMWindow>(context);
- RecordSharedWorkerUsage(document);
+ RecordSharedWorkerUsage(window);
SharedWorker* worker = MakeGarbageCollected<SharedWorker>(context);
worker->UpdateStateIfNeeded();
@@ -90,23 +90,24 @@ SharedWorker* SharedWorker::Create(ExecutionContext* context,
worker->port_ = channel->port1();
MessagePortChannel remote_port = channel->port2()->Disentangle();
- if (!document->GetSecurityOrigin()->CanAccessSharedWorkers()) {
+ if (!window->GetSecurityOrigin()->CanAccessSharedWorkers()) {
exception_state.ThrowSecurityError(
"Access to shared workers is denied to origin '" +
- document->GetSecurityOrigin()->ToString() + "'.");
+ window->GetSecurityOrigin()->ToString() + "'.");
return nullptr;
- } else if (document->GetSecurityOrigin()->IsLocal()) {
- UseCounter::Count(document, WebFeature::kFileAccessedSharedWorker);
+ } else if (window->GetSecurityOrigin()->IsLocal()) {
+ UseCounter::Count(window, WebFeature::kFileAccessedSharedWorker);
}
- KURL script_url = ResolveURL(context, url, exception_state,
- mojom::RequestContextType::SHARED_WORKER);
+ KURL script_url = ResolveURL(
+ context, url, exception_state, mojom::RequestContextType::SHARED_WORKER,
+ network::mojom::RequestDestination::kSharedWorker);
if (script_url.IsEmpty())
return nullptr;
mojo::PendingRemote<mojom::blink::BlobURLToken> blob_url_token;
if (script_url.ProtocolIs("blob")) {
- document->GetPublicURLManager().Resolve(
+ window->GetPublicURLManager().Resolve(
script_url, blob_url_token.InitWithNewPipeAndPassReceiver());
}
@@ -136,11 +137,11 @@ SharedWorker* SharedWorker::Create(ExecutionContext* context,
}
DCHECK(!options->name.IsNull());
if (options->type == mojom::blink::ScriptType::kClassic)
- UseCounter::Count(document, WebFeature::kClassicSharedWorker);
+ UseCounter::Count(window, WebFeature::kClassicSharedWorker);
else if (options->type == mojom::blink::ScriptType::kModule)
- UseCounter::Count(document, WebFeature::kModuleSharedWorker);
+ UseCounter::Count(window, WebFeature::kModuleSharedWorker);
- SharedWorkerClientHolder::From(*document)->Connect(
+ SharedWorkerClientHolder::From(*window)->Connect(
worker, std::move(remote_port), script_url, std::move(blob_url_token),
std::move(options));
diff --git a/chromium/third_party/blink/renderer/core/workers/shared_worker.idl b/chromium/third_party/blink/renderer/core/workers/shared_worker.idl
index 36051236e4b..7cdc4b5b75d 100644
--- a/chromium/third_party/blink/renderer/core/workers/shared_worker.idl
+++ b/chromium/third_party/blink/renderer/core/workers/shared_worker.idl
@@ -33,7 +33,8 @@
[
ActiveScriptWrappable,
- // TODO(foolip): Exposed=(Window,Worker),
+ // TODO(foolip): Exposed=(Window, Worker),
+ Exposed=Window,
RuntimeEnabled=SharedWorker
] interface SharedWorker : EventTarget {
[CallWith=ExecutionContext, RaisesException] constructor(ScriptURLString scriptURL, optional (DOMString or WorkerOptions) options = {});
diff --git a/chromium/third_party/blink/renderer/core/workers/shared_worker_client.cc b/chromium/third_party/blink/renderer/core/workers/shared_worker_client.cc
index 77f05a17e2f..ae6d25ceae6 100644
--- a/chromium/third_party/blink/renderer/core/workers/shared_worker_client.cc
+++ b/chromium/third_party/blink/renderer/core/workers/shared_worker_client.cc
@@ -4,7 +4,7 @@
#include "third_party/blink/renderer/core/workers/shared_worker_client.h"
-#include "base/logging.h"
+#include "base/check_op.h"
#include "third_party/blink/renderer/core/dom/events/event.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/inspector/console_message.h"
@@ -27,7 +27,7 @@ void SharedWorkerClient::OnCreated(
worker_->SetIsBeingConnected(true);
// No nested workers (for now) - connect() can only be called from a
- // document context.
+ // window context.
DCHECK(worker_->GetExecutionContext()->IsDocument());
DCHECK_EQ(creation_context_type,
worker_->GetExecutionContext()->IsSecureContext()
diff --git a/chromium/third_party/blink/renderer/core/workers/shared_worker_client_holder.cc b/chromium/third_party/blink/renderer/core/workers/shared_worker_client_holder.cc
index 99bbd31f3fa..3e61484883f 100644
--- a/chromium/third_party/blink/renderer/core/workers/shared_worker_client_holder.cc
+++ b/chromium/third_party/blink/renderer/core/workers/shared_worker_client_holder.cc
@@ -32,7 +32,7 @@
#include <memory>
#include <utility>
-#include "base/logging.h"
+#include "base/check.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
#include "third_party/blink/public/common/messaging/message_port_channel.h"
@@ -60,23 +60,24 @@ namespace blink {
const char SharedWorkerClientHolder::kSupplementName[] =
"SharedWorkerClientHolder";
-SharedWorkerClientHolder* SharedWorkerClientHolder::From(Document& document) {
+SharedWorkerClientHolder* SharedWorkerClientHolder::From(
+ LocalDOMWindow& window) {
DCHECK(IsMainThread());
SharedWorkerClientHolder* holder =
- Supplement<Document>::From<SharedWorkerClientHolder>(document);
+ Supplement<LocalDOMWindow>::From<SharedWorkerClientHolder>(window);
if (!holder) {
- holder = MakeGarbageCollected<SharedWorkerClientHolder>(document);
- Supplement<Document>::ProvideTo(document, holder);
+ holder = MakeGarbageCollected<SharedWorkerClientHolder>(window);
+ Supplement<LocalDOMWindow>::ProvideTo(window, holder);
}
return holder;
}
-SharedWorkerClientHolder::SharedWorkerClientHolder(Document& document)
- : connector_(document.ToExecutionContext()),
- client_receivers_(document.ToExecutionContext()),
- task_runner_(document.GetTaskRunner(blink::TaskType::kDOMManipulation)) {
+SharedWorkerClientHolder::SharedWorkerClientHolder(LocalDOMWindow& window)
+ : connector_(&window),
+ client_receivers_(&window),
+ task_runner_(window.GetTaskRunner(blink::TaskType::kDOMManipulation)) {
DCHECK(IsMainThread());
- document.GetBrowserInterfaceBroker().GetInterface(
+ window.GetBrowserInterfaceBroker().GetInterface(
connector_.BindNewPipeAndPassReceiver(task_runner_));
}
@@ -142,7 +143,7 @@ void SharedWorkerClientHolder::Connect(
void SharedWorkerClientHolder::Trace(Visitor* visitor) {
visitor->Trace(connector_);
visitor->Trace(client_receivers_);
- Supplement<Document>::Trace(visitor);
+ Supplement<LocalDOMWindow>::Trace(visitor);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/workers/shared_worker_client_holder.h b/chromium/third_party/blink/renderer/core/workers/shared_worker_client_holder.h
index c573cd93ab7..3e2bd9e3c29 100644
--- a/chromium/third_party/blink/renderer/core/workers/shared_worker_client_holder.h
+++ b/chromium/third_party/blink/renderer/core/workers/shared_worker_client_holder.h
@@ -41,8 +41,8 @@
#include "third_party/blink/public/mojom/worker/shared_worker_connector.mojom-blink.h"
#include "third_party/blink/public/mojom/worker/shared_worker_info.mojom-blink.h"
#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
#include "third_party/blink/renderer/platform/mojo/heap_mojo_remote.h"
#include "third_party/blink/renderer/platform/mojo/heap_mojo_unique_receiver_set.h"
@@ -59,18 +59,18 @@ class SharedWorker;
// new client instance regardless of existing connections, and keeps it until
// the connection gets lost.
//
-// SharedWorkerClientHolder is a per-Document object and owned by Document via
-// Supplement<Document>.
+// SharedWorkerClientHolder is a per-LocalDOMWindow object and owned by
+// LocalDOMWindow via Supplement<LocalDOMWindow>.
class CORE_EXPORT SharedWorkerClientHolder final
: public GarbageCollected<SharedWorkerClientHolder>,
- public Supplement<Document> {
+ public Supplement<LocalDOMWindow> {
USING_GARBAGE_COLLECTED_MIXIN(SharedWorkerClientHolder);
public:
static const char kSupplementName[];
- static SharedWorkerClientHolder* From(Document& document);
+ static SharedWorkerClientHolder* From(LocalDOMWindow&);
- explicit SharedWorkerClientHolder(Document&);
+ explicit SharedWorkerClientHolder(LocalDOMWindow&);
virtual ~SharedWorkerClientHolder() = default;
// Establishes a connection with SharedWorkerHost in the browser process.
diff --git a/chromium/third_party/blink/renderer/core/workers/shared_worker_global_scope.cc b/chromium/third_party/blink/renderer/core/workers/shared_worker_global_scope.cc
index 7290eabda66..003eeb4c980 100644
--- a/chromium/third_party/blink/renderer/core/workers/shared_worker_global_scope.cc
+++ b/chromium/third_party/blink/renderer/core/workers/shared_worker_global_scope.cc
@@ -35,7 +35,6 @@
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/renderer/bindings/core/v8/source_location.h"
#include "third_party/blink/renderer/bindings/core/v8/worker_or_worklet_script_controller.h"
-#include "third_party/blink/renderer/core/core_initializer.h"
#include "third_party/blink/renderer/core/events/message_event.h"
#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/inspector/console_message.h"
@@ -60,7 +59,7 @@ SharedWorkerGlobalScope::SharedWorkerGlobalScope(
: WorkerGlobalScope(std::move(creation_params), thread, time_origin) {
appcache_host_ = MakeGarbageCollected<ApplicationCacheHostForWorker>(
appcache_host_id, GetBrowserInterfaceBroker(),
- GetTaskRunner(TaskType::kInternalLoading));
+ GetTaskRunner(TaskType::kInternalLoading), this);
}
SharedWorkerGlobalScope::~SharedWorkerGlobalScope() = default;
@@ -77,7 +76,6 @@ void SharedWorkerGlobalScope::Initialize(
const Vector<CSPHeaderAndType>& response_csp_headers,
const Vector<String>* response_origin_trial_tokens,
int64_t appcache_id) {
- CoreInitializer::GetInstance().ProvideLocalFileSystemToWorker(*this);
// Step 12.3. "Set worker global scope's url to response's url."
InitializeURL(response_url);
diff --git a/chromium/third_party/blink/renderer/core/workers/shared_worker_reporting_proxy.cc b/chromium/third_party/blink/renderer/core/workers/shared_worker_reporting_proxy.cc
index df1750cee6d..f62aded8c34 100644
--- a/chromium/third_party/blink/renderer/core/workers/shared_worker_reporting_proxy.cc
+++ b/chromium/third_party/blink/renderer/core/workers/shared_worker_reporting_proxy.cc
@@ -64,9 +64,6 @@ void SharedWorkerReportingProxy::ReportConsoleMessage(
}
void SharedWorkerReportingProxy::DidFailToFetchClassicScript() {
- // TODO(nhiroki): Add a runtime flag check for off-the-main-thread shared
- // worker script fetch. This function should be called only when the flag is
- // enabled (https://crbug.com/924041).
DCHECK(!IsMainThread());
PostCrossThreadTask(
*parent_execution_context_task_runners_->Get(TaskType::kInternalDefault),
diff --git a/chromium/third_party/blink/renderer/core/workers/threaded_worklet_messaging_proxy.cc b/chromium/third_party/blink/renderer/core/workers/threaded_worklet_messaging_proxy.cc
index 21dfe9270a8..1b0025264fe 100644
--- a/chromium/third_party/blink/renderer/core/workers/threaded_worklet_messaging_proxy.cc
+++ b/chromium/third_party/blink/renderer/core/workers/threaded_worklet_messaging_proxy.cc
@@ -12,6 +12,7 @@
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/execution_context/security_context.h"
#include "third_party/blink/renderer/core/frame/csp/content_security_policy.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame_client.h"
#include "third_party/blink/renderer/core/inspector/thread_debugger.h"
#include "third_party/blink/renderer/core/loader/worker_fetch_context.h"
@@ -51,28 +52,28 @@ void ThreadedWorkletMessagingProxy::Initialize(
// LayoutWorklet and PaintWorklet.
const String global_scope_name = g_empty_string;
- Document* document = Document::From(GetExecutionContext());
- ContentSecurityPolicy* csp = document->GetContentSecurityPolicy();
+ LocalDOMWindow* window = To<LocalDOMWindow>(GetExecutionContext());
+ ContentSecurityPolicy* csp = window->GetContentSecurityPolicy();
DCHECK(csp);
auto global_scope_creation_params =
std::make_unique<GlobalScopeCreationParams>(
- document->Url(), mojom::blink::ScriptType::kModule, global_scope_name,
- document->UserAgent(),
- document->GetFrame()->Client()->UserAgentMetadata(),
- document->GetFrame()->Client()->CreateWorkerFetchContext(),
- csp->Headers(), document->GetReferrerPolicy(),
- document->GetSecurityOrigin(), document->IsSecureContext(),
- document->GetHttpsState(), worker_clients,
- document->GetFrame()->Client()->CreateWorkerContentSettingsClient(),
- document->GetSecurityContext().AddressSpace(),
- OriginTrialContext::GetTokens(document->ToExecutionContext()).get(),
+ window->Url(), mojom::blink::ScriptType::kModule, global_scope_name,
+ window->UserAgent(),
+ window->GetFrame()->Client()->UserAgentMetadata(),
+ window->GetFrame()->Client()->CreateWorkerFetchContext(),
+ csp->Headers(), window->GetReferrerPolicy(),
+ window->GetSecurityOrigin(), window->IsSecureContext(),
+ window->GetHttpsState(), worker_clients,
+ window->GetFrame()->Client()->CreateWorkerContentSettingsClient(),
+ window->GetSecurityContext().AddressSpace(),
+ OriginTrialContext::GetTokens(window).get(),
base::UnguessableToken::Create(),
- std::make_unique<WorkerSettings>(document->GetSettings()),
+ std::make_unique<WorkerSettings>(window->GetFrame()->GetSettings()),
kV8CacheOptionsDefault, module_responses_map,
mojo::NullRemote() /* browser_interface_broker */,
BeginFrameProviderParams(), nullptr /* parent_feature_policy */,
- document->ToExecutionContext()->GetAgentClusterID());
+ window->GetAgentClusterID());
// Worklets share the pre-initialized backing thread so that we don't have to
// specify the backing thread startup data.
diff --git a/chromium/third_party/blink/renderer/core/workers/threaded_worklet_test.cc b/chromium/third_party/blink/renderer/core/workers/threaded_worklet_test.cc
index e3b14213e1f..d3d601d60e8 100644
--- a/chromium/third_party/blink/renderer/core/workers/threaded_worklet_test.cc
+++ b/chromium/third_party/blink/renderer/core/workers/threaded_worklet_test.cc
@@ -7,6 +7,7 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_cache_options.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/inspector/console_message_storage.h"
#include "third_party/blink/renderer/core/inspector/thread_debugger.h"
#include "third_party/blink/renderer/core/origin_trials/origin_trial_context.h"
@@ -93,6 +94,13 @@ class ThreadedWorkletThreadForTest : public WorkerThread {
CrossThreadBindOnce(&test::ExitRunLoop));
}
+ void TestAgentCluster(base::UnguessableToken owner_agent_cluster_id) {
+ ASSERT_TRUE(owner_agent_cluster_id);
+ EXPECT_EQ(GlobalScope()->GetAgentClusterID(), owner_agent_cluster_id);
+ PostCrossThreadTask(*GetParentTaskRunnerForTesting(), FROM_HERE,
+ CrossThreadBindOnce(&test::ExitRunLoop));
+ }
+
void TestContentSecurityPolicy() {
EXPECT_TRUE(IsCurrentThread());
ContentSecurityPolicy* csp = GlobalScope()->GetContentSecurityPolicy();
@@ -192,25 +200,32 @@ class ThreadedWorkletMessagingProxyForTest
~ThreadedWorkletMessagingProxyForTest() override = default;
void Start() {
- Document* document = Document::From(GetExecutionContext());
std::unique_ptr<Vector<char>> cached_meta_data = nullptr;
WorkerClients* worker_clients = nullptr;
std::unique_ptr<WorkerSettings> worker_settings = nullptr;
InitializeWorkerThread(
std::make_unique<GlobalScopeCreationParams>(
- document->Url(), mojom::blink::ScriptType::kModule,
- "threaded_worklet", document->UserAgent(),
- document->GetFrame()->Loader().UserAgentMetadata(),
+ GetExecutionContext()->Url(), mojom::blink::ScriptType::kModule,
+ "threaded_worklet", GetExecutionContext()->UserAgent(),
+ To<LocalDOMWindow>(GetExecutionContext())
+ ->GetFrame()
+ ->Loader()
+ .UserAgentMetadata(),
nullptr /* web_worker_fetch_context */,
- document->GetContentSecurityPolicy()->Headers(),
- document->GetReferrerPolicy(), document->GetSecurityOrigin(),
- document->IsSecureContext(), document->GetHttpsState(),
- worker_clients, nullptr /* content_settings_client */,
- document->GetSecurityContext().AddressSpace(),
- OriginTrialContext::GetTokens(document->ToExecutionContext()).get(),
+ GetExecutionContext()->GetContentSecurityPolicy()->Headers(),
+ GetExecutionContext()->GetReferrerPolicy(),
+ GetExecutionContext()->GetSecurityOrigin(),
+ GetExecutionContext()->IsSecureContext(),
+ GetExecutionContext()->GetHttpsState(), worker_clients,
+ nullptr /* content_settings_client */,
+ GetExecutionContext()->GetSecurityContext().AddressSpace(),
+ OriginTrialContext::GetTokens(GetExecutionContext()).get(),
base::UnguessableToken::Create(), std::move(worker_settings),
kV8CacheOptionsDefault,
- MakeGarbageCollected<WorkletModuleResponsesMap>()),
+ MakeGarbageCollected<WorkletModuleResponsesMap>(),
+ mojo::NullRemote() /* browser_interface_broker */,
+ BeginFrameProviderParams(), nullptr /* parent_feature_policy */,
+ GetExecutionContext()->GetAgentClusterID()),
base::nullopt);
}
@@ -235,7 +250,7 @@ class ThreadedWorkletTest : public testing::Test {
messaging_proxy_ =
MakeGarbageCollected<ThreadedWorkletMessagingProxyForTest>(
- page_->GetDocument().ToExecutionContext());
+ page_->GetFrame().DomWindow());
ThreadedWorkletThreadForTest::EnsureSharedBackingThread();
}
@@ -256,6 +271,9 @@ class ThreadedWorkletTest : public testing::Test {
messaging_proxy_->GetWorkerThread());
}
+ ExecutionContext* GetExecutionContext() {
+ return page_->GetFrame().DomWindow();
+ }
Document& GetDocument() { return page_->GetDocument(); }
private:
@@ -273,6 +291,18 @@ TEST_F(ThreadedWorkletTest, SecurityOrigin) {
test::EnterRunLoop();
}
+TEST_F(ThreadedWorkletTest, AgentCluster) {
+ MessagingProxy()->Start();
+
+ // The worklet should be in the owner window's agent cluster.
+ PostCrossThreadTask(
+ *GetWorkerThread()->GetTaskRunner(TaskType::kInternalTest), FROM_HERE,
+ CrossThreadBindOnce(&ThreadedWorkletThreadForTest::TestAgentCluster,
+ CrossThreadUnretained(GetWorkerThread()),
+ GetExecutionContext()->GetAgentClusterID()));
+ test::EnterRunLoop();
+}
+
TEST_F(ThreadedWorkletTest, ContentSecurityPolicy) {
// Set up the CSP for Document before starting ThreadedWorklet because
// ThreadedWorklet inherits the owner Document's CSP.
diff --git a/chromium/third_party/blink/renderer/core/workers/worker_classic_script_loader.cc b/chromium/third_party/blink/renderer/core/workers/worker_classic_script_loader.cc
index e15412a8780..dc1858e41ce 100644
--- a/chromium/third_party/blink/renderer/core/workers/worker_classic_script_loader.cc
+++ b/chromium/third_party/blink/renderer/core/workers/worker_classic_script_loader.cc
@@ -128,7 +128,7 @@ void WorkerClassicScriptLoader::LoadSynchronously(
threadable_loader_ = MakeGarbageCollected<ThreadableLoader>(
execution_context, this, resource_loader_options,
fetch_client_settings_object_fetcher);
- threadable_loader_->Start(request);
+ threadable_loader_->Start(std::move(request));
}
void WorkerClassicScriptLoader::LoadTopLevelScriptAsynchronously(
@@ -175,7 +175,7 @@ void WorkerClassicScriptLoader::LoadTopLevelScriptAsynchronously(
threadable_loader_ = MakeGarbageCollected<ThreadableLoader>(
execution_context, this, resource_loader_options,
fetch_client_settings_object_fetcher);
- threadable_loader_->Start(request);
+ threadable_loader_->Start(std::move(request));
if (failed_)
NotifyFinished();
}
diff --git a/chromium/third_party/blink/renderer/core/workers/worker_global_scope.cc b/chromium/third_party/blink/renderer/core/workers/worker_global_scope.cc
index ee2b239577f..487b17c2e23 100644
--- a/chromium/third_party/blink/renderer/core/workers/worker_global_scope.cc
+++ b/chromium/third_party/blink/renderer/core/workers/worker_global_scope.cc
@@ -45,6 +45,7 @@
#include "third_party/blink/renderer/core/frame/user_activation.h"
#include "third_party/blink/renderer/core/inspector/console_message.h"
#include "third_party/blink/renderer/core/inspector/console_message_storage.h"
+#include "third_party/blink/renderer/core/inspector/inspector_issue_storage.h"
#include "third_party/blink/renderer/core/inspector/worker_inspector_controller.h"
#include "third_party/blink/renderer/core/inspector/worker_thread_debugger.h"
#include "third_party/blink/renderer/core/loader/threadable_loader.h"
@@ -297,7 +298,9 @@ void WorkerGlobalScope::ImportScriptsInternal(const Vector<String>& urls,
source_code.length(), handler ? handler->GetCodeCacheSize() : 0);
ScriptController()->Evaluate(
ScriptSourceCode(source_code, ScriptSourceLocationType::kUnknown,
- handler, response_url),
+ handler,
+ ScriptSourceCode::UsePostRedirectURL() ? response_url
+ : complete_url),
sanitize_script_errors, &error_event, GetV8CacheOptions());
if (error_event) {
ScriptController()->RethrowExceptionFromImportedScript(error_event,
@@ -346,6 +349,12 @@ void WorkerGlobalScope::AddConsoleMessageImpl(ConsoleMessage* console_message,
this, console_message, discard_duplicates);
}
+void WorkerGlobalScope::AddInspectorIssue(
+ mojom::blink::InspectorIssueInfoPtr info) {
+ GetThread()->GetInspectorIssueStorage()->AddInspectorIssue(this,
+ std::move(info));
+}
+
CoreProbeSink* WorkerGlobalScope::GetProbeSink() {
if (IsClosing())
return nullptr;
@@ -369,9 +378,6 @@ void WorkerGlobalScope::EvaluateClassicScript(
std::unique_ptr<Vector<uint8_t>> cached_meta_data,
const v8_inspector::V8StackTraceId& stack_id) {
DCHECK(!IsContextPaused());
- CHECK(!GetExecutionContext()->IsContextDestroyed())
- << "https://crbug.com/930618: worker global scope was destroyed before "
- "evaluating classic script";
SingleCachedMetadataHandler* handler =
CreateWorkerScriptCachedMetadataHandler(script_url,
diff --git a/chromium/third_party/blink/renderer/core/workers/worker_global_scope.h b/chromium/third_party/blink/renderer/core/workers/worker_global_scope.h
index ca49b8c6c14..05935ca9706 100644
--- a/chromium/third_party/blink/renderer/core/workers/worker_global_scope.h
+++ b/chromium/third_party/blink/renderer/core/workers/worker_global_scope.h
@@ -232,6 +232,7 @@ class CORE_EXPORT WorkerGlobalScope
// Used for importScripts().
void ImportScriptsInternal(const Vector<String>& urls, ExceptionState&);
// ExecutionContext
+ void AddInspectorIssue(mojom::blink::InspectorIssueInfoPtr) final;
EventTarget* ErrorEventTarget() final { return this; }
KURL url_;
diff --git a/chromium/third_party/blink/renderer/core/workers/worker_global_scope.idl b/chromium/third_party/blink/renderer/core/workers/worker_global_scope.idl
index 616a02c4ac2..a84f6fd89d6 100644
--- a/chromium/third_party/blink/renderer/core/workers/worker_global_scope.idl
+++ b/chromium/third_party/blink/renderer/core/workers/worker_global_scope.idl
@@ -34,8 +34,7 @@
readonly attribute WorkerGlobalScope self;
readonly attribute WorkerLocation location;
- // TODO(foolip): onerror should be an OnErrorEventHandler.
- attribute EventHandler onerror;
+ attribute OnErrorEventHandler onerror;
attribute EventHandler onlanguagechange;
[RuntimeEnabled=TimeZoneChangeEvent] attribute EventHandler ontimezonechange;
// attribute EventHandler onoffline;
diff --git a/chromium/third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.cc b/chromium/third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.cc
index 141b1d06dda..d39a0d26cec 100644
--- a/chromium/third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.cc
+++ b/chromium/third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.h"
+#include "services/network/public/mojom/web_sandbox_flags.mojom-blink.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/mojom/security_context/insecure_request_policy.mojom-blink.h"
#include "third_party/blink/public/platform/task_type.h"
@@ -13,6 +14,7 @@
#include "third_party/blink/renderer/core/execution_context/agent.h"
#include "third_party/blink/renderer/core/execution_context/security_context_init.h"
#include "third_party/blink/renderer/core/frame/deprecation.h"
+#include "third_party/blink/renderer/core/frame/reporting_context.h"
#include "third_party/blink/renderer/core/inspector/console_message.h"
#include "third_party/blink/renderer/core/loader/loader_factory_for_worker.h"
#include "third_party/blink/renderer/core/loader/modulescript/module_script_fetch_request.h"
@@ -33,6 +35,7 @@
#include "third_party/blink/renderer/platform/loader/fetch/null_resource_fetcher_properties.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_load_observer.h"
+#include "third_party/blink/renderer/platform/weborigin/scheme_registry.h"
#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"
@@ -78,26 +81,13 @@ class OutsideSettingsCSPDelegate final
return outside_settings_object_->GetSecurityOrigin();
}
- SecureContextMode GetSecureContextMode() override {
- DCHECK(global_scope_for_logging_->IsContextThread());
- // TODO(mkwst): This doesn't handle nested workers correctly; we ought to
- // be reading the SecureContextMode from the relevant SecurityContext, but
- // we don't have it here. This code simply checks the worker's origin, which
- // generally works, but would incorrectly consider a secure worker nested in
- // a non-secure worker as a "secure context".
- return outside_settings_object_->GetSecurityOrigin()
- ->IsPotentiallyTrustworthy()
- ? SecureContextMode::kSecureContext
- : SecureContextMode::kInsecureContext;
- }
-
// We don't have to do anything here, as we don't want to update
// SecurityContext of either parent context or WorkerOrWorkletGlobalScope.
// TODO(hiroshige): Revisit the relationship of ContentSecurityPolicy,
// SecurityContext and FetchClientSettingsObject, e.g. when doing
// off-the-main-thread shared worker/service worker top-level script fetch.
// https://crbug.com/924041 https://crbug.com/924043
- void SetSandboxFlags(SandboxFlags) override {}
+ void SetSandboxFlags(network::mojom::blink::WebSandboxFlags) override {}
void SetRequireTrustedTypes() override {}
void AddInsecureRequestPolicy(mojom::blink::InsecureRequestPolicy) override {}
void DisableEval(const String& error_message) override {}
@@ -198,7 +188,7 @@ WorkerOrWorkletGlobalScope::WorkerOrWorkletGlobalScope(
SecurityContextInit(origin,
MakeGarbageCollected<OriginTrialContext>(),
agent),
- SecurityContext::kLocal),
+ SecurityContext::kWorker),
name_(name),
parent_devtools_token_(parent_devtools_token),
worker_clients_(worker_clients),
@@ -265,6 +255,9 @@ void WorkerOrWorkletGlobalScope::CountDeprecation(WebFeature feature) {
return;
used_features_.set(static_cast<size_t>(feature));
+ ReportingContext::From(this)->QueueReport(
+ Deprecation::CreateReport(Url(), feature));
+
// Adds a deprecation message to the console.
DCHECK(!Deprecation::DeprecationMessage(feature).IsEmpty());
AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>(
@@ -274,6 +267,18 @@ void WorkerOrWorkletGlobalScope::CountDeprecation(WebFeature feature) {
ReportingProxy().CountDeprecation(feature);
}
+ResourceLoadScheduler::ThrottleOptionOverride
+WorkerOrWorkletGlobalScope::GetThrottleOptionOverride() const {
+ return ResourceLoadScheduler::ThrottleOptionOverride::kNone;
+}
+
+void WorkerOrWorkletGlobalScope::UpdateFetcherThrottleOptionOverride() {
+ if (inside_settings_resource_fetcher_) {
+ inside_settings_resource_fetcher_->SetThrottleOptionOverride(
+ GetThrottleOptionOverride());
+ }
+}
+
void WorkerOrWorkletGlobalScope::InitializeWebFetchContextIfNeeded() {
if (web_fetch_context_initialized_)
return;
@@ -336,6 +341,20 @@ ResourceFetcher* WorkerOrWorkletGlobalScope::CreateFetcherInternal(
*this, web_worker_fetch_context_));
init.use_counter = MakeGarbageCollected<DetachableUseCounter>(this);
init.console_logger = MakeGarbageCollected<DetachableConsoleLogger>(this);
+
+ // Potentially support throttling network requests from a worker. Note,
+ // this does not work currently for worklets, but worklets should not be
+ // able to make network requests anyway.
+ if (IsWorkerGlobalScope()) {
+ init.frame_or_worker_scheduler = GetScheduler();
+
+ // The only network requests possible from a worker are
+ // RequestContext::FETCH which are not normally throttlable.
+ // Possibly override this restriction so network from a throttled
+ // worker will also be throttled.
+ init.throttle_option_override = GetThrottleOptionOverride();
+ }
+
fetcher = MakeGarbageCollected<ResourceFetcher>(init);
fetcher->SetResourceLoadObserver(
MakeGarbageCollected<ResourceLoadObserverForWorker>(
@@ -370,6 +389,9 @@ ResourceFetcher* WorkerOrWorkletGlobalScope::CreateOutsideSettingsFetcher(
DCHECK(IsContextThread());
auto* content_security_policy = MakeGarbageCollected<ContentSecurityPolicy>();
+ content_security_policy->SetSupportsWasmEval(
+ SchemeRegistry::SchemeSupportsWasmEvalCSP(
+ outside_settings_object.GetSecurityOrigin()->Protocol()));
for (const auto& policy_and_type : outside_content_security_policy_headers_) {
content_security_policy->DidReceiveHeader(
policy_and_type.first, policy_and_type.second,
@@ -423,9 +445,10 @@ WorkerOrWorkletGlobalScope::GetTaskRunner(TaskType type) {
return GetThread()->GetTaskRunner(type);
}
-void WorkerOrWorkletGlobalScope::ApplySandboxFlags(SandboxFlags mask) {
+void WorkerOrWorkletGlobalScope::ApplySandboxFlags(
+ network::mojom::blink::WebSandboxFlags mask) {
GetSecurityContext().ApplySandboxFlags(mask);
- if (IsSandboxed(mojom::blink::WebSandboxFlags::kOrigin) &&
+ if (IsSandboxed(network::mojom::blink::WebSandboxFlags::kOrigin) &&
!GetSecurityOrigin()->IsOpaque()) {
GetSecurityContext().SetSecurityOrigin(
GetSecurityOrigin()->DeriveNewOpaqueOrigin());
@@ -441,6 +464,8 @@ void WorkerOrWorkletGlobalScope::InitContentSecurityPolicyFromVector(
const Vector<CSPHeaderAndType>& headers) {
if (!GetContentSecurityPolicy()) {
auto* csp = MakeGarbageCollected<ContentSecurityPolicy>();
+ csp->SetSupportsWasmEval(SchemeRegistry::SchemeSupportsWasmEvalCSP(
+ GetSecurityOrigin()->Protocol()));
GetSecurityContext().SetContentSecurityPolicy(csp);
}
for (const auto& policy_and_type : headers) {
@@ -510,6 +535,16 @@ void WorkerOrWorkletGlobalScope::SetDefersLoadingForResourceFetchers(
resource_fetcher->SetDefersLoading(defers);
}
+int WorkerOrWorkletGlobalScope::GetOutstandingThrottledLimit() const {
+ // Default to what has been a typical throttle limit for iframes. Note,
+ // however, this value is largely meaningless unless the global has set
+ // a ThrottleOptionOverride. Workers can only make fetch/xhr requests
+ // which are not throttlable by default. If GetThrottleOptionOverride()
+ // is overridden, then this method should also be overridden with a
+ // more meaningful value.
+ return 2;
+}
+
void WorkerOrWorkletGlobalScope::Trace(Visitor* visitor) {
visitor->Trace(security_context_);
visitor->Trace(inside_settings_resource_fetcher_);
diff --git a/chromium/third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.h b/chromium/third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.h
index 5b8588e87fa..e09324a71e5 100644
--- a/chromium/third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.h
+++ b/chromium/third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.h
@@ -8,6 +8,7 @@
#include <bitset>
#include "base/single_thread_task_runner.h"
#include "services/network/public/mojom/fetch_api.mojom-blink-forward.h"
+#include "services/network/public/mojom/web_sandbox_flags.mojom-blink-forward.h"
#include "third_party/blink/public/platform/web_url_request.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_cache_options.h"
#include "third_party/blink/renderer/core/core_export.h"
@@ -19,6 +20,7 @@
#include "third_party/blink/renderer/core/workers/global_scope_creation_params.h"
#include "third_party/blink/renderer/core/workers/worker_clients.h"
#include "third_party/blink/renderer/core/workers/worker_navigator.h"
+#include "third_party/blink/renderer/platform/loader/fetch/resource_load_scheduler.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_loader_options.h"
#include "third_party/blink/renderer/platform/scheduler/public/worker_scheduler.h"
#include "third_party/blink/renderer/platform/wtf/casting.h"
@@ -152,10 +154,12 @@ class CORE_EXPORT WorkerOrWorkletGlobalScope : public EventTargetWithInlineData,
scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner(TaskType) override;
- void ApplySandboxFlags(SandboxFlags mask);
+ void ApplySandboxFlags(network::mojom::blink::WebSandboxFlags mask);
void SetDefersLoadingForResourceFetchers(bool defers);
+ virtual int GetOutstandingThrottledLimit() const;
+
protected:
// Sets outside's CSP used for off-main-thread top-level worker script
// fetch.
@@ -187,6 +191,13 @@ class CORE_EXPORT WorkerOrWorkletGlobalScope : public EventTargetWithInlineData,
return web_worker_fetch_context_.get();
}
+ virtual ResourceLoadScheduler::ThrottleOptionOverride
+ GetThrottleOptionOverride() const;
+
+ // This method must be call after the fetcher is created if conditions
+ // change such that a different ThrottleOptionOverride should be applied.
+ void UpdateFetcherThrottleOptionOverride();
+
private:
void InitializeWebFetchContextIfNeeded();
ResourceFetcher* CreateFetcherInternal(const FetchClientSettingsObject&,
diff --git a/chromium/third_party/blink/renderer/core/workers/worker_thread.cc b/chromium/third_party/blink/renderer/core/workers/worker_thread.cc
index d11b948c6de..fe98ad619b9 100644
--- a/chromium/third_party/blink/renderer/core/workers/worker_thread.cc
+++ b/chromium/third_party/blink/renderer/core/workers/worker_thread.cc
@@ -36,6 +36,7 @@
#include "third_party/blink/renderer/bindings/core/v8/worker_or_worklet_script_controller.h"
#include "third_party/blink/renderer/core/execution_context/agent.h"
#include "third_party/blink/renderer/core/inspector/console_message_storage.h"
+#include "third_party/blink/renderer/core/inspector/inspector_issue_storage.h"
#include "third_party/blink/renderer/core/inspector/inspector_task_runner.h"
#include "third_party/blink/renderer/core/inspector/worker_devtools_params.h"
#include "third_party/blink/renderer/core/inspector/worker_inspector_controller.h"
@@ -570,6 +571,7 @@ void WorkerThread::InitializeOnWorkerThread(
const KURL url_for_debugger = global_scope_creation_params->script_url;
console_message_storage_ = MakeGarbageCollected<ConsoleMessageStorage>();
+ inspector_issue_storage_ = MakeGarbageCollected<InspectorIssueStorage>();
global_scope_ =
CreateWorkerGlobalScope(std::move(global_scope_creation_params));
worker_reporting_proxy_.DidCreateWorkerGlobalScope(GlobalScope());
@@ -623,12 +625,6 @@ void WorkerThread::EvaluateClassicScriptOnWorkerThread(
String source_code,
std::unique_ptr<Vector<uint8_t>> cached_meta_data,
const v8_inspector::V8StackTraceId& stack_id) {
- // TODO(crbug.com/930618): Remove this check after we identified the cause
- // of the crash.
- {
- MutexLocker lock(mutex_);
- CHECK_EQ(ThreadState::kRunning, thread_state_);
- }
WorkerGlobalScope* global_scope = To<WorkerGlobalScope>(GlobalScope());
CHECK(global_scope);
global_scope->EvaluateClassicScript(script_url, std::move(source_code),
@@ -734,6 +730,7 @@ void WorkerThread::PerformShutdownOnWorkerThread() {
global_scope_ = nullptr;
console_message_storage_.Clear();
+ inspector_issue_storage_.Clear();
if (IsOwningBackingThread())
GetWorkerBackingThread().ShutdownOnBackingThread();
diff --git a/chromium/third_party/blink/renderer/core/workers/worker_thread.h b/chromium/third_party/blink/renderer/core/workers/worker_thread.h
index 6dbb1009c9e..7d05b387d4c 100644
--- a/chromium/third_party/blink/renderer/core/workers/worker_thread.h
+++ b/chromium/third_party/blink/renderer/core/workers/worker_thread.h
@@ -58,6 +58,7 @@ namespace blink {
class ConsoleMessageStorage;
class InspectorTaskRunner;
+class InspectorIssueStorage;
class WorkerBackingThread;
class WorkerInspectorController;
class WorkerOrWorkletGlobalScope;
@@ -162,6 +163,9 @@ class CORE_EXPORT WorkerThread : public Thread::TaskObserver {
ConsoleMessageStorage* GetConsoleMessageStorage() const {
return console_message_storage_.Get();
}
+ InspectorIssueStorage* GetInspectorIssueStorage() const {
+ return inspector_issue_storage_.Get();
+ }
v8::Isolate* GetIsolate();
bool IsCurrentThread();
@@ -436,6 +440,7 @@ class CORE_EXPORT WorkerThread : public Thread::TaskObserver {
Platform::NestedMessageLoopRunner* nested_runner_ = nullptr;
CrossThreadPersistent<ConsoleMessageStorage> console_message_storage_;
+ CrossThreadPersistent<InspectorIssueStorage> inspector_issue_storage_;
CrossThreadPersistent<WorkerOrWorkletGlobalScope> global_scope_;
CrossThreadPersistent<WorkerInspectorController> worker_inspector_controller_;
diff --git a/chromium/third_party/blink/renderer/core/workers/worker_thread_test.cc b/chromium/third_party/blink/renderer/core/workers/worker_thread_test.cc
index a0da94e16c1..19d23ec871f 100644
--- a/chromium/third_party/blink/renderer/core/workers/worker_thread_test.cc
+++ b/chromium/third_party/blink/renderer/core/workers/worker_thread_test.cc
@@ -492,7 +492,8 @@ TEST_F(WorkerThreadTest, Terminate_WhileDebuggerTaskIsRunning) {
EXPECT_EQ(ExitCode::kGracefullyTerminated, GetExitCode());
}
-TEST_F(WorkerThreadTest, TerminateWorkerWhileChildIsLoading) {
+// TODO(https://crbug.com/1072997): This test occasionally crashes.
+TEST_F(WorkerThreadTest, DISABLED_TerminateWorkerWhileChildIsLoading) {
ExpectReportingCalls();
Start();
worker_thread_->WaitForInit();
diff --git a/chromium/third_party/blink/renderer/core/workers/worklet.cc b/chromium/third_party/blink/renderer/core/workers/worklet.cc
index 0659d33f6c2..9148ae9a367 100644
--- a/chromium/third_party/blink/renderer/core/workers/worklet.cc
+++ b/chromium/third_party/blink/renderer/core/workers/worklet.cc
@@ -12,9 +12,9 @@
#include "third_party/blink/public/platform/web_url_request.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_worklet_options.h"
-#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
#include "third_party/blink/renderer/core/fetch/request.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/loader/worker_resource_timing_notifier_impl.h"
#include "third_party/blink/renderer/core/workers/worklet_pending_tasks.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
@@ -26,8 +26,8 @@
namespace blink {
-Worklet::Worklet(Document* document)
- : ExecutionContextLifecycleObserver(document),
+Worklet::Worklet(LocalDOMWindow& window)
+ : ExecutionContextLifecycleObserver(&window),
module_responses_map_(MakeGarbageCollected<WorkletModuleResponsesMap>()) {
DCHECK(IsMainThread());
}
diff --git a/chromium/third_party/blink/renderer/core/workers/worklet.h b/chromium/third_party/blink/renderer/core/workers/worklet.h
index ecf4340a6c4..4b747f7cb87 100644
--- a/chromium/third_party/blink/renderer/core/workers/worklet.h
+++ b/chromium/third_party/blink/renderer/core/workers/worklet.h
@@ -16,7 +16,7 @@
namespace blink {
-class Document;
+class LocalDOMWindow;
class WorkletOptions;
// This is the base implementation of Worklet interface defined in the spec:
@@ -54,7 +54,7 @@ class CORE_EXPORT Worklet : public ScriptWrappable,
void Trace(Visitor*) override;
protected:
- explicit Worklet(Document*);
+ explicit Worklet(LocalDOMWindow&);
// Returns one of available global scopes.
WorkletGlobalScopeProxy* FindAvailableGlobalScope();
diff --git a/chromium/third_party/blink/renderer/core/workers/worklet.idl b/chromium/third_party/blink/renderer/core/workers/worklet.idl
index cb4571e9baf..bc08a8470d3 100644
--- a/chromium/third_party/blink/renderer/core/workers/worklet.idl
+++ b/chromium/third_party/blink/renderer/core/workers/worklet.idl
@@ -5,6 +5,7 @@
// https://drafts.css-houdini.org/worklets/#worklet
[
+ Exposed=Window,
SecureContext
] interface Worklet {
[CallWith=ScriptState, RaisesException] Promise<void> addModule(USVString moduleURL, optional WorkletOptions options = {});
diff --git a/chromium/third_party/blink/renderer/core/workers/worklet_global_scope.cc b/chromium/third_party/blink/renderer/core/workers/worklet_global_scope.cc
index 6e760135057..5f2f2a191ae 100644
--- a/chromium/third_party/blink/renderer/core/workers/worklet_global_scope.cc
+++ b/chromium/third_party/blink/renderer/core/workers/worklet_global_scope.cc
@@ -10,10 +10,12 @@
#include "third_party/blink/renderer/bindings/core/v8/script_source_code.h"
#include "third_party/blink/renderer/bindings/core/v8/source_location.h"
#include "third_party/blink/renderer/bindings/core/v8/worker_or_worklet_script_controller.h"
+#include "third_party/blink/renderer/core/execution_context/agent.h"
#include "third_party/blink/renderer/core/frame/frame_console.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/inspector/console_message.h"
#include "third_party/blink/renderer/core/inspector/console_message_storage.h"
+#include "third_party/blink/renderer/core/inspector/inspector_issue_storage.h"
#include "third_party/blink/renderer/core/inspector/main_thread_debugger.h"
#include "third_party/blink/renderer/core/inspector/worker_thread_debugger.h"
#include "third_party/blink/renderer/core/origin_trials/origin_trial_context.h"
@@ -33,14 +35,14 @@ WorkletGlobalScope::WorkletGlobalScope(
std::unique_ptr<GlobalScopeCreationParams> creation_params,
WorkerReportingProxy& reporting_proxy,
LocalFrame* frame,
- Agent* agent)
+ bool create_microtask_queue)
: WorkletGlobalScope(std::move(creation_params),
reporting_proxy,
ToIsolate(frame),
ThreadType::kMainThread,
frame,
nullptr /* worker_thread */,
- agent) {}
+ create_microtask_queue) {}
WorkletGlobalScope::WorkletGlobalScope(
std::unique_ptr<GlobalScopeCreationParams> creation_params,
@@ -52,7 +54,7 @@ WorkletGlobalScope::WorkletGlobalScope(
ThreadType::kOffMainThread,
nullptr /* frame */,
worker_thread,
- nullptr /* agent */) {}
+ false /* create_microtask_queue */) {}
// Partial implementation of the "set up a worklet environment settings object"
// algorithm:
@@ -64,13 +66,17 @@ WorkletGlobalScope::WorkletGlobalScope(
ThreadType thread_type,
LocalFrame* frame,
WorkerThread* worker_thread,
- Agent* agent)
+ bool create_microtask_queue)
: WorkerOrWorkletGlobalScope(
isolate,
SecurityOrigin::CreateUniqueOpaque(),
- // TODO(tzik): Assign an Agent for Worklets after
- // NonMainThreadScheduler gets ready to run microtasks.
- agent,
+ MakeGarbageCollected<Agent>(
+ isolate,
+ creation_params->agent_cluster_id,
+ create_microtask_queue
+ ? v8::MicrotaskQueue::New(isolate,
+ v8::MicrotasksPolicy::kScoped)
+ : nullptr),
creation_params->global_scope_name,
creation_params->parent_devtools_token,
creation_params->v8_cache_options,
@@ -85,15 +91,16 @@ WorkletGlobalScope::WorkletGlobalScope(
module_responses_map_(creation_params->module_responses_map),
// Step 4. "Let inheritedHTTPSState be outsideSettings's HTTPS state."
https_state_(creation_params->starter_https_state),
- agent_cluster_id_(creation_params->agent_cluster_id.is_empty()
- ? base::UnguessableToken::Create()
- : creation_params->agent_cluster_id),
thread_type_(thread_type),
frame_(frame),
worker_thread_(worker_thread) {
DCHECK((thread_type_ == ThreadType::kMainThread && frame_) ||
(thread_type_ == ThreadType::kOffMainThread && worker_thread_));
+ // Worklet should be in the owner's agent cluster.
+ // https://html.spec.whatwg.org/C/#obtain-a-worklet-agent
+ DCHECK(creation_params->agent_cluster_id);
+
// Step 2: "Let inheritedAPIBaseURL be outsideSettings's API base URL."
// |url_| is the inheritedAPIBaseURL passed from the parent Document.
@@ -152,6 +159,16 @@ void WorkletGlobalScope::AddConsoleMessageImpl(ConsoleMessage* console_message,
worker_thread_->GlobalScope(), console_message, discard_duplicates);
}
+void WorkletGlobalScope::AddInspectorIssue(
+ mojom::blink::InspectorIssueInfoPtr info) {
+ if (IsMainThreadWorkletGlobalScope()) {
+ frame_->AddInspectorIssue(std::move(info));
+ } else {
+ worker_thread_->GetInspectorIssueStorage()->AddInspectorIssue(
+ this, std::move(info));
+ }
+}
+
void WorkletGlobalScope::ExceptionThrown(ErrorEvent* error_event) {
if (IsMainThreadWorkletGlobalScope()) {
MainThreadDebugger::Instance()->ExceptionThrown(this, error_event);
diff --git a/chromium/third_party/blink/renderer/core/workers/worklet_global_scope.h b/chromium/third_party/blink/renderer/core/workers/worklet_global_scope.h
index 55db96228c7..f6153a47998 100644
--- a/chromium/third_party/blink/renderer/core/workers/worklet_global_scope.h
+++ b/chromium/third_party/blink/renderer/core/workers/worklet_global_scope.h
@@ -59,6 +59,7 @@ class CORE_EXPORT WorkletGlobalScope
String UserAgent() const final { return user_agent_; }
bool IsContextThread() const final;
void AddConsoleMessageImpl(ConsoleMessage*, bool discard_duplicates) final;
+ void AddInspectorIssue(mojom::blink::InspectorIssueInfoPtr) final;
void ExceptionThrown(ErrorEvent*) final;
CoreProbeSink* GetProbeSink() final;
scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner(TaskType) final;
@@ -70,18 +71,6 @@ class CORE_EXPORT WorkletGlobalScope
virtual LocalFrame* GetFrame() const;
- const base::UnguessableToken& GetAgentClusterID() const final {
- // Currently, worklet agents have no clearly defined owner. See
- // https://html.spec.whatwg.org/C/#integration-with-the-javascript-agent-cluster-formalism
- //
- // However, it is intended that a SharedArrayBuffer can be shared with a
- // worklet, e.g. the AudioWorklet. If this WorkletGlobalScope's creation
- // params included an agent cluster ID, we'll assume that this worklet is
- // in the same agent cluster. See
- // https://bugs.chromium.org/p/chromium/issues/detail?id=892067.
- return agent_cluster_id_;
- }
-
// Implementation of the "fetch and invoke a worklet script" algorithm:
// https://drafts.css-houdini.org/worklets/#fetch-and-invoke-a-worklet-script
// When script evaluation is done or any exception happens, it's notified to
@@ -118,10 +107,13 @@ class CORE_EXPORT WorkletGlobalScope
// Constructs an instance as a main thread worklet. Must be called on the main
// thread.
+ // When |create_microtask_queue| is true, creates a microtask queue separated
+ // from the Isolate's default microtask queue.
WorkletGlobalScope(std::unique_ptr<GlobalScopeCreationParams>,
WorkerReportingProxy&,
LocalFrame*,
- Agent* = nullptr);
+ bool create_microtask_queue);
+
// Constructs an instance as a threaded worklet. Must be called on a worker
// thread.
WorkletGlobalScope(std::unique_ptr<GlobalScopeCreationParams>,
@@ -148,7 +140,7 @@ class CORE_EXPORT WorkletGlobalScope
ThreadType,
LocalFrame*,
WorkerThread*,
- Agent*);
+ bool create_microtask_queue);
EventTarget* ErrorEventTarget() final { return nullptr; }
@@ -169,8 +161,6 @@ class CORE_EXPORT WorkletGlobalScope
const HttpsState https_state_;
- const base::UnguessableToken agent_cluster_id_;
-
const ThreadType thread_type_;
// |frame_| is available only when |thread_type_| is kMainThread.
Member<LocalFrame> frame_;
diff --git a/chromium/third_party/blink/renderer/core/workers/worklet_module_tree_client.cc b/chromium/third_party/blink/renderer/core/workers/worklet_module_tree_client.cc
index 6478a7a6a86..3e0011f7ba8 100644
--- a/chromium/third_party/blink/renderer/core/workers/worklet_module_tree_client.cc
+++ b/chromium/third_party/blink/renderer/core/workers/worklet_module_tree_client.cc
@@ -56,8 +56,8 @@ void WorkletModuleTreeClient::NotifyModuleTreeLoadFinished(
// Step 4: "If script's error to rethrow is not null, then queue a task on
// outsideSettings's responsible event loop given script's error to rethrow to
// run these steps:
+ ScriptState::Scope scope(script_state_);
if (module_script->HasErrorToRethrow()) {
- ScriptState::Scope scope(script_state_);
PostCrossThreadTask(
*outside_settings_task_runner_, FROM_HERE,
CrossThreadBindOnce(
@@ -70,7 +70,7 @@ void WorkletModuleTreeClient::NotifyModuleTreeLoadFinished(
}
// Step 5: "Run a module script given script."
- ScriptValue error =
+ ModuleEvaluationResult result =
Modulator::From(script_state_)
->ExecuteModule(module_script,
Modulator::CaptureEvalErrorFlag::kReport);
@@ -78,7 +78,7 @@ void WorkletModuleTreeClient::NotifyModuleTreeLoadFinished(
auto* global_scope =
To<WorkletGlobalScope>(ExecutionContext::From(script_state_));
- global_scope->ReportingProxy().DidEvaluateModuleScript(error.IsEmpty());
+ global_scope->ReportingProxy().DidEvaluateModuleScript(result.IsSuccess());
// Step 6: "Queue a task on outsideSettings's responsible event loop to run
// these steps:"
diff --git a/chromium/third_party/blink/renderer/core/xml/document_xslt.cc b/chromium/third_party/blink/renderer/core/xml/document_xslt.cc
index ba5a7c1d995..4ad397ea7a2 100644
--- a/chromium/third_party/blink/renderer/core/xml/document_xslt.cc
+++ b/chromium/third_party/blink/renderer/core/xml/document_xslt.cc
@@ -11,6 +11,7 @@
#include "third_party/blink/renderer/core/dom/node.h"
#include "third_party/blink/renderer/core/dom/processing_instruction.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/web_feature.h"
#include "third_party/blink/renderer/core/probe/core_probes.h"
#include "third_party/blink/renderer/core/xml/xsl_style_sheet.h"
@@ -34,7 +35,7 @@ class DOMContentLoadedListener final
DCHECK(RuntimeEnabledFeatures::XSLTEnabled());
DCHECK_EQ(event->type(), "DOMContentLoaded");
- Document& document = *Document::From(execution_context);
+ Document& document = *To<LocalDOMWindow>(execution_context)->document();
DCHECK(!document.Parsing());
// Processing instruction (XML documents only).
diff --git a/chromium/third_party/blink/renderer/core/xml/dom_parser.cc b/chromium/third_party/blink/renderer/core/xml/dom_parser.cc
index c03568e633e..e66ec1de7c2 100644
--- a/chromium/third_party/blink/renderer/core/xml/dom_parser.cc
+++ b/chromium/third_party/blink/renderer/core/xml/dom_parser.cc
@@ -21,6 +21,7 @@
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/document_init.h"
#include "third_party/blink/renderer/core/dom/dom_implementation.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
@@ -30,28 +31,26 @@ namespace blink {
Document* DOMParser::parseFromString(const String& str, const String& type) {
Document* doc = DOMImplementation::createDocument(
DocumentInit::Create()
+ .WithURL(GetDocument()->Url())
.WithTypeFrom(type)
- .WithContextDocument(context_document_)
- .WithOwnerDocument(context_document_)
+ .WithContextDocument(GetDocument())
+ .WithOwnerDocument(GetDocument())
.WithContentSecurityPolicyFromContextDoc());
doc->SetContent(str);
doc->SetMimeType(AtomicString(type));
- if (context_document_) {
- doc->SetURL(context_document_->Url());
- }
return doc;
}
-DOMParser::DOMParser(Document& document)
- : context_document_(document.ContextDocument()) {}
+DOMParser::DOMParser(ScriptState* script_state)
+ : window_(LocalDOMWindow::From(script_state)) {}
void DOMParser::Trace(Visitor* visitor) {
- visitor->Trace(context_document_);
+ visitor->Trace(window_);
ScriptWrappable::Trace(visitor);
}
Document* DOMParser::GetDocument() const {
- return context_document_.Get();
+ return window_->document();
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/xml/dom_parser.h b/chromium/third_party/blink/renderer/core/xml/dom_parser.h
index 058ee51a3c0..9bd336929f3 100644
--- a/chromium/third_party/blink/renderer/core/xml/dom_parser.h
+++ b/chromium/third_party/blink/renderer/core/xml/dom_parser.h
@@ -27,16 +27,18 @@
namespace blink {
class Document;
+class LocalDOMWindow;
+class ScriptState;
class DOMParser final : public ScriptWrappable {
DEFINE_WRAPPERTYPEINFO();
public:
- static DOMParser* Create(Document& document) {
- return MakeGarbageCollected<DOMParser>(document);
+ static DOMParser* Create(ScriptState* script_state) {
+ return MakeGarbageCollected<DOMParser>(script_state);
}
- explicit DOMParser(Document&);
+ explicit DOMParser(ScriptState*);
Document* parseFromString(const String&, const String& type);
@@ -45,7 +47,7 @@ class DOMParser final : public ScriptWrappable {
Document* GetDocument() const;
private:
- WeakMember<Document> context_document_;
+ WeakMember<LocalDOMWindow> window_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/xml/dom_parser.idl b/chromium/third_party/blink/renderer/core/xml/dom_parser.idl
index 26dbfd80754..67b6dc0b2bd 100644
--- a/chromium/third_party/blink/renderer/core/xml/dom_parser.idl
+++ b/chromium/third_party/blink/renderer/core/xml/dom_parser.idl
@@ -30,6 +30,6 @@ enum SupportedType {
[
Exposed=Window
] interface DOMParser {
- [CallWith=Document] constructor();
+ [CallWith=ScriptState] constructor();
[NewObject] Document parseFromString(HTMLString str, SupportedType type);
};
diff --git a/chromium/third_party/blink/renderer/core/xml/xpath_evaluator.idl b/chromium/third_party/blink/renderer/core/xml/xpath_evaluator.idl
index 595ed6610dd..442506ae8ab 100644
--- a/chromium/third_party/blink/renderer/core/xml/xpath_evaluator.idl
+++ b/chromium/third_party/blink/renderer/core/xml/xpath_evaluator.idl
@@ -17,16 +17,14 @@
* Boston, MA 02110-1301, USA.
*/
-// http://www.w3.org/TR/DOM-Level-3-XPath/xpath.html#XPathEvaluator
+// https://dom.spec.whatwg.org/#interface-xpathevaluator
-// Note: The spec says "the XPathEvaluator interface will be implemented on the
-// same object which implements the Document interface" and does not define a
-// constructor or other means to create an XPathEvaluator object. Nonetheless,
-// Blink, Gecko, Presto, WebKit and all have these APIs on both Document and the
-// constructable XPathEvaluator interface.
-
-interface XPathEvaluator {
+[
+ Exposed=Window
+] interface XPathEvaluator {
[Measure] constructor();
+
+ // https://dom.spec.whatwg.org/#mixin-xpathevaluatorbase
[Measure, RaisesException] XPathExpression createExpression(DOMString expression, optional XPathNSResolver? resolver = null);
[Measure] XPathNSResolver createNSResolver(Node nodeResolver);
diff --git a/chromium/third_party/blink/renderer/core/xml/xpath_expression.idl b/chromium/third_party/blink/renderer/core/xml/xpath_expression.idl
index 80d810ffc84..50a935eb065 100644
--- a/chromium/third_party/blink/renderer/core/xml/xpath_expression.idl
+++ b/chromium/third_party/blink/renderer/core/xml/xpath_expression.idl
@@ -18,8 +18,10 @@
* Boston, MA 02110-1301, USA.
*/
-// http://www.w3.org/TR/DOM-Level-3-XPath/xpath.html#XPathExpression
+// https://dom.spec.whatwg.org/#interface-xpathexpression
-interface XPathExpression {
+[
+ Exposed=Window
+] interface XPathExpression {
[RaisesException] XPathResult evaluate(Node contextNode, optional unsigned short type = 0, optional object? inResult = null);
};
diff --git a/chromium/third_party/blink/renderer/core/xml/xpath_result.idl b/chromium/third_party/blink/renderer/core/xml/xpath_result.idl
index 0a87159f8bc..cfc0998dd02 100644
--- a/chromium/third_party/blink/renderer/core/xml/xpath_result.idl
+++ b/chromium/third_party/blink/renderer/core/xml/xpath_result.idl
@@ -17,9 +17,11 @@
* Boston, MA 02110-1301, USA.
*/
-// http://www.w3.org/TR/DOM-Level-3-XPath/xpath.html#XPathResult
+// https://dom.spec.whatwg.org/#interface-xpathresult
-interface XPathResult {
+[
+ Exposed=Window
+] interface XPathResult {
// XPathResultType
const unsigned short ANY_TYPE = 0;
const unsigned short NUMBER_TYPE = 1;
diff --git a/chromium/third_party/blink/renderer/core/xml/xslt_processor.cc b/chromium/third_party/blink/renderer/core/xml/xslt_processor.cc
index 575ec97aeb5..49782f0c144 100644
--- a/chromium/third_party/blink/renderer/core/xml/xslt_processor.cc
+++ b/chromium/third_party/blink/renderer/core/xml/xslt_processor.cc
@@ -72,66 +72,43 @@ Document* XSLTProcessor::CreateDocumentFromSource(
Document* owner_document = &source_node->GetDocument();
if (owner_document == source_node)
url = owner_document->Url();
-
- DocumentInit init =
- DocumentInit::Create()
- .WithDocumentLoader(frame ? frame->Loader().GetDocumentLoader()
- : nullptr)
- .WithURL(url)
- .WithTypeFrom(source_mime_type);
-
String document_source = source_string;
- bool force_xhtml = source_mime_type == "text/plain";
- if (force_xhtml)
- TransformTextStringToXHTMLDocumentString(document_source);
- Document* result = nullptr;
+ String mime_type = source_mime_type;
+ // Force text/plain to be parsed as XHTML. This was added without explanation
+ // in 2005:
+ // https://chromium.googlesource.com/chromium/src/+/e20d8de86f154892d94798bbd8b65720a11d6299
+ // It's unclear whether it's still needed for compat.
+ if (source_mime_type == "text/plain") {
+ mime_type = "application/xhtml+xml";
+ TransformTextStringToXHTMLDocumentString(document_source);
+ }
if (frame) {
- Document* old_document = frame->GetDocument();
- init = init.WithOwnerDocument(old_document)
- .WithSandboxFlags(old_document->GetSandboxFlags());
-
- // Before parsing, we need to save & detach the old document and get the new
- // document in place. Document::Shutdown() tears down the LocalFrameView, so
- // remember whether or not there was one.
- bool has_view = frame->View();
- {
- SubframeLoadingDisabler disabler(old_document);
- IgnoreOpensDuringUnloadCountIncrementer ignore_opens_during_unload(
- old_document);
- frame->DetachChildren();
- if (!frame->Client())
- return nullptr;
-
- old_document->Shutdown();
- }
- // Re-create the LocalFrameView if needed.
- if (has_view)
- frame->Client()->TransitionToCommittedForNewPage();
- result = frame->DomWindow()->InstallNewDocument(init, force_xhtml);
-
- if (old_document) {
- DocumentXSLT::From(*result).SetTransformSourceDocument(old_document);
- result->SetCookieURL(old_document->CookieURL());
-
- auto* csp = MakeGarbageCollected<ContentSecurityPolicy>();
- csp->CopyStateFrom(old_document->GetContentSecurityPolicy());
- result->InitContentSecurityPolicy(csp);
- }
- } else {
- init = init.WithContextDocument(owner_document->ContextDocument());
- result = LocalDOMWindow::CreateDocument(init, force_xhtml);
+ auto params = std::make_unique<WebNavigationParams>();
+ params->url = url;
+ WebNavigationParams::FillStaticResponse(
+ params.get(), mime_type,
+ source_encoding.IsEmpty() ? "UTF-8" : source_encoding,
+ StringUTF8Adaptor(document_source));
+ frame->Loader().CommitNavigation(std::move(params), nullptr,
+ CommitReason::kXSLT);
+ return frame->GetDocument();
}
+ DocumentInit init =
+ DocumentInit::Create()
+ .WithURL(url)
+ .WithTypeFrom(mime_type)
+ .WithContextDocument(owner_document->ContextDocument());
+ Document* document = DOMImplementation::createDocument(init);
DocumentEncodingData data;
data.SetEncoding(source_encoding.IsEmpty()
? UTF8Encoding()
: WTF::TextEncoding(source_encoding));
- result->SetEncodingData(data);
- result->SetContent(document_source);
-
- return result;
+ document->SetEncodingData(data);
+ document->SetContent(document_source);
+ return document;
}
Document* XSLTProcessor::transformToDocument(Node* source_node) {
diff --git a/chromium/third_party/blink/renderer/core/xml/xslt_processor.idl b/chromium/third_party/blink/renderer/core/xml/xslt_processor.idl
index f6ea356cfd1..6217fa81601 100644
--- a/chromium/third_party/blink/renderer/core/xml/xslt_processor.idl
+++ b/chromium/third_party/blink/renderer/core/xml/xslt_processor.idl
@@ -31,6 +31,7 @@
// https://hg.mozilla.org/mozilla-central/file/012853bd80b7/dom/webidl/XSLTProcessor.webidl
[
+ Exposed=Window,
RuntimeEnabled=XSLT
] interface XSLTProcessor {
[CallWith=Document, MeasureAs=XSLTProcessor] constructor();
diff --git a/chromium/third_party/blink/renderer/core/xmlhttprequest/main_thread_disallow_synchronous_xhr_scope.cc b/chromium/third_party/blink/renderer/core/xmlhttprequest/main_thread_disallow_synchronous_xhr_scope.cc
index 677a775e9b3..66063a80324 100644
--- a/chromium/third_party/blink/renderer/core/xmlhttprequest/main_thread_disallow_synchronous_xhr_scope.cc
+++ b/chromium/third_party/blink/renderer/core/xmlhttprequest/main_thread_disallow_synchronous_xhr_scope.cc
@@ -4,7 +4,7 @@
#include "third_party/blink/renderer/core/xmlhttprequest/main_thread_disallow_synchronous_xhr_scope.h"
-#include "base/logging.h"
+#include "base/check.h"
#include "third_party/blink/renderer/platform/wtf/wtf.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.cc b/chromium/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.cc
index 721fc7b15f8..2f3330e03ed 100644
--- a/chromium/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.cc
+++ b/chromium/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.cc
@@ -30,6 +30,7 @@
#include "base/feature_list.h"
#include "base/metrics/histogram_macros.h"
#include "base/time/time.h"
+#include "services/network/public/mojom/trust_tokens.mojom-shared.h"
#include "third_party/blink/public/common/blob/blob_utils.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/mojom/feature_policy/feature_policy.mojom-blink-forward.h"
@@ -47,6 +48,7 @@
#include "third_party/blink/renderer/core/editing/serializers/serialization.h"
#include "third_party/blink/renderer/core/events/progress_event.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
+#include "third_party/blink/renderer/core/fetch/trust_token_issuance_authorization.h"
#include "third_party/blink/renderer/core/fetch/trust_token_to_mojom.h"
#include "third_party/blink/renderer/core/fileapi/blob.h"
#include "third_party/blink/renderer/core/fileapi/file.h"
@@ -56,6 +58,7 @@
#include "third_party/blink/renderer/core/frame/csp/content_security_policy.h"
#include "third_party/blink/renderer/core/frame/deprecation.h"
#include "third_party/blink/renderer/core/frame/frame.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/settings.h"
#include "third_party/blink/renderer/core/html/forms/form_data.h"
#include "third_party/blink/renderer/core/html/html_document.h"
@@ -307,7 +310,8 @@ XMLHttpRequest::~XMLHttpRequest() {
}
Document* XMLHttpRequest::GetDocument() const {
- return Document::From(GetExecutionContext());
+ DCHECK(IsA<LocalDOMWindow>(GetExecutionContext()));
+ return To<LocalDOMWindow>(GetExecutionContext())->document();
}
XMLHttpRequest::State XMLHttpRequest::readyState() const {
@@ -1155,7 +1159,7 @@ void XMLHttpRequest::CreateRequest(scoped_refptr<EncodedFormData> http_body,
resource_loader_options);
loader_->SetTimeout(timeout_);
base::TimeTicks start_time = base::TimeTicks::Now();
- loader_->Start(request);
+ loader_->Start(std::move(request));
if (!async_) {
base::TimeDelta blocking_time = base::TimeTicks::Now() - start_time;
@@ -1473,6 +1477,17 @@ void XMLHttpRequest::setTrustToken(const TrustToken* trust_token,
return;
}
+ if (params->type ==
+ network::mojom::blink::TrustTokenOperationType::kIssuance &&
+ !IsTrustTokenIssuanceAvailableInExecutionContext(
+ *GetExecutionContext())) {
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kNotAllowedError,
+ "Trust Tokens issuance is disabled except in "
+ "contexts with the TrustTokens Origin Trial enabled.");
+ return;
+ }
+
trust_token_params_ = std::move(params);
}
@@ -1694,6 +1709,12 @@ void XMLHttpRequest::DidFail(const ResourceError& error) {
return;
}
+ if (error.TrustTokenOperationError() !=
+ network::mojom::TrustTokenOperationStatus::kOk) {
+ trust_token_operation_error_ =
+ TrustTokenErrorToDOMException(error.TrustTokenOperationError());
+ }
+
HandleNetworkError();
}
@@ -2082,6 +2103,7 @@ void XMLHttpRequest::Trace(Visitor* visitor) {
visitor->Trace(upload_);
visitor->Trace(blob_loader_);
visitor->Trace(response_text_);
+ visitor->Trace(trust_token_operation_error_);
XMLHttpRequestEventTarget::Trace(visitor);
ThreadableLoaderClient::Trace(visitor);
DocumentParserClient::Trace(visitor);
diff --git a/chromium/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.h b/chromium/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.h
index 438c6da55f3..bd835627bf1 100644
--- a/chromium/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.h
+++ b/chromium/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.h
@@ -30,9 +30,10 @@
#include "services/network/public/mojom/trust_tokens.mojom-blink.h"
#include "services/network/public/mojom/url_loader_factory.mojom-blink.h"
#include "third_party/blink/renderer/bindings/core/v8/active_script_wrappable.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_trust_token.h"
#include "third_party/blink/renderer/core/dom/document_parser_client.h"
+#include "third_party/blink/renderer/core/dom/dom_exception.h"
#include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.h"
-#include "third_party/blink/renderer/core/fetch/trust_token.h"
#include "third_party/blink/renderer/core/loader/threadable_loader_client.h"
#include "third_party/blink/renderer/core/probe/async_task_id.h"
#include "third_party/blink/renderer/core/xmlhttprequest/xml_http_request_event_target.h"
@@ -159,6 +160,9 @@ class XMLHttpRequest final : public XMLHttpRequestEventTarget,
String responseType();
void setResponseType(const String&, ExceptionState&);
String responseURL();
+ DOMException* trustTokenOperationError() const {
+ return trust_token_operation_error_;
+ }
// For Inspector.
void SendForInspectorXHRReplay(scoped_refptr<EncodedFormData>,
@@ -303,6 +307,7 @@ class XMLHttpRequest final : public XMLHttpRequestEventTarget,
AtomicString method_;
HTTPHeaderMap request_headers_;
network::mojom::blink::TrustTokenParamsPtr trust_token_params_;
+ Member<DOMException> trust_token_operation_error_;
// Not converted to ASCII lowercase. Must be lowered later or compared
// using case insensitive comparison functions if needed.
AtomicString mime_type_override_;
diff --git a/chromium/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.idl b/chromium/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.idl
index a17a33b0793..53f65e0d104 100644
--- a/chromium/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.idl
+++ b/chromium/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.idl
@@ -57,7 +57,7 @@ enum XMLHttpRequestResponseType {
[RaisesException] void open(ByteString method, USVString url);
[RaisesException] void open(ByteString method, USVString url, boolean async, optional USVString? username = null, optional USVString? password = null);
[RaisesException] void setRequestHeader(ByteString name, ByteString value);
- [RaisesException, RuntimeEnabled=TrustTokens, SecureContext] void setTrustToken(TrustToken trustToken);
+ [RaisesException, RuntimeEnabled=TrustTokens, SecureContext, MeasureAs=TrustTokenXhr] void setTrustToken(TrustToken trustToken);
[RaisesException=Setter] attribute unsigned long timeout;
[RaisesException=Setter] attribute boolean withCredentials;
readonly attribute XMLHttpRequestUpload upload;
@@ -78,4 +78,5 @@ enum XMLHttpRequestResponseType {
[Custom=Getter, RaisesException=Getter] readonly attribute USVString responseText;
// TODO(foolip): responseXML should be [Exposed=Window].
[MeasureAs=XMLHttpRequestResponseXML, RaisesException=Getter] readonly attribute Document? responseXML;
+ [RuntimeEnabled=TrustTokens, SecureContext] readonly attribute DOMException trustTokenOperationError;
};